Added "Use High Quality Audio" check box in settings dialog (this changes the CELT bit rate actually)

This commit is contained in:
Volker Fischer 2009-08-15 20:37:18 +00:00
parent 9b2c0b13aa
commit cb097793f0
6 changed files with 713 additions and 636 deletions

View File

@ -37,7 +37,9 @@ CClient::CClient ( const quint16 iPortNumber ) :
bOpenChatOnNewMessage ( true ), bOpenChatOnNewMessage ( true ),
bDoAutoSockBufSize ( true ), bDoAutoSockBufSize ( true ),
iSndCrdPrefFrameSizeFactor ( FRAME_SIZE_FACTOR_DEFAULT ), iSndCrdPrefFrameSizeFactor ( FRAME_SIZE_FACTOR_DEFAULT ),
iSndCrdFrameSizeFactor ( FRAME_SIZE_FACTOR_DEFAULT ) iSndCrdFrameSizeFactor ( FRAME_SIZE_FACTOR_DEFAULT ),
iCeltNumCodedBytes ( CELT_NUM_BYTES_NORMAL_QUALITY ),
bCeltDoHighQuality ( false )
{ {
// init audio endocder/decoder (mono) // init audio endocder/decoder (mono)
CeltMode = celt_mode_create ( CeltMode = celt_mode_create (
@ -157,7 +159,7 @@ bool CClient::SetServerAddr ( QString strNAddr )
void CClient::SetSndCrdPrefFrameSizeFactor ( const int iNewFactor ) void CClient::SetSndCrdPrefFrameSizeFactor ( const int iNewFactor )
{ {
// right now we simply set the internal value // first check new input parameter
if ( ( iNewFactor == FRAME_SIZE_FACTOR_PREFERRED ) || if ( ( iNewFactor == FRAME_SIZE_FACTOR_PREFERRED ) ||
( iNewFactor == FRAME_SIZE_FACTOR_DEFAULT ) || ( iNewFactor == FRAME_SIZE_FACTOR_DEFAULT ) ||
( iNewFactor == FRAME_SIZE_FACTOR_SAFE ) ) ( iNewFactor == FRAME_SIZE_FACTOR_SAFE ) )
@ -183,6 +185,28 @@ void CClient::SetSndCrdPrefFrameSizeFactor ( const int iNewFactor )
} }
} }
void CClient::SetCELTHighQuality ( const bool bNCeltHighQualityFlag )
{
// init with new parameter, if client was running then first
// stop it and restart again after new initialization
const bool bWasRunning = Sound.IsRunning();
if ( bWasRunning )
{
Sound.Stop();
}
// set new parameter
bCeltDoHighQuality = bNCeltHighQualityFlag;
// init with new block size index parameter
Init();
if ( bWasRunning )
{
Sound.Start();
}
}
QString CClient::SetSndCrdDev ( const int iNewDev ) QString CClient::SetSndCrdDev ( const int iNewDev )
{ {
// if client was running then first // if client was running then first
@ -289,7 +313,6 @@ void CClient::Init()
iSndCrdFrameSizeFactor = iMonoBlockSizeSam / SYSTEM_FRAME_SIZE_SAMPLES; iSndCrdFrameSizeFactor = iMonoBlockSizeSam / SYSTEM_FRAME_SIZE_SAMPLES;
vecsAudioSndCrdMono.Init ( iMonoBlockSizeSam ); vecsAudioSndCrdMono.Init ( iMonoBlockSizeSam );
vecsAudioSndCrdStereo.Init ( iStereoBlockSizeSam ); vecsAudioSndCrdStereo.Init ( iStereoBlockSizeSam );
vecdAudioStereo.Init ( iStereoBlockSizeSam ); vecdAudioStereo.Init ( iStereoBlockSizeSam );
@ -303,10 +326,15 @@ iSndCrdFrameSizeFactor = iMonoBlockSizeSam / SYSTEM_FRAME_SIZE_SAMPLES;
// init reverberation // init reverberation
AudioReverb.Init ( SYSTEM_SAMPLE_RATE ); AudioReverb.Init ( SYSTEM_SAMPLE_RATE );
// 22: low/normal quality 150 kbsp (128) / 108 kbps (256) // inits for CELT coding
// 44: high quality 216 kbps (128) / 174 kbps (256) if ( bCeltDoHighQuality )
iCeltNumCodedBytes = 22; {
iCeltNumCodedBytes = CELT_NUM_BYTES_HIGH_QUALITY;
}
else
{
iCeltNumCodedBytes = CELT_NUM_BYTES_NORMAL_QUALITY;
}
vecCeltData.Init ( iCeltNumCodedBytes ); vecCeltData.Init ( iCeltNumCodedBytes );
// init network buffers // init network buffers

View File

@ -1,206 +1,216 @@
/******************************************************************************\ /******************************************************************************\
* Copyright (c) 2004-2009 * Copyright (c) 2004-2009
* *
* Author(s): * Author(s):
* Volker Fischer * Volker Fischer
* *
****************************************************************************** ******************************************************************************
* *
* This program is free software; you can redistribute it and/or modify it under * 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 * 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 * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * 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 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* *
* You should have received a copy of the GNU General Public License along with * 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., * this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
\******************************************************************************/ \******************************************************************************/
#if !defined ( CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) #if !defined ( CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ )
#define CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ #define CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_
#include <qglobal.h> #include <qglobal.h>
#include <qhostaddress.h> #include <qhostaddress.h>
#include <qhostinfo.h> #include <qhostinfo.h>
#include <qstring.h> #include <qstring.h>
#include <qdatetime.h> #include <qdatetime.h>
#include <qmessagebox.h> #include <qmessagebox.h>
#include "celt.h" #include "celt.h"
#include "global.h" #include "global.h"
#include "socket.h" #include "socket.h"
#include "channel.h" #include "channel.h"
#include "util.h" #include "util.h"
#ifdef _WIN32 #ifdef _WIN32
# include "../windows/sound.h" # include "../windows/sound.h"
#else #else
# include "../linux/sound.h" # include "../linux/sound.h"
# include <sched.h> # include <sched.h>
# include <socket.h> # include <socket.h>
# include <netdb.h> # include <netdb.h>
#endif #endif
/* Definitions ****************************************************************/ /* Definitions ****************************************************************/
// audio in fader range // audio in fader range
#define AUD_FADER_IN_MIN 0 #define AUD_FADER_IN_MIN 0
#define AUD_FADER_IN_MAX 100 #define AUD_FADER_IN_MAX 100
#define AUD_FADER_IN_MIDDLE ( AUD_FADER_IN_MAX / 2 ) #define AUD_FADER_IN_MIDDLE ( AUD_FADER_IN_MAX / 2 )
// audio reverberation range // audio reverberation range
#define AUD_REVERB_MAX 100 #define AUD_REVERB_MAX 100
// CELT number of coded bytes per audio packet
/* Classes ********************************************************************/ // 22: low/normal quality 150 kbsp (128) / 108 kbps (256)
class CClient : public QObject // 44: high quality 216 kbps (128) / 174 kbps (256)
{ #define CELT_NUM_BYTES_NORMAL_QUALITY 22
Q_OBJECT #define CELT_NUM_BYTES_HIGH_QUALITY 44
public:
CClient ( const quint16 iPortNumber ); /* Classes ********************************************************************/
virtual ~CClient() {} class CClient : public QObject
{
void Start(); Q_OBJECT
void Stop();
bool IsRunning() { return Sound.IsRunning(); } public:
bool SetServerAddr ( QString strNAddr ); CClient ( const quint16 iPortNumber );
double MicLevelL() { return SignalLevelMeter.MicLevelLeft(); } virtual ~CClient() {}
double MicLevelR() { return SignalLevelMeter.MicLevelRight(); }
bool IsConnected() { return Channel.IsConnected(); } void Start();
void Stop();
double GetTimingStdDev() { return CycleTimeVariance.GetStdDev(); } bool IsRunning() { return Sound.IsRunning(); }
bool SetServerAddr ( QString strNAddr );
bool GetOpenChatOnNewMessage() { return bOpenChatOnNewMessage; } double MicLevelL() { return SignalLevelMeter.MicLevelLeft(); }
void SetOpenChatOnNewMessage ( const bool bNV ) { bOpenChatOnNewMessage = bNV; } double MicLevelR() { return SignalLevelMeter.MicLevelRight(); }
bool IsConnected() { return Channel.IsConnected(); }
int GetAudioInFader() { return iAudioInFader; }
void SetAudioInFader ( const int iNV ) { iAudioInFader = iNV; } double GetTimingStdDev() { return CycleTimeVariance.GetStdDev(); }
int GetReverbLevel() { return iReverbLevel; } bool GetOpenChatOnNewMessage() { return bOpenChatOnNewMessage; }
void SetReverbLevel ( const int iNL ) { iReverbLevel = iNL; } void SetOpenChatOnNewMessage ( const bool bNV ) { bOpenChatOnNewMessage = bNV; }
bool IsReverbOnLeftChan() { return bReverbOnLeftChan; } bool GetCELTHighQuality() { return bCeltDoHighQuality; }
void SetReverbOnLeftChan ( const bool bIL ) void SetCELTHighQuality ( const bool bNCeltHighQualityFlag );
{
bReverbOnLeftChan = bIL; int GetAudioInFader() { return iAudioInFader; }
AudioReverb.Clear(); void SetAudioInFader ( const int iNV ) { iAudioInFader = iNV; }
}
int GetReverbLevel() { return iReverbLevel; }
void SetDoAutoSockBufSize ( const bool bValue ) { bDoAutoSockBufSize = bValue; } void SetReverbLevel ( const int iNL ) { iReverbLevel = iNL; }
bool GetDoAutoSockBufSize() { return bDoAutoSockBufSize; }
void SetSockBufNumFrames ( const int iNumBlocks ) bool IsReverbOnLeftChan() { return bReverbOnLeftChan; }
{ void SetReverbOnLeftChan ( const bool bIL )
// only change parameter if new parameter is different from current one {
if ( Channel.GetSockBufNumFrames() != iNumBlocks ) bReverbOnLeftChan = bIL;
{ AudioReverb.Clear();
// set the new socket size (number of frames) }
if ( !Channel.SetSockBufNumFrames ( iNumBlocks ) )
{ void SetDoAutoSockBufSize ( const bool bValue ) { bDoAutoSockBufSize = bValue; }
// if setting of socket buffer size was successful, bool GetDoAutoSockBufSize() { return bDoAutoSockBufSize; }
// tell the server that size has changed void SetSockBufNumFrames ( const int iNumBlocks )
Channel.CreateJitBufMes ( iNumBlocks ); {
} // only change parameter if new parameter is different from current one
} if ( Channel.GetSockBufNumFrames() != iNumBlocks )
} {
int GetSockBufNumFrames() { return Channel.GetSockBufNumFrames(); } // set the new socket size (number of frames)
if ( !Channel.SetSockBufNumFrames ( iNumBlocks ) )
int GetUploadRateKbps() { return Channel.GetUploadRateKbps(); } {
// if setting of socket buffer size was successful,
int GetSndCrdNumDev() { return Sound.GetNumDev(); } // tell the server that size has changed
std::string GetSndCrdDeviceName ( const int iDiD ) Channel.CreateJitBufMes ( iNumBlocks );
{ return Sound.GetDeviceName ( iDiD ); } }
}
QString SetSndCrdDev ( const int iNewDev ); }
int GetSndCrdDev() { return Sound.GetDev(); } int GetSockBufNumFrames() { return Channel.GetSockBufNumFrames(); }
void OpenSndCrdDriverSetup() { Sound.OpenDriverSetup(); }
int GetUploadRateKbps() { return Channel.GetUploadRateKbps(); }
void SetSndCrdPrefFrameSizeFactor ( const int iNewFactor );
int GetSndCrdPrefFrameSizeFactor() int GetSndCrdNumDev() { return Sound.GetNumDev(); }
{ return iSndCrdPrefFrameSizeFactor; } std::string GetSndCrdDeviceName ( const int iDiD )
int GetSndCrdActualMonoBlSize() { return iMonoBlockSizeSam; } { return Sound.GetDeviceName ( iDiD ); }
void SetRemoteChanGain ( const int iId, const double dGain ) QString SetSndCrdDev ( const int iNewDev );
{ Channel.SetRemoteChanGain ( iId, dGain ); } int GetSndCrdDev() { return Sound.GetDev(); }
void OpenSndCrdDriverSetup() { Sound.OpenDriverSetup(); }
void SetRemoteName() { Channel.SetRemoteName ( strName ); }
void SetSndCrdPrefFrameSizeFactor ( const int iNewFactor );
void SendTextMess ( const QString& strChatText ) int GetSndCrdPrefFrameSizeFactor()
{ Channel.CreateChatTextMes ( strChatText ); } { return iSndCrdPrefFrameSizeFactor; }
int GetSndCrdActualMonoBlSize() { return iMonoBlockSizeSam; }
void SendPingMess()
{ Channel.CreatePingMes ( PreciseTime.elapsed() ); }; void SetRemoteChanGain ( const int iId, const double dGain )
{ Channel.SetRemoteChanGain ( iId, dGain ); }
CChannel* GetChannel() { return &Channel; }
void SetRemoteName() { Channel.SetRemoteName ( strName ); }
// settings void SendTextMess ( const QString& strChatText )
CVector<QString> vstrIPAddress; { Channel.CreateChatTextMes ( strChatText ); }
QString strName;
void SendPingMess()
protected: { Channel.CreatePingMes ( PreciseTime.elapsed() ); };
// callback function must be static, otherwise it does not work
static void AudioCallback ( CVector<short>& psData, void* arg ); CChannel* GetChannel() { return &Channel; }
void Init();
void ProcessAudioData ( CVector<short>& vecsStereoSndCrd ); // settings
void UpdateSocketBufferSize(); CVector<QString> vstrIPAddress;
QString strName;
// only one channel is needed for client application
CChannel Channel; protected:
bool bDoAutoSockBufSize; // callback function must be static, otherwise it does not work
static void AudioCallback ( CVector<short>& psData, void* arg );
// audio encoder/decoder
CELTMode* CeltMode; void Init();
CELTEncoder* CeltEncoder; void ProcessAudioData ( CVector<short>& vecsStereoSndCrd );
CELTDecoder* CeltDecoder; void UpdateSocketBufferSize();
int iCeltNumCodedBytes;
CVector<unsigned char> vecCeltData; // only one channel is needed for client application
CChannel Channel;
CSocket Socket; bool bDoAutoSockBufSize;
CSound Sound;
CStereoSignalLevelMeter SignalLevelMeter; // audio encoder/decoder
CELTMode* CeltMode;
CVector<uint8_t> vecbyNetwData; CELTEncoder* CeltEncoder;
CELTDecoder* CeltDecoder;
int iAudioInFader; int iCeltNumCodedBytes;
bool bReverbOnLeftChan; bool bCeltDoHighQuality;
int iReverbLevel; CVector<unsigned char> vecCeltData;
CAudioReverb AudioReverb;
CSocket Socket;
int iSndCrdPrefFrameSizeFactor; CSound Sound;
int iSndCrdFrameSizeFactor; CStereoSignalLevelMeter SignalLevelMeter;
int iMonoBlockSizeSam; CVector<uint8_t> vecbyNetwData;
int iStereoBlockSizeSam;
int iAudioInFader;
bool bOpenChatOnNewMessage; bool bReverbOnLeftChan;
int iReverbLevel;
CVector<int16_t> vecsAudioSndCrdMono; CAudioReverb AudioReverb;
CVector<int16_t> vecsAudioSndCrdStereo;
CVector<double> vecdAudioStereo; int iSndCrdPrefFrameSizeFactor;
CVector<int16_t> vecsNetwork; int iSndCrdFrameSizeFactor;
// for ping measurement int iMonoBlockSizeSam;
CPreciseTime PreciseTime; int iStereoBlockSizeSam;
CCycleTimeVariance CycleTimeVariance; bool bOpenChatOnNewMessage;
public slots: CVector<int16_t> vecsAudioSndCrdMono;
void OnSendProtMessage ( CVector<uint8_t> vecMessage ); CVector<int16_t> vecsAudioSndCrdStereo;
void OnReqJittBufSize(); CVector<double> vecdAudioStereo;
void OnNewConnection(); CVector<int16_t> vecsNetwork;
void OnReceivePingMessage ( int iMs );
void OnSndCrdReinitRequest(); // for ping measurement
CPreciseTime PreciseTime;
signals:
void ConClientListMesReceived ( CVector<CChannelShortInfo> vecChanInfo ); CCycleTimeVariance CycleTimeVariance;
void ChatTextReceived ( QString strChatText );
void PingTimeReceived ( int iPingTime ); public slots:
}; void OnSendProtMessage ( CVector<uint8_t> vecMessage );
void OnReqJittBufSize();
#endif /* !defined ( CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) */ void OnNewConnection();
void OnReceivePingMessage ( int iMs );
void OnSndCrdReinitRequest();
signals:
void ConClientListMesReceived ( CVector<CChannelShortInfo> vecChanInfo );
void ChatTextReceived ( QString strChatText );
void PingTimeReceived ( int iPingTime );
};
#endif /* !defined ( CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) */

View File

@ -83,6 +83,16 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
cbOpenChatOnNewMessage->setCheckState ( Qt::Unchecked ); cbOpenChatOnNewMessage->setCheckState ( Qt::Unchecked );
} }
// "High Quality Audio" check box
if ( pClient->GetCELTHighQuality() )
{
cbUseHighQualityAudio->setCheckState ( Qt::Checked );
}
else
{
cbUseHighQualityAudio->setCheckState ( Qt::Unchecked );
}
// set text for sound card buffer delay radio buttons // set text for sound card buffer delay radio buttons
rButBufferDelayPreferred->setText ( GenSndCrdBufferDelayString ( rButBufferDelayPreferred->setText ( GenSndCrdBufferDelayString (
FRAME_SIZE_FACTOR_PREFERRED * SYSTEM_FRAME_SIZE_SAMPLES, FRAME_SIZE_FACTOR_PREFERRED * SYSTEM_FRAME_SIZE_SAMPLES,
@ -117,6 +127,8 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
// check boxes // check boxes
QObject::connect ( cbOpenChatOnNewMessage, SIGNAL ( stateChanged ( int ) ), QObject::connect ( cbOpenChatOnNewMessage, SIGNAL ( stateChanged ( int ) ),
this, SLOT ( OnOpenChatOnNewMessageStateChanged ( int ) ) ); this, SLOT ( OnOpenChatOnNewMessageStateChanged ( int ) ) );
QObject::connect ( cbUseHighQualityAudio, SIGNAL ( stateChanged ( int ) ),
this, SLOT ( OnUseHighQualityAudioStateChanged ( int ) ) );
QObject::connect ( cbAutoJitBuf, SIGNAL ( stateChanged ( int ) ), QObject::connect ( cbAutoJitBuf, SIGNAL ( stateChanged ( int ) ),
this, SLOT ( OnAutoJitBuf ( int ) ) ); this, SLOT ( OnAutoJitBuf ( int ) ) );
@ -269,6 +281,12 @@ void CClientSettingsDlg::OnOpenChatOnNewMessageStateChanged ( int value )
UpdateDisplay(); UpdateDisplay();
} }
void CClientSettingsDlg::OnUseHighQualityAudioStateChanged ( int value )
{
pClient->SetCELTHighQuality ( value == Qt::Checked );
UpdateDisplay();
}
void CClientSettingsDlg::OnSndCrdBufferDelayButtonGroupClicked ( QAbstractButton* button ) void CClientSettingsDlg::OnSndCrdBufferDelayButtonGroupClicked ( QAbstractButton* button )
{ {
if ( button == rButBufferDelayPreferred ) if ( button == rButBufferDelayPreferred )

View File

@ -1,90 +1,91 @@
/******************************************************************************\ /******************************************************************************\
* Copyright (c) 2004-2009 * Copyright (c) 2004-2009
* *
* Author(s): * Author(s):
* Volker Fischer * Volker Fischer
* *
****************************************************************************** ******************************************************************************
* *
* This program is free software; you can redistribute it and/or modify it under * 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 * 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 * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * 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 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* *
* You should have received a copy of the GNU General Public License along with * 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., * this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
\******************************************************************************/ \******************************************************************************/
#include <qlabel.h> #include <qlabel.h>
#include <qstring.h> #include <qstring.h>
#include <qlineedit.h> #include <qlineedit.h>
#include <qpushbutton.h> #include <qpushbutton.h>
#include <qprogressbar.h> #include <qprogressbar.h>
#include <qwhatsthis.h> #include <qwhatsthis.h>
#include <qtimer.h> #include <qtimer.h>
#include <qslider.h> #include <qslider.h>
#include <qradiobutton.h> #include <qradiobutton.h>
#include <qmenubar.h> #include <qmenubar.h>
#include <qlayout.h> #include <qlayout.h>
#include <qbuttongroup.h> #include <qbuttongroup.h>
#include "global.h" #include "global.h"
#include "client.h" #include "client.h"
#include "multicolorled.h" #include "multicolorled.h"
#ifdef _WIN32 #ifdef _WIN32
# include "../windows/moc/clientsettingsdlgbase.h" # include "../windows/moc/clientsettingsdlgbase.h"
#else #else
# include "moc/clientsettingsdlgbase.h" # include "moc/clientsettingsdlgbase.h"
#endif #endif
/* Definitions ****************************************************************/ /* Definitions ****************************************************************/
// update time for GUI controls // update time for GUI controls
#define DISPLAY_UPDATE_TIME 1000 // ms #define DISPLAY_UPDATE_TIME 1000 // ms
#define PING_UPDATE_TIME 500 // ms #define PING_UPDATE_TIME 500 // ms
/* Classes ********************************************************************/ /* Classes ********************************************************************/
class CClientSettingsDlg : public QDialog, private Ui_CClientSettingsDlgBase class CClientSettingsDlg : public QDialog, private Ui_CClientSettingsDlgBase
{ {
Q_OBJECT Q_OBJECT
public: public:
CClientSettingsDlg ( CClient* pNCliP, QWidget* parent = 0, CClientSettingsDlg ( CClient* pNCliP, QWidget* parent = 0,
Qt::WindowFlags f = 0 ); Qt::WindowFlags f = 0 );
void SetStatus ( const int iMessType, const int iStatus ); void SetStatus ( const int iMessType, const int iStatus );
protected: protected:
void UpdateJitterBufferFrame(); void UpdateJitterBufferFrame();
void UpdateSoundCardFrame(); void UpdateSoundCardFrame();
QString GenSndCrdBufferDelayString ( const int iFrameSize, QString GenSndCrdBufferDelayString ( const int iFrameSize,
const QString strAddText = "" ); const QString strAddText = "" );
virtual void showEvent ( QShowEvent* showEvent ); virtual void showEvent ( QShowEvent* showEvent );
virtual void hideEvent ( QHideEvent* hideEvent ); virtual void hideEvent ( QHideEvent* hideEvent );
CClient* pClient; CClient* pClient;
QTimer TimerStatus; QTimer TimerStatus;
QTimer TimerPing; QTimer TimerPing;
QButtonGroup SndCrdBufferDelayButtonGroup; QButtonGroup SndCrdBufferDelayButtonGroup;
void UpdateDisplay(); void UpdateDisplay();
public slots: public slots:
void OnTimerStatus() { UpdateDisplay(); } void OnTimerStatus() { UpdateDisplay(); }
void OnTimerPing(); void OnTimerPing();
void OnSliderNetBuf ( int value ); void OnSliderNetBuf ( int value );
void OnSliderSndCrdBufferDelay ( int value ); void OnSliderSndCrdBufferDelay ( int value );
void OnAutoJitBuf ( int value ); void OnAutoJitBuf ( int value );
void OnOpenChatOnNewMessageStateChanged ( int value ); void OnOpenChatOnNewMessageStateChanged ( int value );
void OnSndCrdBufferDelayButtonGroupClicked ( QAbstractButton* button ); void OnUseHighQualityAudioStateChanged ( int value );
void OnPingTimeResult ( int iPingTime ); void OnSndCrdBufferDelayButtonGroupClicked ( QAbstractButton* button );
void OnSoundCrdSelection ( int iSndDevIdx ); void OnPingTimeResult ( int iPingTime );
void OnDriverSetupBut(); void OnSoundCrdSelection ( int iSndDevIdx );
}; void OnDriverSetupBut();
};

View File

@ -297,7 +297,17 @@
<item> <item>
<widget class="QCheckBox" name="cbOpenChatOnNewMessage" > <widget class="QCheckBox" name="cbOpenChatOnNewMessage" >
<property name="text" > <property name="text" >
<string>Open chat on new message</string> <string>Open Chat on New Message</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbUseHighQualityAudio" >
<property name="windowModality" >
<enum>Qt::NonModal</enum>
</property>
<property name="text" >
<string>Use High Quality Audio</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -309,7 +319,7 @@
<property name="sizeHint" > <property name="sizeHint" >
<size> <size>
<width>201</width> <width>201</width>
<height>16</height> <height>41</height>
</size> </size>
</property> </property>
</spacer> </spacer>

View File

@ -1,331 +1,341 @@
/******************************************************************************\ /******************************************************************************\
* Copyright (c) 2004-2009 * Copyright (c) 2004-2009
* *
* Author(s): * Author(s):
* Volker Fischer * Volker Fischer
* *
****************************************************************************** ******************************************************************************
* *
* This program is free software; you can redistribute it and/or modify it under * 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 * 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 * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * 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 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* *
* You should have received a copy of the GNU General Public License along with * 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., * this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
\******************************************************************************/ \******************************************************************************/
#include "settings.h" #include "settings.h"
/* Implementation *************************************************************/ /* Implementation *************************************************************/
void CSettings::ReadIniFile ( const QString& sFileName ) void CSettings::ReadIniFile ( const QString& sFileName )
{ {
int iValue; int iValue;
bool bValue; bool bValue;
QDomDocument IniXMLDocument; QDomDocument IniXMLDocument;
// load data from init-file // load data from init-file
// prepare file name for loading initialization data from XML file // prepare file name for loading initialization data from XML file
QString sCurFileName = sFileName; QString sCurFileName = sFileName;
if ( sCurFileName.isEmpty() ) if ( sCurFileName.isEmpty() )
{ {
// if no file name is available, use default file name // if no file name is available, use default file name
sCurFileName = LLCON_INIT_FILE_NAME; sCurFileName = LLCON_INIT_FILE_NAME;
} }
// read data from file if possible // read data from file if possible
QFile file ( sCurFileName ); QFile file ( sCurFileName );
if ( file.open ( QIODevice::ReadOnly ) ) if ( file.open ( QIODevice::ReadOnly ) )
{ {
QTextStream in ( &file ); QTextStream in ( &file );
IniXMLDocument.setContent ( in.readAll(), false ); IniXMLDocument.setContent ( in.readAll(), false );
file.close(); file.close();
} }
// actual settings data --------------------------------------------------- // actual settings data ---------------------------------------------------
// IP addresses // IP addresses
for ( int iIPAddrIdx = 0; iIPAddrIdx < MAX_NUM_SERVER_ADDR_ITEMS; iIPAddrIdx++ ) for ( int iIPAddrIdx = 0; iIPAddrIdx < MAX_NUM_SERVER_ADDR_ITEMS; iIPAddrIdx++ )
{ {
QString sDefaultIP = ""; QString sDefaultIP = "";
// use default only for first entry // use default only for first entry
if ( iIPAddrIdx == 0 ) if ( iIPAddrIdx == 0 )
{ {
sDefaultIP = DEFAULT_SERVER_ADDRESS; sDefaultIP = DEFAULT_SERVER_ADDRESS;
} }
pClient->vstrIPAddress[iIPAddrIdx] = pClient->vstrIPAddress[iIPAddrIdx] =
GetIniSetting ( IniXMLDocument, "client", GetIniSetting ( IniXMLDocument, "client",
QString ( "ipaddress%1" ).arg ( iIPAddrIdx ), sDefaultIP ); QString ( "ipaddress%1" ).arg ( iIPAddrIdx ), sDefaultIP );
} }
// name // name
pClient->strName = GetIniSetting ( IniXMLDocument, "client", "name" ); pClient->strName = GetIniSetting ( IniXMLDocument, "client", "name" );
// audio fader // audio fader
if ( GetNumericIniSet ( IniXMLDocument, "client", "audfad", if ( GetNumericIniSet ( IniXMLDocument, "client", "audfad",
AUD_FADER_IN_MIN, AUD_FADER_IN_MAX, iValue ) ) AUD_FADER_IN_MIN, AUD_FADER_IN_MAX, iValue ) )
{ {
pClient->SetAudioInFader ( iValue ); pClient->SetAudioInFader ( iValue );
} }
// reverberation level // reverberation level
if ( GetNumericIniSet ( IniXMLDocument, "client", "revlev", if ( GetNumericIniSet ( IniXMLDocument, "client", "revlev",
0, AUD_REVERB_MAX, iValue ) ) 0, AUD_REVERB_MAX, iValue ) )
{ {
pClient->SetReverbLevel ( iValue ); pClient->SetReverbLevel ( iValue );
} }
// reverberation channel assignment // reverberation channel assignment
if ( GetFlagIniSet ( IniXMLDocument, "client", "reverblchan", bValue ) ) if ( GetFlagIniSet ( IniXMLDocument, "client", "reverblchan", bValue ) )
{ {
pClient->SetReverbOnLeftChan ( bValue ); pClient->SetReverbOnLeftChan ( bValue );
} }
// sound card selection // sound card selection
// special case with this setting: the sound card initialization depends on this setting // special case with this setting: the sound card initialization depends on this setting
// call, therefore, if no setting file parameter could be retrieved, the sound card is // call, therefore, if no setting file parameter could be retrieved, the sound card is
// initialized with a default setting defined here // initialized with a default setting defined here
if ( GetNumericIniSet ( IniXMLDocument, "client", "auddevidx", if ( GetNumericIniSet ( IniXMLDocument, "client", "auddevidx",
1, MAX_NUMBER_SOUND_CARDS, iValue ) ) 1, MAX_NUMBER_SOUND_CARDS, iValue ) )
{ {
pClient->SetSndCrdDev ( iValue ); pClient->SetSndCrdDev ( iValue );
} }
else else
{ {
// use "INVALID_SNC_CARD_DEVICE" to tell the sound card driver that no // use "INVALID_SNC_CARD_DEVICE" to tell the sound card driver that no
// device selection was done previously // device selection was done previously
pClient->SetSndCrdDev ( INVALID_SNC_CARD_DEVICE ); pClient->SetSndCrdDev ( INVALID_SNC_CARD_DEVICE );
} }
// sound card preferred buffer size index // sound card preferred buffer size index
if ( GetNumericIniSet ( IniXMLDocument, "client", "prefsndcrdbufidx", if ( GetNumericIniSet ( IniXMLDocument, "client", "prefsndcrdbufidx",
FRAME_SIZE_FACTOR_PREFERRED, FRAME_SIZE_FACTOR_SAFE, iValue ) ) FRAME_SIZE_FACTOR_PREFERRED, FRAME_SIZE_FACTOR_SAFE, iValue ) )
{ {
// additional check required since only a subset of factors are // additional check required since only a subset of factors are
// defined // defined
if ( ( iValue == FRAME_SIZE_FACTOR_PREFERRED ) || if ( ( iValue == FRAME_SIZE_FACTOR_PREFERRED ) ||
( iValue == FRAME_SIZE_FACTOR_DEFAULT ) || ( iValue == FRAME_SIZE_FACTOR_DEFAULT ) ||
( iValue == FRAME_SIZE_FACTOR_SAFE ) ) ( iValue == FRAME_SIZE_FACTOR_SAFE ) )
{ {
pClient->SetSndCrdPrefFrameSizeFactor ( iValue ); pClient->SetSndCrdPrefFrameSizeFactor ( iValue );
} }
} }
// automatic network jitter buffer size setting // automatic network jitter buffer size setting
if ( GetFlagIniSet ( IniXMLDocument, "client", "autojitbuf", bValue ) ) if ( GetFlagIniSet ( IniXMLDocument, "client", "autojitbuf", bValue ) )
{ {
pClient->SetDoAutoSockBufSize ( bValue ); pClient->SetDoAutoSockBufSize ( bValue );
} }
// network jitter buffer size // network jitter buffer size
if ( GetNumericIniSet ( IniXMLDocument, "client", "jitbuf", if ( GetNumericIniSet ( IniXMLDocument, "client", "jitbuf",
MIN_NET_BUF_SIZE_NUM_BL, MAX_NET_BUF_SIZE_NUM_BL, iValue ) ) MIN_NET_BUF_SIZE_NUM_BL, MAX_NET_BUF_SIZE_NUM_BL, iValue ) )
{ {
pClient->SetSockBufNumFrames ( iValue ); pClient->SetSockBufNumFrames ( iValue );
} }
// flag whether the chat window shall be opened on a new chat message // flag whether the chat window shall be opened on a new chat message
if ( GetFlagIniSet ( IniXMLDocument, "client", "openchatonnewmessage", bValue ) ) if ( GetFlagIniSet ( IniXMLDocument, "client", "openchatonnewmessage", bValue ) )
{ {
pClient->SetOpenChatOnNewMessage ( bValue ); pClient->SetOpenChatOnNewMessage ( bValue );
} }
}
// flag whether using high quality audio or not
void CSettings::WriteIniFile ( const QString& sFileName ) if ( GetFlagIniSet ( IniXMLDocument, "client", "highqualityaudio", bValue ) )
{ {
// create XML document for storing initialization parameters pClient->SetCELTHighQuality ( bValue );
QDomDocument IniXMLDocument; }
}
// actual settings data --------------------------------------------------- void CSettings::WriteIniFile ( const QString& sFileName )
// IP addresses {
for ( int iIPAddrIdx = 0; iIPAddrIdx < MAX_NUM_SERVER_ADDR_ITEMS; iIPAddrIdx++ ) // create XML document for storing initialization parameters
{ QDomDocument IniXMLDocument;
PutIniSetting ( IniXMLDocument, "client",
QString ( "ipaddress%1" ).arg ( iIPAddrIdx ),
pClient->vstrIPAddress[iIPAddrIdx] ); // actual settings data ---------------------------------------------------
} // IP addresses
for ( int iIPAddrIdx = 0; iIPAddrIdx < MAX_NUM_SERVER_ADDR_ITEMS; iIPAddrIdx++ )
// name {
PutIniSetting ( IniXMLDocument, "client", "name", PutIniSetting ( IniXMLDocument, "client",
pClient->strName ); QString ( "ipaddress%1" ).arg ( iIPAddrIdx ),
pClient->vstrIPAddress[iIPAddrIdx] );
// audio fader }
SetNumericIniSet ( IniXMLDocument, "client", "audfad",
pClient->GetAudioInFader() ); // name
PutIniSetting ( IniXMLDocument, "client", "name",
// reverberation level pClient->strName );
SetNumericIniSet ( IniXMLDocument, "client", "revlev",
pClient->GetReverbLevel() ); // audio fader
SetNumericIniSet ( IniXMLDocument, "client", "audfad",
// reverberation channel assignment pClient->GetAudioInFader() );
SetFlagIniSet ( IniXMLDocument, "client", "reverblchan",
pClient->IsReverbOnLeftChan() ); // reverberation level
SetNumericIniSet ( IniXMLDocument, "client", "revlev",
// sound card selection pClient->GetReverbLevel() );
SetNumericIniSet ( IniXMLDocument, "client", "auddevidx",
pClient->GetSndCrdDev() ); // reverberation channel assignment
SetFlagIniSet ( IniXMLDocument, "client", "reverblchan",
// sound card preferred buffer size index pClient->IsReverbOnLeftChan() );
SetNumericIniSet ( IniXMLDocument, "client", "prefsndcrdbufidx",
pClient->GetSndCrdPrefFrameSizeFactor() ); // sound card selection
SetNumericIniSet ( IniXMLDocument, "client", "auddevidx",
// automatic network jitter buffer size setting pClient->GetSndCrdDev() );
SetFlagIniSet ( IniXMLDocument, "client", "autojitbuf",
pClient->GetDoAutoSockBufSize() ); // sound card preferred buffer size index
SetNumericIniSet ( IniXMLDocument, "client", "prefsndcrdbufidx",
// network jitter buffer size pClient->GetSndCrdPrefFrameSizeFactor() );
SetNumericIniSet ( IniXMLDocument, "client", "jitbuf",
pClient->GetSockBufNumFrames() ); // automatic network jitter buffer size setting
SetFlagIniSet ( IniXMLDocument, "client", "autojitbuf",
// flag whether the chat window shall be opened on a new chat message pClient->GetDoAutoSockBufSize() );
SetFlagIniSet ( IniXMLDocument, "client", "openchatonnewmessage",
pClient->GetOpenChatOnNewMessage() ); // network jitter buffer size
SetNumericIniSet ( IniXMLDocument, "client", "jitbuf",
// prepare file name for storing initialization data in XML file pClient->GetSockBufNumFrames() );
QString sCurFileName = sFileName;
if ( sCurFileName.isEmpty() ) // flag whether the chat window shall be opened on a new chat message
{ SetFlagIniSet ( IniXMLDocument, "client", "openchatonnewmessage",
// if no file name is available, use default file name pClient->GetOpenChatOnNewMessage() );
sCurFileName = LLCON_INIT_FILE_NAME;
} // flag whether using high quality audio or not
SetFlagIniSet ( IniXMLDocument, "client", "highqualityaudio",
// store XML data in file pClient->GetCELTHighQuality() );
QFile file ( sCurFileName );
if ( file.open ( QIODevice::WriteOnly ) ) // prepare file name for storing initialization data in XML file
{ QString sCurFileName = sFileName;
QTextStream out ( &file ); if ( sCurFileName.isEmpty() )
out << IniXMLDocument.toString(); {
} // if no file name is available, use default file name
} sCurFileName = LLCON_INIT_FILE_NAME;
}
void CSettings::SetNumericIniSet ( QDomDocument& xmlFile, const QString& strSection,
const QString& strKey, const int iValue ) // store XML data in file
{ QFile file ( sCurFileName );
// convert input parameter which is an integer to string and store if ( file.open ( QIODevice::WriteOnly ) )
PutIniSetting ( xmlFile, strSection, strKey, QString("%1").arg(iValue) ); {
} QTextStream out ( &file );
out << IniXMLDocument.toString();
bool CSettings::GetNumericIniSet ( const QDomDocument& xmlFile, const QString& strSection, }
const QString& strKey, const int iRangeStart, }
const int iRangeStop, int& iValue )
{ void CSettings::SetNumericIniSet ( QDomDocument& xmlFile, const QString& strSection,
// init return value const QString& strKey, const int iValue )
bool bReturn = false; {
// convert input parameter which is an integer to string and store
const QString strGetIni = GetIniSetting ( xmlFile, strSection, strKey ); PutIniSetting ( xmlFile, strSection, strKey, QString("%1").arg(iValue) );
}
// check if it is a valid parameter
if ( !strGetIni.isEmpty() ) bool CSettings::GetNumericIniSet ( const QDomDocument& xmlFile, const QString& strSection,
{ const QString& strKey, const int iRangeStart,
// convert string from init file to integer const int iRangeStop, int& iValue )
iValue = strGetIni.toInt(); {
// init return value
// check range bool bReturn = false;
if ( ( iValue >= iRangeStart ) && ( iValue <= iRangeStop ) )
{ const QString strGetIni = GetIniSetting ( xmlFile, strSection, strKey );
bReturn = true;
} // check if it is a valid parameter
} if ( !strGetIni.isEmpty() )
{
return bReturn; // convert string from init file to integer
} iValue = strGetIni.toInt();
void CSettings::SetFlagIniSet ( QDomDocument& xmlFile, const QString& strSection, // check range
const QString& strKey, const bool bValue ) if ( ( iValue >= iRangeStart ) && ( iValue <= iRangeStop ) )
{ {
// we encode true -> "1" and false -> "0" bReturn = true;
if ( bValue == true ) }
{ }
PutIniSetting ( xmlFile, strSection, strKey, "1" );
} return bReturn;
else }
{
PutIniSetting ( xmlFile, strSection, strKey, "0" ); void CSettings::SetFlagIniSet ( QDomDocument& xmlFile, const QString& strSection,
} const QString& strKey, const bool bValue )
} {
// we encode true -> "1" and false -> "0"
bool CSettings::GetFlagIniSet ( const QDomDocument& xmlFile, const QString& strSection, if ( bValue == true )
const QString& strKey, bool& bValue ) {
{ PutIniSetting ( xmlFile, strSection, strKey, "1" );
// init return value }
bool bReturn = false; else
{
const QString strGetIni = GetIniSetting ( xmlFile, strSection, strKey ); PutIniSetting ( xmlFile, strSection, strKey, "0" );
}
if ( !strGetIni.isEmpty() ) }
{
if ( strGetIni.toInt() ) bool CSettings::GetFlagIniSet ( const QDomDocument& xmlFile, const QString& strSection,
{ const QString& strKey, bool& bValue )
bValue = true; {
} // init return value
else bool bReturn = false;
{
bValue = false; const QString strGetIni = GetIniSetting ( xmlFile, strSection, strKey );
}
if ( !strGetIni.isEmpty() )
bReturn = true; {
} if ( strGetIni.toInt() )
{
return bReturn; bValue = true;
} }
else
{
// Init-file routines using XML *********************************************** bValue = false;
QString CSettings::GetIniSetting ( const QDomDocument& xmlFile, const QString& sSection, }
const QString& sKey, const QString& sDefaultVal )
{ bReturn = true;
// init return parameter with default value }
QString sResult ( sDefaultVal );
return bReturn;
// get section }
QDomElement xmlSection = xmlFile.firstChildElement ( sSection );
if ( !xmlSection.isNull() )
{ // Init-file routines using XML ***********************************************
// get key QString CSettings::GetIniSetting ( const QDomDocument& xmlFile, const QString& sSection,
QDomElement xmlKey = xmlSection.firstChildElement ( sKey ); const QString& sKey, const QString& sDefaultVal )
if ( !xmlKey.isNull() ) {
{ // init return parameter with default value
// get value QString sResult ( sDefaultVal );
sResult = xmlKey.text();
} // get section
} QDomElement xmlSection = xmlFile.firstChildElement ( sSection );
if ( !xmlSection.isNull() )
return sResult; {
} // get key
QDomElement xmlKey = xmlSection.firstChildElement ( sKey );
void CSettings::PutIniSetting ( QDomDocument& xmlFile, const QString& sSection, if ( !xmlKey.isNull() )
const QString& sKey, const QString& sValue ) {
{ // get value
// check if section is already there, if not then create it sResult = xmlKey.text();
QDomElement xmlSection = xmlFile.firstChildElement ( sSection ); }
if ( xmlSection.isNull() ) }
{
// create new root element and add to document return sResult;
xmlSection = xmlFile.createElement ( sSection ); }
xmlFile.appendChild ( xmlSection );
} void CSettings::PutIniSetting ( QDomDocument& xmlFile, const QString& sSection,
const QString& sKey, const QString& sValue )
// check if key is already there, if not then create it {
QDomElement xmlKey = xmlSection.firstChildElement ( sKey ); // check if section is already there, if not then create it
if ( xmlKey.isNull() ) QDomElement xmlSection = xmlFile.firstChildElement ( sSection );
{ if ( xmlSection.isNull() )
xmlKey = xmlFile.createElement ( sKey ); {
xmlSection.appendChild ( xmlKey ); // create new root element and add to document
} xmlSection = xmlFile.createElement ( sSection );
xmlFile.appendChild ( xmlSection );
// add actual data to the key }
QDomText currentValue = xmlFile.createTextNode ( sValue );
xmlKey.appendChild ( currentValue ); // check if key is already there, if not then create it
} QDomElement xmlKey = xmlSection.firstChildElement ( sKey );
if ( xmlKey.isNull() )
{
xmlKey = xmlFile.createElement ( sKey );
xmlSection.appendChild ( xmlKey );
}
// add actual data to the key
QDomText currentValue = xmlFile.createTextNode ( sValue );
xmlKey.appendChild ( currentValue );
}