2011-06-11 20:18:46 +02:00
|
|
|
/******************************************************************************\
|
2020-01-01 15:41:43 +01:00
|
|
|
* Copyright (c) 2004-2020
|
2011-06-11 20:18:46 +02:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
\******************************************************************************/
|
|
|
|
|
2019-07-09 08:52:38 +02:00
|
|
|
#pragma once
|
2011-06-11 20:18:46 +02:00
|
|
|
|
2020-04-09 20:06:34 +02:00
|
|
|
#include <QTcpSocket>
|
2013-01-02 21:41:04 +01:00
|
|
|
#include <QHostAddress>
|
|
|
|
#include <QHostInfo>
|
|
|
|
#include <QMenu>
|
|
|
|
#include <QWhatsThis>
|
|
|
|
#include <QTextBrowser>
|
|
|
|
#include <QLabel>
|
2015-01-17 17:53:54 +01:00
|
|
|
#include <QCheckBox>
|
2015-01-30 21:58:49 +01:00
|
|
|
#include <QComboBox>
|
|
|
|
#include <QLineEdit>
|
2013-01-02 21:41:04 +01:00
|
|
|
#include <QDateTime>
|
|
|
|
#include <QFile>
|
|
|
|
#include <QDesktopServices>
|
|
|
|
#include <QUrl>
|
|
|
|
#include <QLocale>
|
2015-03-16 17:17:31 +01:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
|
|
|
|
# include <QElapsedTimer>
|
|
|
|
#endif
|
2011-06-11 20:18:46 +02:00
|
|
|
#include <vector>
|
2013-12-16 21:36:48 +01:00
|
|
|
#include <algorithm>
|
2011-06-11 20:18:46 +02:00
|
|
|
#include "global.h"
|
|
|
|
using namespace std; // because of the library: "vector"
|
|
|
|
#ifdef _WIN32
|
2019-07-09 08:52:38 +02:00
|
|
|
# include <winsock2.h>
|
2019-07-09 09:16:38 +02:00
|
|
|
# include <ws2ipdef.h>
|
2011-06-11 20:18:46 +02:00
|
|
|
# include <windows.h>
|
|
|
|
# include <mmsystem.h>
|
2014-06-12 21:28:39 +02:00
|
|
|
#elif defined ( __APPLE__ ) || defined ( __MACOSX )
|
|
|
|
# include <mach/mach.h>
|
|
|
|
# include <mach/mach_error.h>
|
|
|
|
# include <mach/mach_time.h>
|
|
|
|
#else
|
2013-12-27 17:04:46 +01:00
|
|
|
# include <sys/time.h>
|
2013-01-08 20:26:05 +01:00
|
|
|
#endif
|
2013-01-09 10:28:15 +01:00
|
|
|
#include "ui_aboutdlgbase.h"
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
|
2015-01-30 21:58:49 +01:00
|
|
|
class CClient; // forward declaration of CClient
|
|
|
|
|
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
/* Definitions ****************************************************************/
|
|
|
|
#define METER_FLY_BACK 2
|
2019-01-12 13:45:08 +01:00
|
|
|
#define INVALID_MIDI_CH -1 // invalid MIDI channel definition
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* Global functions ***********************************************************/
|
|
|
|
// converting double to short
|
|
|
|
inline short Double2Short ( const double dInput )
|
|
|
|
{
|
|
|
|
// lower bound
|
|
|
|
if ( dInput < _MINSHORT )
|
|
|
|
{
|
|
|
|
return _MINSHORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// upper bound
|
|
|
|
if ( dInput > _MAXSHORT )
|
|
|
|
{
|
|
|
|
return _MAXSHORT;
|
|
|
|
}
|
|
|
|
|
2019-05-17 22:55:46 +02:00
|
|
|
return static_cast<short> ( dInput );
|
2011-06-11 20:18:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// debug error handling
|
|
|
|
void DebugError ( const QString& pchErDescr,
|
|
|
|
const QString& pchPar1Descr,
|
|
|
|
const double dPar1,
|
|
|
|
const QString& pchPar2Descr,
|
|
|
|
const double dPar2 );
|
|
|
|
|
2013-02-17 11:33:01 +01:00
|
|
|
// calculate the bit rate in bits per second from the number of coded bytes
|
2020-04-07 22:09:29 +02:00
|
|
|
inline int CalcBitRateBitsPerSecFromCodedBytes ( const int iCeltNumCodedBytes,
|
|
|
|
const int iFrameSize )
|
2013-02-17 11:33:01 +01:00
|
|
|
{
|
2020-04-07 22:09:29 +02:00
|
|
|
return ( SYSTEM_SAMPLE_RATE_HZ * iCeltNumCodedBytes * 8 ) / iFrameSize;
|
2013-02-17 11:33:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
/******************************************************************************\
|
|
|
|
* CVector Base Class *
|
|
|
|
\******************************************************************************/
|
|
|
|
template<class TData> class CVector : public std::vector<TData>
|
|
|
|
{
|
|
|
|
public:
|
2013-12-24 11:06:03 +01:00
|
|
|
CVector() {}
|
2013-02-23 21:13:43 +01:00
|
|
|
CVector ( const int iNeSi ) { Init ( iNeSi ); }
|
2013-12-24 11:06:03 +01:00
|
|
|
CVector ( const int iNeSi,
|
|
|
|
const TData tInVa ) { Init ( iNeSi, tInVa ); }
|
2011-06-11 20:18:46 +02:00
|
|
|
|
2020-03-29 12:12:13 +02:00
|
|
|
CVector ( CVector const& ) = default;
|
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
void Init ( const int iNewSize );
|
|
|
|
|
|
|
|
// use this init to give all elements a defined value
|
2013-12-24 11:06:03 +01:00
|
|
|
void Init ( const int iNewSize,
|
|
|
|
const TData tIniVal );
|
|
|
|
|
|
|
|
// set all values to the given reset value
|
|
|
|
void Reset ( const TData tResetVal )
|
|
|
|
{
|
|
|
|
std::fill ( this->begin(), this->end(), tResetVal );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Enlarge ( const int iAddedSize )
|
|
|
|
{
|
2013-12-24 11:20:24 +01:00
|
|
|
std::vector<TData>::resize ( std::vector<TData>::size() + iAddedSize );
|
2013-12-24 11:06:03 +01:00
|
|
|
}
|
2011-06-11 20:18:46 +02:00
|
|
|
|
2013-12-14 23:11:24 +01:00
|
|
|
void Add ( const TData& tI )
|
|
|
|
{
|
|
|
|
Enlarge ( 1 );
|
2013-12-24 11:20:24 +01:00
|
|
|
std::vector<TData>::back() = tI;
|
2013-12-14 23:11:24 +01:00
|
|
|
}
|
2011-06-11 20:18:46 +02:00
|
|
|
|
2013-02-28 21:54:47 +01:00
|
|
|
int StringFiFoWithCompare ( const QString strNewValue,
|
|
|
|
const bool bDoAdding = true );
|
2013-02-23 21:13:43 +01:00
|
|
|
|
2013-12-24 11:06:03 +01:00
|
|
|
// this function simply converts the type of size to integer
|
2018-03-22 21:47:08 +01:00
|
|
|
inline int Size() const { return static_cast<int> ( std::vector<TData>::size() ); }
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
// This operator allows for a l-value assignment of this object:
|
|
|
|
// CVector[x] = y is possible
|
2013-12-14 23:11:24 +01:00
|
|
|
inline TData& operator[] ( const int iPos )
|
|
|
|
{
|
2014-01-19 16:03:11 +01:00
|
|
|
#ifdef _DEBUG_
|
2013-12-24 11:06:03 +01:00
|
|
|
if ( ( iPos < 0 ) || ( iPos > Size() - 1 ) )
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
DebugError ( "Writing vector out of bounds", "Vector size",
|
2013-12-24 11:06:03 +01:00
|
|
|
Size(), "New parameter", iPos );
|
2011-06-11 20:18:46 +02:00
|
|
|
}
|
2014-01-19 16:03:11 +01:00
|
|
|
#endif
|
2013-12-24 11:06:03 +01:00
|
|
|
return std::vector<TData>::operator[] ( iPos );
|
2013-12-14 23:11:24 +01:00
|
|
|
}
|
2011-06-11 20:18:46 +02:00
|
|
|
|
2013-12-14 23:11:24 +01:00
|
|
|
inline TData operator[] ( const int iPos ) const
|
|
|
|
{
|
2014-01-19 16:03:11 +01:00
|
|
|
#ifdef _DEBUG_
|
2013-12-24 11:06:03 +01:00
|
|
|
if ( ( iPos < 0 ) || ( iPos > Size() - 1 ) )
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
DebugError ( "Reading vector out of bounds", "Vector size",
|
2013-12-24 11:06:03 +01:00
|
|
|
Size(), "New parameter", iPos );
|
2011-06-11 20:18:46 +02:00
|
|
|
}
|
2014-01-19 16:03:11 +01:00
|
|
|
#endif
|
2013-12-24 11:06:03 +01:00
|
|
|
return std::vector<TData>::operator[] ( iPos );
|
2013-12-14 23:11:24 +01:00
|
|
|
}
|
2011-06-11 20:18:46 +02:00
|
|
|
|
2013-12-14 23:11:24 +01:00
|
|
|
inline CVector<TData>& operator= ( const CVector<TData>& vecI )
|
|
|
|
{
|
2014-01-19 16:03:11 +01:00
|
|
|
#ifdef _DEBUG_
|
2013-12-24 11:06:03 +01:00
|
|
|
// vectors which shall be copied MUST have same size!
|
|
|
|
if ( vecI.Size() != Size() )
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
DebugError ( "Vector operator=() different size", "Vector size",
|
2013-12-24 11:06:03 +01:00
|
|
|
Size(), "New parameter", vecI.Size() );
|
2011-06-11 20:18:46 +02:00
|
|
|
}
|
2014-01-19 16:03:11 +01:00
|
|
|
#endif
|
2013-12-24 11:06:03 +01:00
|
|
|
std::vector<TData>::operator= ( vecI );
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Implementation *************************************************************/
|
|
|
|
template<class TData> void CVector<TData>::Init ( const int iNewSize )
|
|
|
|
{
|
2013-12-24 11:06:03 +01:00
|
|
|
// clear old buffer and reserve memory for new buffer
|
2013-12-24 11:20:24 +01:00
|
|
|
std::vector<TData>::clear();
|
|
|
|
std::vector<TData>::resize ( iNewSize );
|
2011-06-11 20:18:46 +02:00
|
|
|
}
|
|
|
|
|
2011-06-28 21:07:24 +02:00
|
|
|
template<class TData> void CVector<TData>::Init ( const int iNewSize,
|
2011-06-11 20:18:46 +02:00
|
|
|
const TData tIniVal )
|
|
|
|
{
|
2013-12-24 11:06:03 +01:00
|
|
|
// call actual init routine and reset all values to the given value
|
2011-06-11 20:18:46 +02:00
|
|
|
Init ( iNewSize );
|
|
|
|
Reset ( tIniVal );
|
|
|
|
}
|
|
|
|
|
2013-02-23 21:13:43 +01:00
|
|
|
// note: this is only supported for string vectors
|
2013-02-28 21:54:47 +01:00
|
|
|
template<class TData> int CVector<TData>::StringFiFoWithCompare ( const QString strNewValue,
|
|
|
|
const bool bDoAdding )
|
2013-02-23 21:13:43 +01:00
|
|
|
{
|
2013-12-24 11:06:03 +01:00
|
|
|
const int iVectorSize = Size();
|
|
|
|
|
2013-02-23 22:09:14 +01:00
|
|
|
CVector<QString> vstrTempList ( iVectorSize, "" );
|
2013-02-23 21:13:43 +01:00
|
|
|
|
2013-02-28 21:54:47 +01:00
|
|
|
// init with illegal index per definition
|
|
|
|
int iOldIndex = -1;
|
|
|
|
|
|
|
|
// init temporary list count (may be overwritten later on)
|
|
|
|
int iTempListCnt = 0;
|
|
|
|
|
|
|
|
if ( bDoAdding )
|
|
|
|
{
|
|
|
|
// store the new element in the current storage list at
|
|
|
|
// the top, make sure we do not have more than allowed stored
|
|
|
|
// elements
|
|
|
|
vstrTempList[0] = strNewValue;
|
|
|
|
iTempListCnt = 1;
|
|
|
|
}
|
2013-02-23 21:13:43 +01:00
|
|
|
|
2013-02-23 22:09:14 +01:00
|
|
|
for ( int iIdx = 0; iIdx < iVectorSize; iIdx++ )
|
2013-02-23 21:13:43 +01:00
|
|
|
{
|
2013-02-27 22:20:14 +01:00
|
|
|
// first check if we still have space in our data storage
|
|
|
|
if ( iTempListCnt < iVectorSize )
|
2013-02-23 21:13:43 +01:00
|
|
|
{
|
2013-02-27 22:20:14 +01:00
|
|
|
// only add old element if it is not the same as the
|
|
|
|
// selected one
|
2013-12-24 11:06:03 +01:00
|
|
|
if ( operator[] ( iIdx ).compare ( strNewValue ) )
|
2013-02-27 22:20:14 +01:00
|
|
|
{
|
2013-12-24 11:06:03 +01:00
|
|
|
vstrTempList[iTempListCnt] = operator[] ( iIdx );
|
2013-02-27 22:20:14 +01:00
|
|
|
|
|
|
|
iTempListCnt++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
iOldIndex = iIdx;
|
|
|
|
}
|
2013-02-23 21:13:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy new generated list to data base
|
|
|
|
*this = vstrTempList;
|
2013-02-27 22:20:14 +01:00
|
|
|
|
|
|
|
return iOldIndex;
|
2013-02-23 21:13:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
/******************************************************************************\
|
|
|
|
* CFIFO Class (First In, First Out) *
|
|
|
|
\******************************************************************************/
|
|
|
|
template<class TData> class CFIFO : public CVector<TData>
|
|
|
|
{
|
|
|
|
public:
|
2013-12-24 11:06:03 +01:00
|
|
|
CFIFO() : iCurIdx ( 0 ) {}
|
|
|
|
CFIFO ( const int iNeSi ) : CVector<TData> ( iNeSi ), iCurIdx ( 0 ) {}
|
2011-06-11 20:18:46 +02:00
|
|
|
CFIFO ( const int iNeSi, const TData tInVa ) :
|
|
|
|
CVector<TData> ( iNeSi, tInVa ), iCurIdx ( 0 ) {}
|
|
|
|
|
|
|
|
void Add ( const TData tNewD );
|
2013-12-24 11:20:24 +01:00
|
|
|
inline TData Get() { return CVector<TData>::operator[] ( iCurIdx ); }
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
virtual void Init ( const int iNewSize );
|
2013-12-24 11:06:03 +01:00
|
|
|
|
2013-12-14 23:11:24 +01:00
|
|
|
virtual void Init ( const int iNewSize,
|
|
|
|
const TData tIniVal );
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
int iCurIdx;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class TData> void CFIFO<TData>::Init ( const int iNewSize )
|
|
|
|
{
|
|
|
|
iCurIdx = 0;
|
|
|
|
CVector<TData>::Init ( iNewSize );
|
|
|
|
}
|
|
|
|
|
2013-12-14 23:11:24 +01:00
|
|
|
template<class TData> void CFIFO<TData>::Init ( const int iNewSize,
|
2011-06-11 20:18:46 +02:00
|
|
|
const TData tIniVal )
|
|
|
|
{
|
|
|
|
iCurIdx = 0;
|
|
|
|
CVector<TData>::Init ( iNewSize, tIniVal );
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class TData> void CFIFO<TData>::Add ( const TData tNewD )
|
|
|
|
{
|
2013-12-24 11:20:24 +01:00
|
|
|
CVector<TData>::operator[] ( iCurIdx ) = tNewD;
|
2011-06-11 20:18:46 +02:00
|
|
|
|
2013-12-24 11:06:03 +01:00
|
|
|
// increment index and check for wrap around
|
2011-06-11 20:18:46 +02:00
|
|
|
iCurIdx++;
|
2013-12-24 11:06:03 +01:00
|
|
|
|
2013-12-24 11:20:24 +01:00
|
|
|
if ( iCurIdx >= CVector<TData>::Size() )
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
iCurIdx = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************\
|
|
|
|
* CMovingAv Class (Moving Average) *
|
|
|
|
\******************************************************************************/
|
|
|
|
template<class TData> class CMovingAv : public CVector<TData>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CMovingAv() :
|
|
|
|
CVector<TData>(),
|
|
|
|
iCurIdx ( 0 ),
|
|
|
|
iNorm ( 0 ),
|
|
|
|
dCurAvResult ( 0 ),
|
|
|
|
dNoDataResult ( 0 ) {}
|
|
|
|
|
|
|
|
void Add ( const TData tNewD );
|
|
|
|
|
|
|
|
void Init ( const int iNewSize,
|
|
|
|
const double dNNoDRes = 0 );
|
|
|
|
|
|
|
|
void Reset();
|
|
|
|
|
|
|
|
inline double GetAverage()
|
|
|
|
{
|
2011-06-28 21:07:24 +02:00
|
|
|
// make sure we do not divide by zero
|
2013-12-24 11:06:03 +01:00
|
|
|
if ( iNorm == 0 )
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
return dNoDataResult;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-12-24 11:06:03 +01:00
|
|
|
return dCurAvResult / iNorm;
|
2011-06-11 20:18:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-18 14:01:36 +02:00
|
|
|
double InitializationState() const
|
2011-06-28 21:07:24 +02:00
|
|
|
{
|
|
|
|
// make sure we do not divide by zero
|
2013-12-24 11:20:24 +01:00
|
|
|
if ( CVector<TData>::Size() != 0 )
|
2011-06-28 21:07:24 +02:00
|
|
|
{
|
2013-12-24 11:20:24 +01:00
|
|
|
return static_cast<double> ( iNorm ) / CVector<TData>::Size();
|
2011-06-28 21:07:24 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
int iCurIdx;
|
|
|
|
int iNorm;
|
|
|
|
double dCurAvResult;
|
|
|
|
double dNoDataResult;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class TData> void CMovingAv<TData>::Init ( const int iNewSize,
|
|
|
|
const double dNNoDRes )
|
|
|
|
{
|
|
|
|
iNorm = 0;
|
|
|
|
iCurIdx = 0;
|
|
|
|
dCurAvResult = 0; // only for scalars!
|
|
|
|
dNoDataResult = dNNoDRes;
|
|
|
|
CVector<TData>::Init ( iNewSize );
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class TData> void CMovingAv<TData>::Reset()
|
|
|
|
{
|
|
|
|
iNorm = 0;
|
|
|
|
iCurIdx = 0;
|
|
|
|
dCurAvResult = 0; // only for scalars!
|
|
|
|
CVector<TData>::Reset ( TData ( 0 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class TData> void CMovingAv<TData>::Add ( const TData tNewD )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Optimized calculation of the moving average. We only add a new value and
|
|
|
|
subtract the old value from the result. We only need one addition and a
|
|
|
|
history buffer.
|
|
|
|
*/
|
2013-12-24 11:06:03 +01:00
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
// subtract oldest value
|
2013-12-24 11:20:24 +01:00
|
|
|
dCurAvResult -= CVector<TData>::operator[] ( iCurIdx );
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
// add new value and write in memory
|
|
|
|
dCurAvResult += tNewD;
|
2013-12-24 11:20:24 +01:00
|
|
|
CVector<TData>::operator[] ( iCurIdx ) = tNewD;
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
// increase position pointer and test if wrap
|
|
|
|
iCurIdx++;
|
2013-12-24 11:20:24 +01:00
|
|
|
if ( iCurIdx >= CVector<TData>::Size() )
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
iCurIdx = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// take care of norm
|
2013-12-24 11:20:24 +01:00
|
|
|
if ( iNorm < CVector<TData>::Size() )
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
2013-12-24 11:06:03 +01:00
|
|
|
iNorm++;
|
2011-06-11 20:18:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************\
|
|
|
|
* GUI Utilities *
|
|
|
|
\******************************************************************************/
|
|
|
|
// About dialog ----------------------------------------------------------------
|
|
|
|
class CAboutDlg : public QDialog, private Ui_CAboutDlgBase
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
2019-05-17 22:55:46 +02:00
|
|
|
CAboutDlg ( QWidget* parent = nullptr );
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
static QString GetVersionAndNameStr ( const bool bWithHtml = true );
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-01-17 17:53:54 +01:00
|
|
|
// Licence dialog --------------------------------------------------------------
|
|
|
|
class CLicenceDlg : public QDialog
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
2019-05-17 22:55:46 +02:00
|
|
|
CLicenceDlg ( QWidget* parent = nullptr );
|
2015-01-17 17:53:54 +01:00
|
|
|
|
|
|
|
protected:
|
|
|
|
QPushButton* butAccept;
|
|
|
|
|
|
|
|
public slots:
|
|
|
|
void OnAgreeStateChanged ( int value ) { butAccept->setEnabled ( value == Qt::Checked ); }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-01-30 21:58:49 +01:00
|
|
|
// Musician profile dialog -----------------------------------------------------
|
|
|
|
class CMusProfDlg : public QDialog
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
CMusProfDlg ( CClient* pNCliP,
|
2019-05-17 22:55:46 +02:00
|
|
|
QWidget* parent = nullptr );
|
2015-01-30 21:58:49 +01:00
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual void showEvent ( QShowEvent* );
|
|
|
|
|
|
|
|
QLineEdit* pedtAlias;
|
|
|
|
QComboBox* pcbxInstrument;
|
|
|
|
QComboBox* pcbxCountry;
|
|
|
|
QLineEdit* pedtCity;
|
|
|
|
QComboBox* pcbxSkill;
|
|
|
|
|
|
|
|
CClient* pClient;
|
|
|
|
|
|
|
|
public slots:
|
|
|
|
void OnAliasTextChanged ( const QString& strNewName );
|
|
|
|
void OnInstrumentActivated ( int iCntryListItem );
|
|
|
|
void OnCountryActivated ( int iCntryListItem );
|
|
|
|
void OnCityTextChanged ( const QString& strNewName );
|
|
|
|
void OnSkillActivated ( int iCntryListItem );
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
// Help menu -------------------------------------------------------------------
|
2013-03-24 16:42:23 +01:00
|
|
|
class CHelpMenu : public QMenu
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
2019-05-17 22:55:46 +02:00
|
|
|
CHelpMenu ( QWidget* parent = nullptr );
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
CAboutDlg AboutDlg;
|
|
|
|
|
|
|
|
public slots:
|
|
|
|
void OnHelpWhatsThis() { QWhatsThis::enterWhatsThisMode(); }
|
|
|
|
void OnHelpAbout() { AboutDlg.exec(); }
|
|
|
|
void OnHelpDownloadLink()
|
|
|
|
{ QDesktopServices::openUrl ( QUrl ( LLCON_DOWNLOAD_URL ) ); }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-04-12 18:24:35 +02:00
|
|
|
// Console writer factory ------------------------------------------------------
|
|
|
|
// this class was written by pljones
|
|
|
|
class ConsoleWriterFactory
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ConsoleWriterFactory() : ptsConsole ( nullptr ) { }
|
|
|
|
QTextStream* get();
|
|
|
|
|
|
|
|
private:
|
|
|
|
QTextStream* ptsConsole;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
/******************************************************************************\
|
2013-02-11 16:53:52 +01:00
|
|
|
* Other Classes/Enums *
|
2011-06-11 20:18:46 +02:00
|
|
|
\******************************************************************************/
|
2013-02-11 16:53:52 +01:00
|
|
|
|
2014-02-23 21:01:17 +01:00
|
|
|
|
|
|
|
// Audio channel configuration -------------------------------------------------
|
|
|
|
enum EAudChanConf
|
|
|
|
{
|
|
|
|
// used for settings -> enum values must be fixed!
|
|
|
|
CC_MONO = 0,
|
|
|
|
CC_MONO_IN_STEREO_OUT = 1,
|
|
|
|
CC_STEREO = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
// Audio compression type enum -------------------------------------------------
|
|
|
|
enum EAudComprType
|
|
|
|
{
|
|
|
|
// used for protocol -> enum values must be fixed!
|
2020-04-11 14:27:50 +02:00
|
|
|
CT_NONE = 0,
|
|
|
|
CT_CELT = 1,
|
|
|
|
CT_OPUS = 2,
|
2020-03-28 16:27:45 +01:00
|
|
|
CT_OPUS64 = 3 // using OPUS with 64 samples frame size
|
2013-02-11 16:53:52 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-08-15 21:15:01 +02:00
|
|
|
// Audio quality enum ----------------------------------------------------------
|
|
|
|
enum EAudioQuality
|
|
|
|
{
|
|
|
|
// used for settings and the comobo box index -> enum values must be fixed!
|
|
|
|
AQ_LOW = 0,
|
|
|
|
AQ_NORMAL = 1,
|
|
|
|
AQ_HIGH = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
// Get data status enum --------------------------------------------------------
|
|
|
|
enum EGetDataStat
|
|
|
|
{
|
|
|
|
GS_BUFFER_OK,
|
|
|
|
GS_BUFFER_UNDERRUN,
|
|
|
|
GS_CHAN_NOW_DISCONNECTED,
|
|
|
|
GS_CHAN_NOT_CONNECTED
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// GUI design enum -------------------------------------------------------------
|
|
|
|
enum EGUIDesign
|
|
|
|
{
|
|
|
|
// used for settings -> enum values must be fixed!
|
|
|
|
GD_STANDARD = 0,
|
|
|
|
GD_ORIGINAL = 1
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-01-18 22:20:41 +01:00
|
|
|
// Server licence type enum ----------------------------------------------------
|
|
|
|
enum ELicenceType
|
|
|
|
{
|
|
|
|
// used for protocol -> enum values must be fixed!
|
2015-01-23 20:43:18 +01:00
|
|
|
LT_NO_LICENCE = 0,
|
|
|
|
LT_CREATIVECOMMONS = 1
|
2015-01-18 22:20:41 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2020-04-11 14:27:50 +02:00
|
|
|
// Central server address type -------------------------------------------------
|
|
|
|
enum ECSAddType
|
|
|
|
{
|
|
|
|
AT_MANUAL = 0,
|
|
|
|
AT_DEFAULT = 1, // Europe and others
|
|
|
|
AT_NORTH_AMERICA = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
// Skill level enum ------------------------------------------------------------
|
|
|
|
enum ESkillLevel
|
|
|
|
{
|
|
|
|
// used for protocol -> enum values must be fixed!
|
|
|
|
SL_NOT_SET = 0,
|
|
|
|
SL_BEGINNER = 1,
|
|
|
|
SL_INTERMEDIATE = 2,
|
|
|
|
SL_PROFESSIONAL = 3
|
|
|
|
};
|
|
|
|
|
2015-02-04 17:07:21 +01:00
|
|
|
// define the GUI RGB colors for each skill level
|
|
|
|
#define RGBCOL_R_SL_NOT_SET 255
|
|
|
|
#define RGBCOL_G_SL_NOT_SET 255
|
|
|
|
#define RGBCOL_B_SL_NOT_SET 255
|
2015-02-04 19:11:58 +01:00
|
|
|
#define RGBCOL_R_SL_BEGINNER 255
|
|
|
|
#define RGBCOL_G_SL_BEGINNER 255
|
|
|
|
#define RGBCOL_B_SL_BEGINNER 200
|
2015-02-04 17:07:21 +01:00
|
|
|
#define RGBCOL_R_SL_INTERMEDIATE 225
|
|
|
|
#define RGBCOL_G_SL_INTERMEDIATE 255
|
|
|
|
#define RGBCOL_B_SL_INTERMEDIATE 225
|
|
|
|
#define RGBCOL_R_SL_SL_PROFESSIONAL 255
|
|
|
|
#define RGBCOL_G_SL_SL_PROFESSIONAL 225
|
|
|
|
#define RGBCOL_B_SL_SL_PROFESSIONAL 225
|
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
// Stereo signal level meter ---------------------------------------------------
|
|
|
|
class CStereoSignalLevelMeter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CStereoSignalLevelMeter() { Reset(); }
|
|
|
|
|
2020-04-10 16:56:45 +02:00
|
|
|
void Update ( const CVector<short>& vecsAudio );
|
|
|
|
double MicLevelLeft() { return CalcLogResult ( dCurLevelL ); }
|
|
|
|
double MicLevelRight() { return CalcLogResult ( dCurLevelR ); }
|
|
|
|
static double CalcLogResult ( const double& dLinearLevel );
|
|
|
|
|
|
|
|
void Reset()
|
2013-12-14 23:11:24 +01:00
|
|
|
{
|
|
|
|
dCurLevelL = 0.0;
|
|
|
|
dCurLevelR = 0.0;
|
|
|
|
}
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
protected:
|
2013-12-14 23:11:24 +01:00
|
|
|
double UpdateCurLevel ( double dCurLevel,
|
|
|
|
const short& sMax );
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
double dCurLevelL;
|
|
|
|
double dCurLevelR;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Host address ----------------------------------------------------------------
|
|
|
|
class CHostAddress
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum EStringMode
|
|
|
|
{
|
|
|
|
SM_IP_PORT,
|
|
|
|
SM_IP_NO_LAST_BYTE,
|
|
|
|
SM_IP_NO_LAST_BYTE_PORT
|
|
|
|
};
|
|
|
|
|
|
|
|
CHostAddress() :
|
|
|
|
InetAddr ( static_cast<quint32> ( 0 ) ),
|
|
|
|
iPort ( 0 ) {}
|
|
|
|
|
|
|
|
CHostAddress ( const QHostAddress NInetAddr,
|
|
|
|
const quint16 iNPort ) :
|
|
|
|
InetAddr ( NInetAddr ),
|
|
|
|
iPort ( iNPort ) {}
|
|
|
|
|
|
|
|
CHostAddress ( const CHostAddress& NHAddr ) :
|
|
|
|
InetAddr ( NHAddr.InetAddr ),
|
|
|
|
iPort ( NHAddr.iPort ) {}
|
|
|
|
|
|
|
|
// copy operator
|
|
|
|
CHostAddress& operator= ( const CHostAddress& NHAddr )
|
|
|
|
{
|
|
|
|
InetAddr = NHAddr.InetAddr;
|
|
|
|
iPort = NHAddr.iPort;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// compare operator
|
2014-01-06 17:06:04 +01:00
|
|
|
bool operator== ( const CHostAddress& CompAddr ) const
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
return ( ( CompAddr.InetAddr == InetAddr ) &&
|
|
|
|
( CompAddr.iPort == iPort ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
QString toString ( const EStringMode eStringMode = SM_IP_PORT ) const
|
|
|
|
{
|
|
|
|
QString strReturn = InetAddr.toString();
|
|
|
|
|
|
|
|
// special case: for local host address, we do not replace the last byte
|
|
|
|
if ( ( ( eStringMode == SM_IP_NO_LAST_BYTE ) ||
|
|
|
|
( eStringMode == SM_IP_NO_LAST_BYTE_PORT ) ) &&
|
|
|
|
( InetAddr != QHostAddress ( QHostAddress::LocalHost ) ) )
|
|
|
|
{
|
|
|
|
// replace last byte by an "x"
|
|
|
|
strReturn = strReturn.section ( ".", 0, 2 ) + ".x";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ( eStringMode == SM_IP_PORT ) ||
|
|
|
|
( eStringMode == SM_IP_NO_LAST_BYTE_PORT ) )
|
|
|
|
{
|
|
|
|
// add port number after a semicolon
|
|
|
|
strReturn += ":" + QString().setNum ( iPort );
|
|
|
|
}
|
|
|
|
|
|
|
|
return strReturn;
|
|
|
|
}
|
|
|
|
|
|
|
|
QHostAddress InetAddr;
|
|
|
|
quint16 iPort;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
// Instrument picture data base ------------------------------------------------
|
|
|
|
// this is a pure static class
|
|
|
|
class CInstPictures
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
public:
|
2013-02-11 16:53:52 +01:00
|
|
|
enum EInstCategory
|
|
|
|
{
|
|
|
|
IC_OTHER_INSTRUMENT,
|
|
|
|
IC_WIND_INSTRUMENT,
|
|
|
|
IC_STRING_INSTRUMENT,
|
|
|
|
IC_PLUCKING_INSTRUMENT,
|
|
|
|
IC_PERCUSSION_INSTRUMENT,
|
2015-02-04 08:02:40 +01:00
|
|
|
IC_KEYBOARD_INSTRUMENT,
|
|
|
|
IC_MULTIPLE_INSTRUMENT
|
2013-02-11 16:53:52 +01:00
|
|
|
};
|
2011-06-11 20:18:46 +02:00
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
// per definition: the very first instrument is the "not used" instrument
|
|
|
|
static int GetNotUsedInstrument() { return 0; }
|
|
|
|
static bool IsNotUsedInstrument ( const int iInstrument ) { return iInstrument == 0; }
|
2011-06-11 20:18:46 +02:00
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
static int GetNumAvailableInst() { return GetTable().Size(); }
|
|
|
|
static QString GetResourceReference ( const int iInstrument );
|
|
|
|
static QString GetName ( const int iInstrument );
|
|
|
|
|
|
|
|
// TODO make use of instrument category (not yet implemented)
|
|
|
|
|
|
|
|
protected:
|
|
|
|
class CInstPictProps
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CInstPictProps() :
|
|
|
|
strName ( "" ),
|
|
|
|
strResourceReference ( "" ),
|
|
|
|
eInstCategory ( IC_OTHER_INSTRUMENT ) {}
|
|
|
|
|
|
|
|
CInstPictProps ( const QString NsName,
|
|
|
|
const QString NsResRef,
|
|
|
|
const EInstCategory NeInstCat ) :
|
|
|
|
strName ( NsName ),
|
|
|
|
strResourceReference ( NsResRef ),
|
|
|
|
eInstCategory ( NeInstCat ) {}
|
|
|
|
|
|
|
|
QString strName;
|
|
|
|
QString strResourceReference;
|
|
|
|
EInstCategory eInstCategory;
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool IsInstIndexInRange ( const int iIdx );
|
|
|
|
|
|
|
|
static CVector<CInstPictProps>& GetTable();
|
2011-06-11 20:18:46 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2020-04-11 10:31:26 +02:00
|
|
|
// Locale management class -----------------------------------------------------
|
|
|
|
class CLocale
|
2015-01-24 16:38:39 +01:00
|
|
|
{
|
|
|
|
public:
|
2020-04-11 14:27:50 +02:00
|
|
|
static QString GetCountryFlagIconsResourceReference ( const QLocale::Country eCountry );
|
|
|
|
static ECSAddType GetCentralServerAddressType ( const QLocale::Country eCountry );
|
2015-01-24 16:38:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
// Info of a channel -----------------------------------------------------------
|
|
|
|
class CChannelCoreInfo
|
2013-02-10 09:52:19 +01:00
|
|
|
{
|
|
|
|
public:
|
2013-02-11 16:53:52 +01:00
|
|
|
CChannelCoreInfo() :
|
|
|
|
strName ( "" ),
|
|
|
|
eCountry ( QLocale::AnyCountry ),
|
|
|
|
strCity ( "" ),
|
|
|
|
iInstrument ( CInstPictures::GetNotUsedInstrument() ),
|
|
|
|
eSkillLevel ( SL_NOT_SET ) {}
|
|
|
|
|
|
|
|
CChannelCoreInfo ( const QString NsName,
|
|
|
|
const QLocale::Country& NeCountry,
|
|
|
|
const QString& NsCity,
|
|
|
|
const int NiInstrument,
|
|
|
|
const ESkillLevel NeSkillLevel ) :
|
|
|
|
strName ( NsName ),
|
2013-02-10 09:52:19 +01:00
|
|
|
eCountry ( NeCountry ),
|
|
|
|
strCity ( NsCity ),
|
|
|
|
iInstrument ( NiInstrument ),
|
2013-02-11 16:53:52 +01:00
|
|
|
eSkillLevel ( NeSkillLevel ) {}
|
2013-02-10 09:52:19 +01:00
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
CChannelCoreInfo ( const CChannelCoreInfo& NCorInf ) :
|
|
|
|
strName ( NCorInf.strName ),
|
|
|
|
eCountry ( NCorInf.eCountry ),
|
|
|
|
strCity ( NCorInf.strCity ),
|
|
|
|
iInstrument ( NCorInf.iInstrument ),
|
|
|
|
eSkillLevel ( NCorInf.eSkillLevel ) {}
|
|
|
|
|
|
|
|
// compare operator
|
|
|
|
bool operator!= ( const CChannelCoreInfo& CompChanInfo )
|
|
|
|
{
|
|
|
|
return ( ( CompChanInfo.strName != strName ) ||
|
|
|
|
( CompChanInfo.eCountry != eCountry ) ||
|
|
|
|
( CompChanInfo.strCity != strCity ) ||
|
|
|
|
( CompChanInfo.iInstrument != iInstrument ) ||
|
|
|
|
( CompChanInfo.eSkillLevel != eSkillLevel ) );
|
|
|
|
}
|
|
|
|
|
2020-03-29 12:12:13 +02:00
|
|
|
CChannelCoreInfo& operator= ( const CChannelCoreInfo& ) = default;
|
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
// fader tag text (channel name)
|
|
|
|
QString strName;
|
2013-02-10 09:52:19 +01:00
|
|
|
|
|
|
|
// country in which the client is located
|
|
|
|
QLocale::Country eCountry;
|
|
|
|
|
|
|
|
// city in which the client is located
|
|
|
|
QString strCity;
|
|
|
|
|
|
|
|
// instrument ID of the client (which instrument is he/she playing)
|
|
|
|
int iInstrument;
|
|
|
|
|
|
|
|
// skill level of the musician
|
2013-02-11 16:53:52 +01:00
|
|
|
ESkillLevel eSkillLevel;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CChannelInfo : public CChannelCoreInfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CChannelInfo() :
|
|
|
|
iChanID ( 0 ),
|
2013-02-13 19:25:56 +01:00
|
|
|
iIpAddr ( 0 ) {}
|
2013-02-11 16:53:52 +01:00
|
|
|
|
|
|
|
CChannelInfo ( const int NiID,
|
|
|
|
const quint32 NiIP,
|
|
|
|
const CChannelCoreInfo& NCorInf ) :
|
|
|
|
CChannelCoreInfo ( NCorInf ),
|
|
|
|
iChanID ( NiID ),
|
2013-02-13 19:25:56 +01:00
|
|
|
iIpAddr ( NiIP ) {}
|
2013-02-11 16:53:52 +01:00
|
|
|
|
|
|
|
CChannelInfo ( const int NiID,
|
|
|
|
const quint32 NiIP,
|
|
|
|
const QString NsName,
|
|
|
|
const QLocale::Country& NeCountry,
|
|
|
|
const QString& NsCity,
|
|
|
|
const int NiInstrument,
|
|
|
|
const ESkillLevel NeSkillLevel ) :
|
|
|
|
CChannelCoreInfo ( NsName,
|
|
|
|
NeCountry,
|
|
|
|
NsCity,
|
|
|
|
NiInstrument,
|
|
|
|
NeSkillLevel ),
|
|
|
|
iChanID ( NiID ),
|
2013-02-13 19:25:56 +01:00
|
|
|
iIpAddr ( NiIP ) {}
|
2013-02-11 16:53:52 +01:00
|
|
|
|
2015-12-09 18:11:16 +01:00
|
|
|
QString GenNameForDisplay() const
|
|
|
|
{
|
|
|
|
// if text is empty, show IP address instead
|
|
|
|
if ( strName.isEmpty() )
|
|
|
|
{
|
|
|
|
// convert IP address to text and show it (use dummy port number
|
|
|
|
// since it is not used here)
|
|
|
|
const CHostAddress TempAddr =
|
|
|
|
CHostAddress ( QHostAddress ( iIpAddr ), 0 );
|
|
|
|
|
|
|
|
return TempAddr.toString ( CHostAddress::SM_IP_NO_LAST_BYTE );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// show name of channel
|
|
|
|
return strName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-11 16:53:52 +01:00
|
|
|
// ID of the channel
|
|
|
|
int iChanID;
|
|
|
|
|
|
|
|
// IP address of the channel
|
|
|
|
quint32 iIpAddr;
|
2013-02-10 09:52:19 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
// Server info -----------------------------------------------------------------
|
|
|
|
class CServerCoreInfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CServerCoreInfo() :
|
|
|
|
iLocalPortNumber ( 0 ),
|
|
|
|
strName ( "" ),
|
|
|
|
eCountry ( QLocale::AnyCountry ),
|
|
|
|
strCity ( "" ),
|
|
|
|
iMaxNumClients ( 0 ),
|
|
|
|
bPermanentOnline ( false ) {}
|
|
|
|
|
|
|
|
CServerCoreInfo (
|
|
|
|
const quint16 NLocPort,
|
|
|
|
const QString& NsName,
|
|
|
|
const QLocale::Country& NeCountry,
|
|
|
|
const QString& NsCity,
|
|
|
|
const int NiMaxNumClients,
|
|
|
|
const bool NbPermOnline) :
|
|
|
|
iLocalPortNumber ( NLocPort ),
|
|
|
|
strName ( NsName ),
|
|
|
|
eCountry ( NeCountry ),
|
|
|
|
strCity ( NsCity ),
|
|
|
|
iMaxNumClients ( NiMaxNumClients ),
|
|
|
|
bPermanentOnline ( NbPermOnline ) {}
|
|
|
|
|
|
|
|
// local port number of the server
|
|
|
|
quint16 iLocalPortNumber;
|
|
|
|
|
|
|
|
// name of the server
|
|
|
|
QString strName;
|
|
|
|
|
|
|
|
// country in which the server is located
|
|
|
|
QLocale::Country eCountry;
|
|
|
|
|
|
|
|
// city in which the server is located
|
|
|
|
QString strCity;
|
|
|
|
|
|
|
|
// maximum number of clients which can connect to the server at the same
|
|
|
|
// time
|
|
|
|
int iMaxNumClients;
|
|
|
|
|
|
|
|
// is the server permanently online or not (flag)
|
|
|
|
bool bPermanentOnline;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CServerInfo : public CServerCoreInfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CServerInfo() :
|
2020-04-09 20:06:34 +02:00
|
|
|
HostAddr ( CHostAddress() ),
|
|
|
|
LHostAddr ( CHostAddress() )
|
|
|
|
{}
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
CServerInfo (
|
|
|
|
const CHostAddress& NHAddr,
|
2020-04-09 20:06:34 +02:00
|
|
|
const CHostAddress& NLAddr,
|
2011-06-11 20:18:46 +02:00
|
|
|
const quint16 NLocPort,
|
|
|
|
const QString& NsName,
|
|
|
|
const QLocale::Country& NeCountry,
|
|
|
|
const QString& NsCity,
|
|
|
|
const int NiMaxNumClients,
|
|
|
|
const bool NbPermOnline) :
|
|
|
|
CServerCoreInfo ( NLocPort,
|
|
|
|
NsName,
|
|
|
|
NeCountry,
|
|
|
|
NsCity,
|
|
|
|
NiMaxNumClients,
|
2020-04-09 20:06:34 +02:00
|
|
|
NbPermOnline ),
|
|
|
|
HostAddr ( NHAddr ),
|
|
|
|
LHostAddr ( NLAddr ) {}
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
// internet address of the server
|
|
|
|
CHostAddress HostAddr;
|
2020-04-09 20:06:34 +02:00
|
|
|
|
|
|
|
// server internal address
|
|
|
|
CHostAddress LHostAddr;
|
2011-06-11 20:18:46 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Network transport properties ------------------------------------------------
|
|
|
|
class CNetworkTransportProps
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CNetworkTransportProps() :
|
|
|
|
iBaseNetworkPacketSize ( 0 ),
|
|
|
|
iBlockSizeFact ( 0 ),
|
|
|
|
iNumAudioChannels ( 0 ),
|
|
|
|
iSampleRate ( 0 ),
|
|
|
|
eAudioCodingType ( CT_NONE ),
|
|
|
|
iAudioCodingArg ( 0 ) {}
|
|
|
|
|
|
|
|
CNetworkTransportProps ( const uint32_t iNBNPS,
|
|
|
|
const uint16_t iNBSF,
|
|
|
|
const uint32_t iNNACH,
|
|
|
|
const uint32_t iNSR,
|
|
|
|
const EAudComprType eNACT,
|
|
|
|
const uint32_t iNVers,
|
|
|
|
const int32_t iNACA ) :
|
|
|
|
iBaseNetworkPacketSize ( iNBNPS ),
|
|
|
|
iBlockSizeFact ( iNBSF ),
|
|
|
|
iNumAudioChannels ( iNNACH ),
|
|
|
|
iSampleRate ( iNSR ),
|
|
|
|
eAudioCodingType ( eNACT ),
|
|
|
|
iVersion ( iNVers ),
|
|
|
|
iAudioCodingArg ( iNACA ) {}
|
|
|
|
|
|
|
|
uint32_t iBaseNetworkPacketSize;
|
|
|
|
uint16_t iBlockSizeFact;
|
|
|
|
uint32_t iNumAudioChannels;
|
|
|
|
uint32_t iSampleRate;
|
|
|
|
EAudComprType eAudioCodingType;
|
|
|
|
uint32_t iVersion;
|
|
|
|
int32_t iAudioCodingArg;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Network utility functions ---------------------------------------------------
|
2013-03-24 12:38:00 +01:00
|
|
|
class NetworkUtil
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
public:
|
2012-07-09 14:48:29 +02:00
|
|
|
static bool ParseNetworkAddress ( QString strAddress,
|
|
|
|
CHostAddress& HostAddress );
|
2020-04-09 20:06:34 +02:00
|
|
|
|
|
|
|
static CHostAddress GetLocalAddress();
|
2020-04-11 14:27:50 +02:00
|
|
|
static QString GetCentralServerAddress ( const ECSAddType eCentralServerAddressType,
|
|
|
|
const QString& strCentralServerAddress );
|
2011-06-11 20:18:46 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-02-21 22:25:26 +01:00
|
|
|
// Operating system utility functions ------------------------------------------
|
|
|
|
class COSUtil
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum EOpSystemType
|
|
|
|
{
|
|
|
|
// used for protocol -> enum values must be fixed!
|
|
|
|
OT_WINDOWS = 0,
|
|
|
|
OT_MAC_OS = 1,
|
|
|
|
OT_LINUX = 2,
|
|
|
|
OT_ANDROID = 3,
|
|
|
|
OT_I_OS = 4,
|
|
|
|
OT_UNIX = 5
|
|
|
|
};
|
|
|
|
|
|
|
|
static QString GetOperatingSystemString ( const EOpSystemType eOSType )
|
|
|
|
{
|
|
|
|
switch ( eOSType )
|
|
|
|
{
|
2019-05-17 22:55:46 +02:00
|
|
|
case OT_WINDOWS: return "Windows";
|
|
|
|
case OT_MAC_OS: return "MacOS";
|
|
|
|
case OT_LINUX: return "Linux";
|
|
|
|
case OT_ANDROID: return "Android";
|
|
|
|
case OT_I_OS: return "iOS";
|
|
|
|
case OT_UNIX: return "Unix";
|
|
|
|
default: return "Unknown";
|
2014-02-21 22:25:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static EOpSystemType GetOperatingSystem()
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
return OT_WINDOWS;
|
|
|
|
#elif defined ( __APPLE__ ) || defined ( __MACOSX )
|
|
|
|
return OT_MAC_OS;
|
2014-02-21 22:29:33 +01:00
|
|
|
#elif defined ( ANDROID )
|
2014-02-21 22:25:26 +01:00
|
|
|
return OT_ANDROID;
|
|
|
|
#else
|
|
|
|
return OT_LINUX;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
// Audio reverbration ----------------------------------------------------------
|
|
|
|
class CAudioReverb
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CAudioReverb() {}
|
|
|
|
|
2019-05-17 22:55:46 +02:00
|
|
|
void Init ( const int iSampleRate, const double rT60 = 1.1 );
|
2013-12-15 13:46:09 +01:00
|
|
|
void Clear();
|
2014-01-01 22:31:22 +01:00
|
|
|
void ProcessSample ( int16_t& iInputOutputLeft,
|
|
|
|
int16_t& iInputOutputRight,
|
2013-12-15 13:46:09 +01:00
|
|
|
const double dAttenuation );
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
void setT60 ( const double rT60, const int iSampleRate );
|
|
|
|
bool isPrime ( const int number );
|
|
|
|
|
2014-01-02 11:47:11 +01:00
|
|
|
class COnePole
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
COnePole() : dA ( 0 ), dB ( 0 ) { Reset(); }
|
|
|
|
void setPole ( const double dPole );
|
|
|
|
double Calc ( const double dIn );
|
|
|
|
void Reset() { dLastSample = 0; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
double dA;
|
|
|
|
double dB;
|
|
|
|
double dLastSample;
|
|
|
|
};
|
|
|
|
|
2014-01-01 22:31:22 +01:00
|
|
|
CFIFO<double> allpassDelays[3];
|
|
|
|
CFIFO<double> combDelays[4];
|
2014-01-02 11:47:11 +01:00
|
|
|
COnePole combFilters[4];
|
2014-01-01 22:31:22 +01:00
|
|
|
CFIFO<double> outLeftDelay;
|
|
|
|
CFIFO<double> outRightDelay;
|
|
|
|
double allpassCoefficient;
|
|
|
|
double combCoefficient[4];
|
2011-06-11 20:18:46 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// CRC -------------------------------------------------------------------------
|
|
|
|
class CCRC
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CCRC() : iPoly ( ( 1 << 5 ) | ( 1 << 12 ) ), iBitOutMask ( 1 << 16 )
|
|
|
|
{ Reset(); }
|
|
|
|
|
|
|
|
void Reset();
|
|
|
|
void AddByte ( const uint8_t byNewInput );
|
|
|
|
bool CheckCRC ( const uint32_t iCRC ) { return iCRC == GetCRC(); }
|
|
|
|
uint32_t GetCRC();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
uint32_t iPoly;
|
|
|
|
uint32_t iBitOutMask;
|
|
|
|
uint32_t iStateShiftReg;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Mathematics utilities -------------------------------------------------------
|
2013-03-24 12:38:00 +01:00
|
|
|
class MathUtils
|
2011-06-11 20:18:46 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
static int round ( double x )
|
|
|
|
{
|
2019-05-17 22:55:46 +02:00
|
|
|
return static_cast<int> ( ( x - floor ( x ) ) >= 0.5 ) ? static_cast<int> ( ceil ( x ) ) : static_cast<int> ( floor ( x ) );
|
2011-06-11 20:18:46 +02:00
|
|
|
}
|
2011-06-16 13:25:38 +02:00
|
|
|
|
|
|
|
static void UpDownIIR1 ( double& dOldValue,
|
|
|
|
const double& dNewValue,
|
|
|
|
const double& dWeightUp,
|
|
|
|
const double& dWeightDown )
|
|
|
|
{
|
|
|
|
// different IIR weights for up and down direction
|
|
|
|
if ( dNewValue < dOldValue )
|
|
|
|
{
|
|
|
|
dOldValue =
|
2014-01-06 16:33:53 +01:00
|
|
|
dOldValue * dWeightDown + ( 1.0 - dWeightDown ) * dNewValue;
|
2011-06-16 13:25:38 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dOldValue =
|
2014-01-06 16:33:53 +01:00
|
|
|
dOldValue * dWeightUp + ( 1.0 - dWeightUp ) * dNewValue;
|
2011-06-16 13:25:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DecideWithHysteresis ( const double dValue,
|
|
|
|
const int iOldValue,
|
|
|
|
const double dHysteresis )
|
|
|
|
{
|
|
|
|
// apply hysteresis
|
|
|
|
if ( dValue > static_cast<double> ( iOldValue ) )
|
|
|
|
{
|
|
|
|
return round ( dValue - dHysteresis );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return round ( dValue + dHysteresis );
|
|
|
|
}
|
|
|
|
}
|
2011-06-11 20:18:46 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Precise time ----------------------------------------------------------------
|
|
|
|
// required for ping measurement
|
|
|
|
class CPreciseTime
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
#ifdef _WIN32
|
|
|
|
// for the Windows version we have to define a minimum timer precision
|
|
|
|
// -> set it to 1 ms
|
|
|
|
CPreciseTime() { timeBeginPeriod ( 1 ); }
|
|
|
|
virtual ~CPreciseTime() { timeEndPeriod ( 1 ); }
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// precise time (on Windows the QTime is not precise enough)
|
|
|
|
int elapsed()
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
return timeGetTime();
|
2013-12-27 17:04:46 +01:00
|
|
|
#elif defined ( __APPLE__ ) || defined ( __MACOSX )
|
2014-06-12 21:28:39 +02:00
|
|
|
return mach_absolute_time() / 1000000; // convert ns in ms
|
2013-12-27 17:04:46 +01:00
|
|
|
#else
|
|
|
|
timespec tp;
|
|
|
|
clock_gettime ( CLOCK_MONOTONIC, &tp );
|
2016-02-07 15:02:30 +01:00
|
|
|
return tp.tv_sec * 1000 + tp.tv_nsec / 1000000; // convert ns in ms and add the seconds part
|
2011-06-11 20:18:46 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-03-13 18:10:30 +01:00
|
|
|
// Timing measurement ----------------------------------------------------------
|
|
|
|
// intended for debugging the timing jitter of the sound card or server timer
|
2015-03-16 17:17:31 +01:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
|
2015-03-13 18:10:30 +01:00
|
|
|
class CTimingMeas
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CTimingMeas ( const int iNNMeas, const QString strNFName = "" ) :
|
|
|
|
iNumMeas ( iNNMeas ), vElapsedTimes ( iNNMeas ), strFileName ( strNFName ) { Reset(); }
|
|
|
|
|
|
|
|
void Reset() { iCnt = -1; }
|
|
|
|
void Measure()
|
|
|
|
{
|
|
|
|
// exclude the very first measurement (initialization phase)
|
|
|
|
if ( iCnt == -1 )
|
|
|
|
{
|
|
|
|
iCnt = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// store current measurement
|
|
|
|
vElapsedTimes[iCnt++] = ElapsedTimer.nsecsElapsed();
|
|
|
|
|
|
|
|
// reset count if number of measurements are done
|
|
|
|
if ( iCnt >= iNumMeas )
|
|
|
|
{
|
|
|
|
iCnt = 0;
|
|
|
|
|
|
|
|
// store results in a file if file name is given
|
|
|
|
if ( !strFileName.isEmpty() )
|
|
|
|
{
|
|
|
|
QFile File ( strFileName );
|
|
|
|
|
|
|
|
if ( File.open ( QIODevice::WriteOnly | QIODevice::Text ) )
|
|
|
|
{
|
|
|
|
QTextStream streamFile ( &File );
|
|
|
|
for ( int i = 0; i < iNumMeas; i++ )
|
|
|
|
{
|
|
|
|
// convert ns in ms and store the value
|
2015-11-20 13:09:16 +01:00
|
|
|
streamFile << i << " " << static_cast<double> ( vElapsedTimes[i] ) / 1000000 << endl;
|
2015-03-13 18:10:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ElapsedTimer.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
int iNumMeas;
|
|
|
|
CVector<int> vElapsedTimes;
|
|
|
|
QString strFileName;
|
|
|
|
QElapsedTimer ElapsedTimer;
|
|
|
|
int iCnt;
|
|
|
|
};
|
2015-03-16 17:17:31 +01:00
|
|
|
#endif
|
2015-03-13 18:10:30 +01:00
|
|
|
|
|
|
|
|
2011-06-11 20:18:46 +02:00
|
|
|
/******************************************************************************\
|
|
|
|
* Statistics *
|
|
|
|
\******************************************************************************/
|
|
|
|
// Error rate measurement ------------------------------------------------------
|
|
|
|
class CErrorRate
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CErrorRate() {}
|
|
|
|
|
|
|
|
void Init ( const int iHistoryLength,
|
|
|
|
const bool bNBlockOnDoubleErr = false )
|
|
|
|
{
|
|
|
|
// initialize buffer (use "no data result" of 1.0 which stands for the
|
|
|
|
// worst error rate possible)
|
|
|
|
ErrorsMovAvBuf.Init ( iHistoryLength, 1.0 );
|
|
|
|
|
|
|
|
bPreviousState = true;
|
|
|
|
|
|
|
|
// store setting
|
|
|
|
bBlockOnDoubleErrors = bNBlockOnDoubleErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Reset()
|
|
|
|
{
|
|
|
|
ErrorsMovAvBuf.Reset();
|
|
|
|
bPreviousState = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Update ( const bool bState )
|
|
|
|
{
|
|
|
|
// if two states were false, do not use the new value
|
|
|
|
if ( bBlockOnDoubleErrors && bPreviousState && bState )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// add errors as values 0 and 1 to get correct error rate average
|
|
|
|
if ( bState )
|
|
|
|
{
|
|
|
|
ErrorsMovAvBuf.Add ( 1 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ErrorsMovAvBuf.Add ( 0 );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// store state
|
|
|
|
bPreviousState = bState;
|
|
|
|
}
|
|
|
|
|
|
|
|
double GetAverage() { return ErrorsMovAvBuf.GetAverage(); }
|
2011-06-18 14:01:36 +02:00
|
|
|
double InitializationState() { return ErrorsMovAvBuf.InitializationState(); }
|
2011-06-11 20:18:46 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
CMovingAv<char> ErrorsMovAvBuf;
|
|
|
|
bool bBlockOnDoubleErrors;
|
|
|
|
bool bPreviousState;
|
|
|
|
};
|