diff --git a/src/server.cpp b/src/server.cpp index 8fbed3d0e3..186cc44991 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -24,192 +24,6 @@ #include "server.h" -// CHighPrecisionTimer implementation ****************************************** -#ifdef _WIN32 -CHighPrecisionTimer::CHighPrecisionTimer ( const bool bNewUseDoubleSystemFrameSize ) : bUseDoubleSystemFrameSize ( bNewUseDoubleSystemFrameSize ) -{ - // add some error checking, the high precision timer implementation only - // supports 64 and 128 samples frame size at 48 kHz sampling rate -# if ( SYSTEM_FRAME_SIZE_SAMPLES != 64 ) && ( DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES != 128 ) -# error "Only system frame size of 64 and 128 samples is supported by this module" -# endif -# if ( SYSTEM_SAMPLE_RATE_HZ != 48000 ) -# error "Only a system sample rate of 48 kHz is supported by this module" -# endif - - // Since QT only supports a minimum timer resolution of 1 ms but for our - // server we require a timer interval of 2.333 ms for 128 samples - // frame size at 48 kHz sampling rate. - // To support this interval, we use a timer with 2 ms resolution for 128 - // samples frame size and 1 ms resolution for 64 samples frame size. - // Then we fire the actual frame timer if the error to the actual - // required interval is minimum. - veciTimeOutIntervals.Init ( 3 ); - - // for 128 sample frame size at 48 kHz sampling rate with 2 ms timer resolution: - // actual intervals: 0.0 2.666 5.333 8.0 - // quantized to 2 ms: 0 2 6 8 (0) - // for 64 sample frame size at 48 kHz sampling rate with 1 ms timer resolution: - // actual intervals: 0.0 1.333 2.666 4.0 - // quantized to 2 ms: 0 1 3 4 (0) - veciTimeOutIntervals[0] = 0; - veciTimeOutIntervals[1] = 1; - veciTimeOutIntervals[2] = 0; - - Timer.setTimerType ( Qt::PreciseTimer ); - - // connect timer timeout signal - QObject::connect ( &Timer, &QTimer::timeout, this, &CHighPrecisionTimer::OnTimer ); -} - -void CHighPrecisionTimer::Start() -{ - // reset position pointer and counter - iCurPosInVector = 0; - iIntervalCounter = 0; - - if ( bUseDoubleSystemFrameSize ) - { - // start internal timer with 2 ms resolution for 128 samples frame size - Timer.start ( 2 ); - } - else - { - // start internal timer with 1 ms resolution for 64 samples frame size - Timer.start ( 1 ); - } -} - -void CHighPrecisionTimer::Stop() -{ - // stop timer - Timer.stop(); -} - -void CHighPrecisionTimer::OnTimer() -{ - // check if maximum number of high precision timer intervals are - // finished - if ( veciTimeOutIntervals[iCurPosInVector] == iIntervalCounter ) - { - // reset interval counter - iIntervalCounter = 0; - - // go to next position in vector, take care of wrap around - iCurPosInVector++; - if ( iCurPosInVector == veciTimeOutIntervals.Size() ) - { - iCurPosInVector = 0; - } - - // minimum time error to actual required timer interval is reached, - // emit signal for server - emit timeout(); - } - else - { - // next high precision timer interval - iIntervalCounter++; - } -} -#else // Mac and Linux -CHighPrecisionTimer::CHighPrecisionTimer ( const bool bUseDoubleSystemFrameSize ) : bRun ( false ) -{ - // calculate delay in ns - uint64_t iNsDelay; - - if ( bUseDoubleSystemFrameSize ) - { - iNsDelay = ( (uint64_t) DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES * 1000000000 ) / (uint64_t) SYSTEM_SAMPLE_RATE_HZ; // in ns - } - else - { - iNsDelay = ( (uint64_t) SYSTEM_FRAME_SIZE_SAMPLES * 1000000000 ) / (uint64_t) SYSTEM_SAMPLE_RATE_HZ; // in ns - } - -# if defined( __APPLE__ ) || defined( __MACOSX ) - // calculate delay in mach absolute time - struct mach_timebase_info timeBaseInfo; - mach_timebase_info ( &timeBaseInfo ); - - Delay = ( iNsDelay * (uint64_t) timeBaseInfo.denom ) / (uint64_t) timeBaseInfo.numer; -# else - // set delay - Delay = iNsDelay; -# endif -} - -void CHighPrecisionTimer::Start() -{ - // only start if not already running - if ( !bRun ) - { - // set run flag - bRun = true; - - // set initial end time -# if defined( __APPLE__ ) || defined( __MACOSX ) - NextEnd = mach_absolute_time() + Delay; -# else - clock_gettime ( CLOCK_MONOTONIC, &NextEnd ); - - NextEnd.tv_nsec += Delay; - if ( NextEnd.tv_nsec >= 1000000000L ) - { - NextEnd.tv_sec++; - NextEnd.tv_nsec -= 1000000000L; - } -# endif - - // start thread - QThread::start ( QThread::TimeCriticalPriority ); - } -} - -void CHighPrecisionTimer::Stop() -{ - // set flag so that thread can leave the main loop - bRun = false; - - // give thread some time to terminate - wait ( 5000 ); -} - -void CHighPrecisionTimer::run() -{ - // loop until the thread shall be terminated - while ( bRun ) - { - // call processing routine by fireing signal - - //### TODO: BEGIN ###// - // by emit a signal we leave the high priority thread -> maybe use some - // other connection type to have something like a true callback, e.g. - // "Qt::DirectConnection" -> Can this work? - emit timeout(); - //### TODO: END ###// - - // now wait until the next buffer shall be processed (we - // use the "increment method" to make sure we do not introduce - // a timing drift) -# if defined( __APPLE__ ) || defined( __MACOSX ) - mach_wait_until ( NextEnd ); - - NextEnd += Delay; -# else - clock_nanosleep ( CLOCK_MONOTONIC, TIMER_ABSTIME, &NextEnd, NULL ); - - NextEnd.tv_nsec += Delay; - if ( NextEnd.tv_nsec >= 1000000000L ) - { - NextEnd.tv_sec++; - NextEnd.tv_nsec -= 1000000000L; - } -# endif - } -} -#endif - // CServer implementation ****************************************************** CServer::CServer ( const int iNewMaxNumChan, const QString& strLoggingFileName, diff --git a/src/server.h b/src/server.h index c76aa99147..89560adeb3 100644 --- a/src/server.h +++ b/src/server.h @@ -25,7 +25,6 @@ #pragma once #include -#include #include #include #include @@ -52,71 +51,6 @@ #define INVALID_CHANNEL_ID ( MAX_NUM_CHANNELS + 1 ) /* Classes ********************************************************************/ -#if ( defined( WIN32 ) || defined( _WIN32 ) ) -// using QTimer for Windows -class CHighPrecisionTimer : public QObject -{ - Q_OBJECT - -public: - CHighPrecisionTimer ( const bool bNewUseDoubleSystemFrameSize ); - - void Start(); - void Stop(); - bool isActive() const { return Timer.isActive(); } - -protected: - QTimer Timer; - CVector veciTimeOutIntervals; - int iCurPosInVector; - int iIntervalCounter; - bool bUseDoubleSystemFrameSize; - -public slots: - void OnTimer(); - -signals: - void timeout(); -}; -#else -// using mach timers for Mac and nanosleep for Linux -# if defined( __APPLE__ ) || defined( __MACOSX ) -# include -# include -# include -# else -# include -# endif - -class CHighPrecisionTimer : public QThread -{ - Q_OBJECT - -public: - CHighPrecisionTimer ( const bool bUseDoubleSystemFrameSize ); - - void Start(); - void Stop(); - bool isActive() { return bRun; } - -protected: - virtual void run(); - - bool bRun; - -# if defined( __APPLE__ ) || defined( __MACOSX ) - uint64_t Delay; - uint64_t NextEnd; -# else - long Delay; - timespec NextEnd; -# endif - -signals: - void timeout(); -}; -#endif - template class CServerSlots : public CServerSlots { diff --git a/src/sound/jack/sound.h b/src/sound/jack/sound.h index e37e58e210..eaf26b270e 100644 --- a/src/sound/jack/sound.h +++ b/src/sound/jack/sound.h @@ -34,15 +34,15 @@ #include #include #include -#include "../../util.h" -#include "../soundbase.h" -#include "../../global.h" - #if WITH_JACK # include # include #endif +#include "../../global.h" +#include "../../util.h" +#include "../soundbase.h" + /* Definitions ****************************************************************/ #define NUM_IN_OUT_CHANNELS 2 // always stereo @@ -116,7 +116,6 @@ class CSound : public CSoundBase }; #else // no sound -> dummy class definition -# include "server.h" class CSound : public CSoundBase { Q_OBJECT diff --git a/src/translation/translation_de_DE.qm b/src/translation/translation_de_DE.qm index 640ad998d3..f314fa857b 100644 Binary files a/src/translation/translation_de_DE.qm and b/src/translation/translation_de_DE.qm differ diff --git a/src/translation/translation_es_ES.qm b/src/translation/translation_es_ES.qm index 21d32178c0..6a2c7c5522 100644 Binary files a/src/translation/translation_es_ES.qm and b/src/translation/translation_es_ES.qm differ diff --git a/src/translation/translation_fr_FR.qm b/src/translation/translation_fr_FR.qm index 217d5cabc9..b7ff6f82e1 100644 Binary files a/src/translation/translation_fr_FR.qm and b/src/translation/translation_fr_FR.qm differ diff --git a/src/translation/translation_it_IT.qm b/src/translation/translation_it_IT.qm index 6ddbd333c4..1e6822f151 100644 Binary files a/src/translation/translation_it_IT.qm and b/src/translation/translation_it_IT.qm differ diff --git a/src/translation/translation_nl_NL.qm b/src/translation/translation_nl_NL.qm index 66e1826284..bc9c147042 100644 Binary files a/src/translation/translation_nl_NL.qm and b/src/translation/translation_nl_NL.qm differ diff --git a/src/translation/translation_pl_PL.qm b/src/translation/translation_pl_PL.qm index 8fa31f508a..5ab7334c8d 100644 Binary files a/src/translation/translation_pl_PL.qm and b/src/translation/translation_pl_PL.qm differ diff --git a/src/translation/translation_pt_BR.qm b/src/translation/translation_pt_BR.qm index e493272883..a3b2fedf26 100644 Binary files a/src/translation/translation_pt_BR.qm and b/src/translation/translation_pt_BR.qm differ diff --git a/src/translation/translation_pt_PT.qm b/src/translation/translation_pt_PT.qm index 8ed2aead09..ca13552e99 100644 Binary files a/src/translation/translation_pt_PT.qm and b/src/translation/translation_pt_PT.qm differ diff --git a/src/translation/translation_sk_SK.qm b/src/translation/translation_sk_SK.qm index 21f9280a7f..97aa86372a 100644 Binary files a/src/translation/translation_sk_SK.qm and b/src/translation/translation_sk_SK.qm differ diff --git a/src/translation/translation_sv_SE.qm b/src/translation/translation_sv_SE.qm index 0f8124f904..5023e573ed 100644 Binary files a/src/translation/translation_sv_SE.qm and b/src/translation/translation_sv_SE.qm differ diff --git a/src/translation/translation_zh_CN.qm b/src/translation/translation_zh_CN.qm index c081af62c9..5e27a73ab5 100644 Binary files a/src/translation/translation_zh_CN.qm and b/src/translation/translation_zh_CN.qm differ diff --git a/src/util.cpp b/src/util.cpp index 0e523ad8a2..8209fec2bc 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -23,9 +23,6 @@ \******************************************************************************/ #include "util.h" -#ifndef SERVER_ONLY -# include "client.h" -#endif /* Implementation *************************************************************/ // Input level meter implementation -------------------------------------------- @@ -377,6 +374,192 @@ void CAudioReverb::Process ( CVector& vecsStereoInOut, const bool bReve } } +// CHighPrecisionTimer implementation ****************************************** +#ifdef _WIN32 +CHighPrecisionTimer::CHighPrecisionTimer ( const bool bNewUseDoubleSystemFrameSize ) : bUseDoubleSystemFrameSize ( bNewUseDoubleSystemFrameSize ) +{ + // add some error checking, the high precision timer implementation only + // supports 64 and 128 samples frame size at 48 kHz sampling rate +# if ( SYSTEM_FRAME_SIZE_SAMPLES != 64 ) && ( DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES != 128 ) +# error "Only system frame size of 64 and 128 samples is supported by this module" +# endif +# if ( SYSTEM_SAMPLE_RATE_HZ != 48000 ) +# error "Only a system sample rate of 48 kHz is supported by this module" +# endif + + // Since QT only supports a minimum timer resolution of 1 ms but for our + // server we require a timer interval of 2.333 ms for 128 samples + // frame size at 48 kHz sampling rate. + // To support this interval, we use a timer with 2 ms resolution for 128 + // samples frame size and 1 ms resolution for 64 samples frame size. + // Then we fire the actual frame timer if the error to the actual + // required interval is minimum. + veciTimeOutIntervals.Init ( 3 ); + + // for 128 sample frame size at 48 kHz sampling rate with 2 ms timer resolution: + // actual intervals: 0.0 2.666 5.333 8.0 + // quantized to 2 ms: 0 2 6 8 (0) + // for 64 sample frame size at 48 kHz sampling rate with 1 ms timer resolution: + // actual intervals: 0.0 1.333 2.666 4.0 + // quantized to 2 ms: 0 1 3 4 (0) + veciTimeOutIntervals[0] = 0; + veciTimeOutIntervals[1] = 1; + veciTimeOutIntervals[2] = 0; + + Timer.setTimerType ( Qt::PreciseTimer ); + + // connect timer timeout signal + QObject::connect ( &Timer, &QTimer::timeout, this, &CHighPrecisionTimer::OnTimer ); +} + +void CHighPrecisionTimer::Start() +{ + // reset position pointer and counter + iCurPosInVector = 0; + iIntervalCounter = 0; + + if ( bUseDoubleSystemFrameSize ) + { + // start internal timer with 2 ms resolution for 128 samples frame size + Timer.start ( 2 ); + } + else + { + // start internal timer with 1 ms resolution for 64 samples frame size + Timer.start ( 1 ); + } +} + +void CHighPrecisionTimer::Stop() +{ + // stop timer + Timer.stop(); +} + +void CHighPrecisionTimer::OnTimer() +{ + // check if maximum number of high precision timer intervals are + // finished + if ( veciTimeOutIntervals[iCurPosInVector] == iIntervalCounter ) + { + // reset interval counter + iIntervalCounter = 0; + + // go to next position in vector, take care of wrap around + iCurPosInVector++; + if ( iCurPosInVector == veciTimeOutIntervals.Size() ) + { + iCurPosInVector = 0; + } + + // minimum time error to actual required timer interval is reached, + // emit signal for server + emit timeout(); + } + else + { + // next high precision timer interval + iIntervalCounter++; + } +} +#else // Mac and Linux +CHighPrecisionTimer::CHighPrecisionTimer ( const bool bUseDoubleSystemFrameSize ) : bRun ( false ) +{ + // calculate delay in ns + uint64_t iNsDelay; + + if ( bUseDoubleSystemFrameSize ) + { + iNsDelay = ( (uint64_t) DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES * 1000000000 ) / (uint64_t) SYSTEM_SAMPLE_RATE_HZ; // in ns + } + else + { + iNsDelay = ( (uint64_t) SYSTEM_FRAME_SIZE_SAMPLES * 1000000000 ) / (uint64_t) SYSTEM_SAMPLE_RATE_HZ; // in ns + } + +# if defined( __APPLE__ ) || defined( __MACOSX ) + // calculate delay in mach absolute time + struct mach_timebase_info timeBaseInfo; + mach_timebase_info ( &timeBaseInfo ); + + Delay = ( iNsDelay * (uint64_t) timeBaseInfo.denom ) / (uint64_t) timeBaseInfo.numer; +# else + // set delay + Delay = iNsDelay; +# endif +} + +void CHighPrecisionTimer::Start() +{ + // only start if not already running + if ( !bRun ) + { + // set run flag + bRun = true; + + // set initial end time +# if defined( __APPLE__ ) || defined( __MACOSX ) + NextEnd = mach_absolute_time() + Delay; +# else + clock_gettime ( CLOCK_MONOTONIC, &NextEnd ); + + NextEnd.tv_nsec += Delay; + if ( NextEnd.tv_nsec >= 1000000000L ) + { + NextEnd.tv_sec++; + NextEnd.tv_nsec -= 1000000000L; + } +# endif + + // start thread + QThread::start ( QThread::TimeCriticalPriority ); + } +} + +void CHighPrecisionTimer::Stop() +{ + // set flag so that thread can leave the main loop + bRun = false; + + // give thread some time to terminate + wait ( 5000 ); +} + +void CHighPrecisionTimer::run() +{ + // loop until the thread shall be terminated + while ( bRun ) + { + // call processing routine by fireing signal + + //### TODO: BEGIN ###// + // by emit a signal we leave the high priority thread -> maybe use some + // other connection type to have something like a true callback, e.g. + // "Qt::DirectConnection" -> Can this work? + emit timeout(); + //### TODO: END ###// + + // now wait until the next buffer shall be processed (we + // use the "increment method" to make sure we do not introduce + // a timing drift) +# if defined( __APPLE__ ) || defined( __MACOSX ) + mach_wait_until ( NextEnd ); + + NextEnd += Delay; +# else + clock_nanosleep ( CLOCK_MONOTONIC, TIMER_ABSTIME, &NextEnd, NULL ); + + NextEnd.tv_nsec += Delay; + if ( NextEnd.tv_nsec >= 1000000000L ) + { + NextEnd.tv_sec++; + NextEnd.tv_nsec -= 1000000000L; + } +# endif + } +} +#endif + /******************************************************************************\ * GUI Utilities * \******************************************************************************/ diff --git a/src/util.h b/src/util.h index cb31e9c7ca..d2cf75480a 100644 --- a/src/util.h +++ b/src/util.h @@ -23,11 +23,39 @@ \******************************************************************************/ #pragma once - +#include +#include +#ifdef _WIN32 +# include +# include +# include +# include +#elif defined( __APPLE__ ) || defined( __MACOSX ) +// using mach timers for Mac +# include +# include +# include +#else +// using mach nanosleep for Linux +# include +#endif #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _WIN32 +# include +#endif #ifndef HEADLESS # include # include @@ -43,30 +71,8 @@ # include # include "ui_aboutdlgbase.h" #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + #include "global.h" -#ifdef _WIN32 -# include -# include -# include -# include -#elif defined( __APPLE__ ) || defined( __MACOSX ) -# include -# include -# include -#else -# include -#endif #ifndef SERVER_ONLY class CClient; // forward declaration of CClient @@ -369,7 +375,7 @@ public slots: void keyPressEvent ( QKeyEvent* pEvent ) { // block escape key - if ( pEvent->key() != Qt::Key_Escape ) + if ( ( this->windowFlags() & Qt::Dialog ) != 0 || pEvent->key() != Qt::Key_Escape ) { # ifdef ANDROID if ( pEvent->key() == Qt::Key_Back ) @@ -1205,7 +1211,9 @@ class MathUtils } }; -// Timing measurement ---------------------------------------------------------- +/******************************************************************************\ +* Timing measurement * +\******************************************************************************/ // intended for debugging the timing jitter of the sound card or server timer class CTimingMeas { @@ -1261,6 +1269,64 @@ class CTimingMeas int iCnt; }; +// High resolution timer +#if ( defined( WIN32 ) || defined( _WIN32 ) ) +// using QTimer for Windows +class CHighPrecisionTimer : public QObject +{ + Q_OBJECT + +public: + CHighPrecisionTimer ( const bool bNewUseDoubleSystemFrameSize ); + + void Start(); + void Stop(); + bool isActive() const { return Timer.isActive(); } + +protected: + QTimer Timer; + CVector veciTimeOutIntervals; + int iCurPosInVector; + int iIntervalCounter; + bool bUseDoubleSystemFrameSize; + +public slots: + void OnTimer(); + +signals: + void timeout(); +}; +#else + +class CHighPrecisionTimer : public QThread +{ + Q_OBJECT + +public: + CHighPrecisionTimer ( const bool bUseDoubleSystemFrameSize ); + + void Start(); + void Stop(); + bool isActive() { return bRun; } + +protected: + virtual void run(); + + bool bRun; + +# if defined( __APPLE__ ) || defined( __MACOSX ) + uint64_t Delay; + uint64_t NextEnd; +# else + long Delay; + timespec NextEnd; +# endif + +signals: + void timeout(); +}; +#endif + /******************************************************************************\ * Statistics * \******************************************************************************/