diff --git a/CMakeLists.txt b/CMakeLists.txt index 72a7897de61..c408073eeb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1174,6 +1174,7 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL src/util/fileaccess.cpp src/util/fileinfo.cpp src/util/filename.cpp + src/util/font.cpp src/util/imagefiledata.cpp src/util/imagefiledata.cpp src/util/imageutils.cpp @@ -1200,7 +1201,6 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL src/util/tapfilter.cpp src/util/task.cpp src/util/taskmonitor.cpp - src/util/threadcputimer.cpp src/util/time.cpp src/util/timer.cpp src/util/valuetransformer.cpp @@ -1470,7 +1470,6 @@ set(MIXXX_LIB_PRECOMPILED_HEADER src/util/taskmonitor.h src/util/thread_affinity.h src/util/thread_annotations.h - src/util/threadcputimer.h src/util/time.h src/util/timer.h src/util/trace.h diff --git a/src/analyzer/analyzerwaveform.h b/src/analyzer/analyzerwaveform.h index 4771cc50993..ccdafd5242d 100644 --- a/src/analyzer/analyzerwaveform.h +++ b/src/analyzer/analyzerwaveform.h @@ -46,16 +46,16 @@ struct WaveformStride { inline void store(WaveformData* data) { for (int i = 0; i < ChannelCount; ++i) { WaveformData& datum = *(data + i); - datum.filtered.all = static_cast(math_min(255.0, + datum.filtered.all = static_cast(std::min(255.0, m_postScaleConversion * m_overallData[i] + 0.5)); - datum.filtered.low = static_cast(math_min(255.0, + datum.filtered.low = static_cast(std::min(255.0, m_postScaleConversion * m_filteredData[i][Low] + 0.5)); - datum.filtered.mid = static_cast(math_min(255.0, + datum.filtered.mid = static_cast(std::min(255.0, m_postScaleConversion * m_filteredData[i][Mid] + 0.5)); - datum.filtered.high = static_cast(math_min(255.0, + datum.filtered.high = static_cast(std::min(255.0, m_postScaleConversion * m_filteredData[i][High] + 0.5)); for (int stemIdx = 0; stemIdx < m_stemCount; stemIdx++) { - datum.stems[stemIdx] = static_cast(math_min(255.0, + datum.stems[stemIdx] = static_cast(std::min(255.0, m_postScaleConversion * m_stemData[i][stemIdx] + 0.5)); } } @@ -78,17 +78,17 @@ struct WaveformStride { if (m_averageDivisor) { for (int i = 0; i < ChannelCount; ++i) { WaveformData& datum = *(data + i); - datum.filtered.all = static_cast(math_min(255.0, + datum.filtered.all = static_cast(std::min(255.0, m_postScaleConversion * m_averageOverallData[i] / m_averageDivisor + 0.5)); - datum.filtered.low = static_cast(math_min(255.0, + datum.filtered.low = static_cast(std::min(255.0, m_postScaleConversion * m_averageFilteredData[i][Low] / m_averageDivisor + 0.5)); - datum.filtered.mid = static_cast(math_min(255.0, + datum.filtered.mid = static_cast(std::min(255.0, m_postScaleConversion * m_averageFilteredData[i][Mid] / m_averageDivisor + 0.5)); - datum.filtered.high = static_cast(math_min(255.0, + datum.filtered.high = static_cast(std::min(255.0, m_postScaleConversion * m_averageFilteredData[i][High] / m_averageDivisor + 0.5)); @@ -97,13 +97,13 @@ struct WaveformStride { // This is the case if The Overview Waveform has more samples than the detailed waveform for (int i = 0; i < ChannelCount; ++i) { WaveformData& datum = *(data + i); - datum.filtered.all = static_cast(math_min(255.0, + datum.filtered.all = static_cast(std::min(255.0, m_postScaleConversion * m_overallData[i] + 0.5)); - datum.filtered.low = static_cast(math_min(255.0, + datum.filtered.low = static_cast(std::min(255.0, m_postScaleConversion * m_filteredData[i][Low] + 0.5)); - datum.filtered.mid = static_cast(math_min(255.0, + datum.filtered.mid = static_cast(std::min(255.0, m_postScaleConversion * m_filteredData[i][Mid] + 0.5)); - datum.filtered.high = static_cast(math_min(255.0, + datum.filtered.high = static_cast(std::min(255.0, m_postScaleConversion * m_filteredData[i][High] + 0.5)); } } diff --git a/src/database/schemamanager.cpp b/src/database/schemamanager.cpp index a17dc47e9a3..5f0ef182918 100644 --- a/src/database/schemamanager.cpp +++ b/src/database/schemamanager.cpp @@ -1,11 +1,14 @@ #include "database/schemamanager.h" +#include +#include +#include + #include "util/assert.h" #include "util/db/fwdsqlquery.h" #include "util/db/sqltransaction.h" #include "util/logger.h" #include "util/math.h" -#include "util/optional.h" #include "util/xml.h" namespace { diff --git a/src/effects/backends/builtin/autopaneffect.h b/src/effects/backends/builtin/autopaneffect.h index 50dd2f7d228..4994ea0e1a7 100644 --- a/src/effects/backends/builtin/autopaneffect.h +++ b/src/effects/backends/builtin/autopaneffect.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "effects/backends/effectprocessor.h" #include "engine/filters/enginefilterpansingle.h" @@ -13,27 +14,25 @@ // somewhere else (I hear clicks when I change the period of flanger for example). class RampedSample { public: - inline RampedSample() + constexpr RampedSample() : ramped(false), maxDifference(1.0f), currentValue(0), initialized(false) { } - virtual ~RampedSample(){}; - - inline void setRampingThreshold(const float newMaxDifference) { + constexpr void setRampingThreshold(float newMaxDifference) { maxDifference = newMaxDifference; } - inline void setWithRampingApplied(const float newValue) { + constexpr void setWithRampingApplied(float newValue) { if (!initialized) { currentValue = newValue; initialized = true; } else { float difference = newValue - currentValue; - if (fabs(difference) > maxDifference) { - currentValue += difference / fabs(difference) * maxDifference; + if (abs(difference) > maxDifference) { + currentValue += difference / abs(difference) * maxDifference; ramped = true; } else { currentValue = newValue; @@ -42,7 +41,7 @@ class RampedSample { } } - inline operator float() { + constexpr operator float() { return currentValue; } diff --git a/src/effects/backends/builtin/compressoreffect.cpp b/src/effects/backends/builtin/compressoreffect.cpp index cea9b622f4b..311256fd2ad 100644 --- a/src/effects/backends/builtin/compressoreffect.cpp +++ b/src/effects/backends/builtin/compressoreffect.cpp @@ -1,5 +1,7 @@ #include "effects/backends/builtin/compressoreffect.h" +#include "util/math.h" + namespace { // Auto make up time is empirically selected parameter, which is good enough for most cases constexpr double defaultMakeUpAttackMs = 150; diff --git a/src/effects/backends/builtin/distortioneffect.h b/src/effects/backends/builtin/distortioneffect.h index 70dd90cae16..00e077dc7d6 100644 --- a/src/effects/backends/builtin/distortioneffect.h +++ b/src/effects/backends/builtin/distortioneffect.h @@ -91,7 +91,7 @@ class DistortionEffect : public EffectProcessorImpl { pState->m_previousMakeUpGain = gain; // Crossfade - CSAMPLE crossfadeParam = math_min(driveParam / ModeParams::crossfadeEndParam, 1.f); + CSAMPLE crossfadeParam = std::min(driveParam / ModeParams::crossfadeEndParam, 1.f); SampleUtil::applyRampingGain(pOutput, pState->m_crossfadeParameter, crossfadeParam, diff --git a/src/effects/backends/builtin/phasereffect.cpp b/src/effects/backends/builtin/phasereffect.cpp index 709d23d09a8..74f0c4b4e6f 100644 --- a/src/effects/backends/builtin/phasereffect.cpp +++ b/src/effects/backends/builtin/phasereffect.cpp @@ -2,6 +2,7 @@ #include "effects/backends/effectmanifest.h" #include "engine/effects/engineeffectparameter.h" +#include "util/math.h" namespace { constexpr unsigned int updateCoef = 32; diff --git a/src/effects/backends/builtin/pitchshifteffect.cpp b/src/effects/backends/builtin/pitchshifteffect.cpp index 4d5dbd726c5..1df0d7165ae 100644 --- a/src/effects/backends/builtin/pitchshifteffect.cpp +++ b/src/effects/backends/builtin/pitchshifteffect.cpp @@ -6,6 +6,7 @@ #include "effects/backends/effectmanifest.h" #include "engine/effects/engineeffectparameter.h" +#include "util/math.h" #include "util/sample.h" namespace { diff --git a/src/encoder/encodersndfileflac.cpp b/src/encoder/encodersndfileflac.cpp index 7fb40d8e88f..00637f0b15f 100644 --- a/src/encoder/encodersndfileflac.cpp +++ b/src/encoder/encodersndfileflac.cpp @@ -1,6 +1,7 @@ #include "encoder/encodersndfileflac.h" #include +#include #include "encoder/encoderflacsettings.h" @@ -13,14 +14,14 @@ void convertFloat32ToIntFormat(int* pDest, const CSAMPLE* pSrc, SINT numSamples, if (format & SF_FORMAT_PCM_16) { // note: LOOP VECTORIZED" for (SINT i = 0; i < numSamples; ++i) { - pDest[i] = static_cast(math_clamp(pSrc[i] * kFloatToIntConversionFactor, + pDest[i] = static_cast(std::clamp(pSrc[i] * kFloatToIntConversionFactor, static_cast(static_cast(INT_MIN & 0xFFFF0000)), static_cast(static_cast(INT_MAX & 0xFFFF0000)))); } } else if (format & SF_FORMAT_PCM_24) { // note: LOOP VECTORIZED" for (SINT i = 0; i < numSamples; ++i) { - pDest[i] = static_cast(math_clamp(pSrc[i] * kFloatToIntConversionFactor, + pDest[i] = static_cast(std::clamp(pSrc[i] * kFloatToIntConversionFactor, static_cast(static_cast(INT_MIN & 0xFFFFFF00)), static_cast(static_cast(INT_MAX & 0xFFFFFF00)))); } @@ -62,7 +63,7 @@ void EncoderSndfileFlac::encodeBuffer(const CSAMPLE* pBuffer, const int iBufferS if (m_pClampBuffer) { SINT numSamplesLeft = iBufferSize; while (numSamplesLeft > 0) { - const SINT numSamplesToWrite = math_min(numSamplesLeft, kEncBufferSize); + const SINT numSamplesToWrite = std::min(numSamplesLeft, kEncBufferSize); convertFloat32ToIntFormat(m_pClampBuffer.get(), pBuffer, numSamplesToWrite, diff --git a/src/engine/controls/ratecontrol.cpp b/src/engine/controls/ratecontrol.cpp index 8e1c065ccda..e036eb16ab8 100644 --- a/src/engine/controls/ratecontrol.cpp +++ b/src/engine/controls/ratecontrol.cpp @@ -165,19 +165,8 @@ RateControl::RateControl(const QString& group, m_pJog = new ControlObject(ConfigKey(group, "jog")); - m_pJogFilter = new Rotary(); // FIXME: This should be dependent on sample rate/block size or something - m_pJogFilter->setFilterLength(25); - -// // Update Internal Settings -// // Set Pitchbend Mode -// m_eRateRampMode = static_cast( -// getConfig()->getValue(ConfigKey("[Controls]","RateRamp"), -// static_cast(RampMode::Stepping))); - -// // Set the Sensitivity -// m_iRateRampSensitivity = -// getConfig()->getValueString(ConfigKey("[Controls]","RateRampSensitivity")).toInt(); + m_pJogFilter = new Rotary(25); m_pSyncMode = new ControlProxy(group, "sync_mode", this); } diff --git a/src/engine/enginesidechaincompressor.cpp b/src/engine/enginesidechaincompressor.cpp index 7ff4cb1b043..829b72fbc4a 100644 --- a/src/engine/enginesidechaincompressor.cpp +++ b/src/engine/enginesidechaincompressor.cpp @@ -1,6 +1,8 @@ +#include "engine/enginesidechaincompressor.h" + #include -#include "engine/enginesidechaincompressor.h" +#include "util/assert.h" EngineSideChainCompressor::EngineSideChainCompressor(const QString& group) : m_compressRatio(1.0), diff --git a/src/preferences/broadcastprofile.cpp b/src/preferences/broadcastprofile.cpp index b2d354561ad..e2e2ab2ede0 100644 --- a/src/preferences/broadcastprofile.cpp +++ b/src/preferences/broadcastprofile.cpp @@ -1,3 +1,8 @@ +#include "preferences/broadcastprofile.h" + +#include +#include +#include #include #include #include @@ -16,7 +21,6 @@ using namespace QKeychain; #endif // __QTKEYCHAIN__ #include "broadcast/defs_broadcast.h" -#include "broadcastprofile.h" #include "defs_urls.h" #include "errordialoghandler.h" #include "moc_broadcastprofile.cpp" diff --git a/src/skin/legacy/legacyskinparser.cpp b/src/skin/legacy/legacyskinparser.cpp index 4f401341259..09b7306cf43 100644 --- a/src/skin/legacy/legacyskinparser.cpp +++ b/src/skin/legacy/legacyskinparser.cpp @@ -10,6 +10,7 @@ #include #include "control/controlobject.h" +#include "control/controlpushbutton.h" #include "controllers/controllerlearningeventfilter.h" #include "controllers/controllermanager.h" #include "controllers/keyboard/keyboardeventfilter.h" @@ -2306,7 +2307,9 @@ void LegacySkinParser::setupConnections(const QDomNode& node, WBaseWidget* pWidg ValueTransformer* pTransformer = nullptr; QDomElement transform = m_pContext->selectElement(con, "Transform"); if (!transform.isNull()) { - pTransformer = ValueTransformer::parseFromXml(transform, *m_pContext); + pTransformer = + ValueTransformer::parseFromXml(transform, *m_pContext) + .release(); // TODO don't leak here } QString property; diff --git a/src/sources/audiosource.cpp b/src/sources/audiosource.cpp index 2b3d7525fee..6d4df8397b4 100644 --- a/src/sources/audiosource.cpp +++ b/src/sources/audiosource.cpp @@ -193,7 +193,7 @@ bool AudioSource::verifyReadable() { // Counterexample: The broken FAAD version 2.9.1 is able to open a file // but then fails to decode any sample frames. const SINT numSampleFrames = - math_min(kVerifyReadableMaxFrameCount, frameIndexRange().length()); + std::min(kVerifyReadableMaxFrameCount, frameIndexRange().length()); SampleBuffer sampleBuffer( m_signalInfo.frames2samples(numSampleFrames)); WritableSampleFrames writableSampleFrames( diff --git a/src/sources/readaheadframebuffer.cpp b/src/sources/readaheadframebuffer.cpp index 8613aac9c3d..838c2434728 100644 --- a/src/sources/readaheadframebuffer.cpp +++ b/src/sources/readaheadframebuffer.cpp @@ -288,7 +288,7 @@ WritableSampleFrames ReadAheadFrameBuffer::consumeAndFillBuffer( // Detect and handle unexpected discontinuities: Overlap if (inputRange.start() < outputRange.start()) { const auto overlapRange = IndexRange::between( - math_max(inputRange.start(), minOutputIndex), + std::max(inputRange.start(), minOutputIndex), outputRange.start()); DEBUG_ASSERT( overlapRange.orientation() != @@ -313,7 +313,7 @@ WritableSampleFrames ReadAheadFrameBuffer::consumeAndFillBuffer( } if (!isEmpty() && inputRange.start() < writeIndex()) { const auto overlapRange = IndexRange::between( - math_max(inputRange.start(), readIndex()), + std::max(inputRange.start(), readIndex()), writeIndex()); DEBUG_ASSERT( overlapRange.orientation() != @@ -340,7 +340,7 @@ WritableSampleFrames ReadAheadFrameBuffer::consumeAndFillBuffer( const auto precedingRange = IndexRange::between( inputRange.start(), - math_min(outputRange.start(), inputRange.end())); + std::min(outputRange.start(), inputRange.end())); #if VERBOSE_DEBUG_LOG kLogger.debug() << "Discarding input data" @@ -363,7 +363,7 @@ WritableSampleFrames ReadAheadFrameBuffer::consumeAndFillBuffer( const auto gapRange = IndexRange::between( outputRange.start(), - math_min(inputRange.start(), outputRange.end())); + std::min(inputRange.start(), outputRange.end())); DEBUG_ASSERT( gapRange.orientation() != IndexRange::Orientation::Backward); @@ -390,7 +390,7 @@ WritableSampleFrames ReadAheadFrameBuffer::consumeAndFillBuffer( const auto copyableFrameRange = IndexRange::between( outputRange.start(), - math_min(inputRange.end(), outputRange.end())); + std::min(inputRange.end(), outputRange.end())); DEBUG_ASSERT(copyableFrameRange.orientation() != IndexRange::Orientation::Backward); if (copyableFrameRange.orientation() == IndexRange::Orientation::Forward) { #if VERBOSE_DEBUG_LOG diff --git a/src/util/class.h b/src/util/class.h index 793a7726faa..7fbc82a1573 100644 --- a/src/util/class.h +++ b/src/util/class.h @@ -1,7 +1,11 @@ #pragma once -// A macro to disallow the copy constructor and operator= functions -// This should be used in the private: declarations for a class +// DEPRECATED: Adhere to the rule "the rule of zero" or "the rule of five". +// See https://en.cppreference.com/w/cpp/language/rule_of_three +// Rationale: If a class deals with ownership, it should do nothing more and explicitly +// define the behavior of all special member functions. +// This macro is sprinkled into lots of big classes and ignores the move-related SMF's. +// So its common use violates both principles and thus it should not be used anymore! #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&) = delete; \ void operator=(const TypeName&) = delete; diff --git a/src/util/compatibility/qatomic.h b/src/util/compatibility/qatomic.h index 20dc6004e3c..9b140eaf18a 100644 --- a/src/util/compatibility/qatomic.h +++ b/src/util/compatibility/qatomic.h @@ -9,24 +9,6 @@ // Until the minimum required Qt version of Mixxx is increased some utility // functions that work independently of the Qt version are needed. -template -inline T atomicLoadAcquire(const QAtomicInteger& atomicInt) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - return atomicInt.loadAcquire(); -#else - return atomicInt.load(); -#endif -} - -template -inline T* atomicLoadAcquire(const QAtomicPointer& atomicPtr) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - return atomicPtr.loadAcquire(); -#else - return atomicPtr.load(); -#endif -} - template inline T atomicLoadRelaxed(const QAtomicInteger& atomicInt) { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) @@ -45,15 +27,6 @@ inline T* atomicLoadRelaxed(const QAtomicPointer& atomicPtr) { #endif } -template -inline void atomicStoreRelaxed(QAtomicInteger& atomicInt, T newValue) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - atomicInt.storeRelaxed(newValue); -#else - atomicInt.store(newValue); -#endif -} - template inline void atomicStoreRelaxed(QAtomicPointer& atomicPtr, T* newValue) { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) diff --git a/src/util/font.cpp b/src/util/font.cpp new file mode 100644 index 00000000000..26cc6cee894 --- /dev/null +++ b/src/util/font.cpp @@ -0,0 +1,84 @@ +#include "util/font.h" + +#include +#include +#include +#include + +#include "util/cmdlineargs.h" + +namespace { + +bool addFont(const QString& path) { + int result = QFontDatabase::addApplicationFont(path); + if (result == -1) { + qWarning() << "Failed to add font:" << path; + return false; + } + + // In developer mode, spit out all the families / styles / sizes + // supported by the new font. + if (CmdlineArgs::Instance().getDeveloper()) { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QFontDatabase database; +#endif + QStringList pointSizesStr; + const QStringList families = QFontDatabase::applicationFontFamilies(result); + for (const QString& family : families) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const QStringList styles = QFontDatabase::styles(family); +#else + const QStringList styles = database.styles(family); +#endif + for (const QString& style : styles) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const QList pointSizes = QFontDatabase::pointSizes(family, style); +#else + const QList pointSizes = database.pointSizes(family, style); +#endif + pointSizesStr.clear(); + pointSizesStr.reserve(pointSizes.count()); + for (int point : pointSizes) { + pointSizesStr.append(QString::number(point)); + } + qDebug() << "FONT LOADED family:" << family + << "style:" << style + << "point sizes:" << pointSizesStr.join(","); + } + } + } + return true; +} + +} // namespace + +void FontUtils::initializeFonts(const QString& resourcePath) { + QDir fontsDir(resourcePath); + if (!fontsDir.cd("fonts")) { +#ifdef __LINUX__ + // If the fonts already have been installed via the package + // manager, this is okay. We currently have no way to verify that + // though. + qDebug() +#else + qWarning() +#endif + << "No fonts directory found in" << resourcePath; + return; + } + + QList files = fontsDir.entryInfoList( + QDir::NoDotAndDotDot | QDir::Files | QDir::Readable); + for (const QFileInfo& file : files) { + const QString& path = file.filePath(); + + // Skip text files (e.g. license files). For all others we let Qt tell + // us whether the font format is supported since there is no way to + // check other than adding. + if (path.endsWith(".txt", Qt::CaseInsensitive)) { + continue; + } + + addFont(path); + } +} diff --git a/src/util/font.h b/src/util/font.h index 42bb21f4701..dc47956809f 100644 --- a/src/util/font.h +++ b/src/util/font.h @@ -1,86 +1,7 @@ #pragma once -#include -#include -#include -#include +class QString; -#include "util/cmdlineargs.h" - -class FontUtils { - public: - static void initializeFonts(const QString& resourcePath) { - QDir fontsDir(resourcePath); - if (!fontsDir.cd("fonts")) { -#ifdef __LINUX__ - // If the fonts already have been installed via the package - // manager, this is okay. We currently have no way to verify that - // though. - qDebug() -#else - qWarning() -#endif - << "No fonts directory found in" << resourcePath; - return; - } - - QList files = fontsDir.entryInfoList( - QDir::NoDotAndDotDot | QDir::Files | QDir::Readable); - foreach (const QFileInfo& file, files) { - const QString& path = file.filePath(); - - // Skip text files (e.g. license files). For all others we let Qt tell - // us whether the font format is supported since there is no way to - // check other than adding. - if (path.endsWith(".txt", Qt::CaseInsensitive)) { - continue; - } - - addFont(path); - } - } - - static bool addFont(const QString& path) { - int result = QFontDatabase::addApplicationFont(path); - if (result == -1) { - qWarning() << "Failed to add font:" << path; - return false; - } - - // In developer mode, spit out all the families / styles / sizes - // supported by the new font. - if (CmdlineArgs::Instance().getDeveloper()) { -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - QFontDatabase database; -#endif - QStringList pointSizesStr; - const QStringList families = QFontDatabase::applicationFontFamilies(result); - for (const QString& family : families) { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - const QStringList styles = QFontDatabase::styles(family); -#else - const QStringList styles = database.styles(family); -#endif - for (const QString& style : styles) { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - const QList pointSizes = QFontDatabase::pointSizes(family, style); -#else - const QList pointSizes = database.pointSizes(family, style); -#endif - pointSizesStr.clear(); - pointSizesStr.reserve(pointSizes.count()); - for (int point : pointSizes) { - pointSizesStr.append(QString::number(point)); - } - qDebug() << "FONT LOADED family:" << family - << "style:" << style - << "point sizes:" << pointSizesStr.join(","); - } - } - } - return true; - } - - private: - FontUtils() {} -}; +namespace FontUtils { +void initializeFonts(const QString& resourcePath); +} // namespace FontUtils diff --git a/src/util/readaheadsamplebuffer.cpp b/src/util/readaheadsamplebuffer.cpp index 5e047d0822d..36ec6dd181d 100644 --- a/src/util/readaheadsamplebuffer.cpp +++ b/src/util/readaheadsamplebuffer.cpp @@ -53,7 +53,7 @@ void ReadAheadSampleBuffer::clear() { void ReadAheadSampleBuffer::adjustCapacity(SINT capacity) { DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; - SINT newCapacity = math_max(readableLength(), capacity); + SINT newCapacity = std::max(readableLength(), capacity); if (newCapacity != this->capacity()) { ReadAheadSampleBuffer tmp(*this, newCapacity); swap(tmp); @@ -65,7 +65,7 @@ void ReadAheadSampleBuffer::adjustCapacity(SINT capacity) { SampleBuffer::WritableSlice ReadAheadSampleBuffer::growForWriting(SINT maxWriteLength) { DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; - const SINT tailLength = math_min(maxWriteLength, writableLength()); + const SINT tailLength = std::min(maxWriteLength, writableLength()); const SampleBuffer::WritableSlice tailSlice( m_sampleBuffer, m_readableRange.end(), tailLength); m_readableRange.growBack(tailLength); @@ -77,7 +77,7 @@ SampleBuffer::WritableSlice ReadAheadSampleBuffer::growForWriting(SINT maxWriteL SINT ReadAheadSampleBuffer::shrinkAfterWriting(SINT maxShrinkLength) { DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; - const SINT shrinkLength = math_min(maxShrinkLength, readableLength()); + const SINT shrinkLength = std::min(maxShrinkLength, readableLength()); m_readableRange.shrinkBack(shrinkLength); // If the buffer has become empty reset the write head back to the start // of the available memory @@ -92,7 +92,7 @@ SINT ReadAheadSampleBuffer::shrinkAfterWriting(SINT maxShrinkLength) { SampleBuffer::ReadableSlice ReadAheadSampleBuffer::shrinkForReading(SINT maxReadLength) { DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; - const SINT headLength = math_min(maxReadLength, readableLength()); + const SINT headLength = std::min(maxReadLength, readableLength()); const SampleBuffer::ReadableSlice headSlice( m_sampleBuffer, m_readableRange.start(), headLength); m_readableRange.shrinkFront(headLength); diff --git a/src/util/regex.h b/src/util/regex.h index e3c59368d45..73fa32485e5 100644 --- a/src/util/regex.h +++ b/src/util/regex.h @@ -1,5 +1,7 @@ #pragma once +#include // for qt version checking + // QRegularExpression::escape was introduced in Qt 5.15. #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) #include @@ -9,21 +11,19 @@ #include #include -class RegexUtils { - public: - static QString fileExtensionsRegex(QStringList extensions) { - // Escape every extension appropriately - for (int i = 0; i < extensions.size(); ++i) { +namespace RegexUtils { + +inline QString fileExtensionsRegex(QStringList extensions) { + // Escape every extension appropriately + for (int i = 0; i < extensions.size(); ++i) { #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - extensions[i] = QRegularExpression::escape(extensions[i]); + extensions[i] = QRegularExpression::escape(extensions[i]); #else - extensions[i] = QRegExp::escape(extensions[i]); + extensions[i] = QRegExp::escape(extensions[i]); #endif - } - // Turn the list into a "\\.(jpg|gif|etc)$" style regex string - return QString("\\.(%1)$").arg(extensions.join("|")); } + // Turn the list into a "\\.(jpg|gif|etc)$" style regex string + return QStringLiteral("\\.(%1)$").arg(extensions.join('|')); +} - private: - RegexUtils() {} -}; +} // namespace RegexUtils diff --git a/src/util/rescaler.h b/src/util/rescaler.h index c0d6bb9f367..51460dd8311 100644 --- a/src/util/rescaler.h +++ b/src/util/rescaler.h @@ -1,22 +1,17 @@ #pragma once -class RescalerUtils { - public: +namespace RescalerUtils { +// converts a value on a linear scale to a 1/x scale staring at 1 +inline double linearToOneByX(double in, double inMin, double inMax, double outMax) { + double outRange = outMax - 1; + double inRange = inMax - inMin; + return outMax / (((inMax - in) / inRange * outRange) + 1); +} - // converts a value on a linear scale to a 1/x scale staring at 1 - static double linearToOneByX(double in, double inMin, double inMax, double outMax) { - double outRange = outMax - 1; - double inRange = inMax - inMin; - return outMax / (((inMax - in) / inRange * outRange) + 1); - } - - // converts value on a 1/x scale starting by 1 to a linear scale - static double oneByXToLinear(double in, double inMax, double outMin, double outMax) { - double outRange = outMax - outMin; - double inRange = inMax - 1; - return outMax - (((inMax / in) - 1) / inRange * outRange); - } - - private: - RescalerUtils() {} -}; +// converts value on a 1/x scale starting by 1 to a linear scale +inline double oneByXToLinear(double in, double inMax, double outMin, double outMax) { + double outRange = outMax - outMin; + double inRange = inMax - 1; + return outMax - (((inMax / in) - 1) / inRange * outRange); +} +}; // namespace RescalerUtils diff --git a/src/util/rlimit.h b/src/util/rlimit.h index 1f8b50ea6ec..8030517071f 100644 --- a/src/util/rlimit.h +++ b/src/util/rlimit.h @@ -2,11 +2,12 @@ #ifdef __LINUX__ -class RLimit { - public: - static unsigned int getCurRtPrio(); - static unsigned int getMaxRtPrio(); - static bool isRtPrioAllowed(); -}; +namespace RLimit { + +unsigned int getCurRtPrio(); +unsigned int getMaxRtPrio(); +bool isRtPrioAllowed(); + +} // namespace RLimit #endif // __LINUX__ diff --git a/src/util/rotary.cpp b/src/util/rotary.cpp index 45f3054d91a..63b63e764fe 100644 --- a/src/util/rotary.cpp +++ b/src/util/rotary.cpp @@ -1,93 +1,35 @@ #include "util/rotary.h" -#include +#include -constexpr int kiRotaryFilterMaxLen = 50; - -Rotary::Rotary() - : m_iFilterLength(kiRotaryFilterMaxLen), - m_iFilterPos(0), - m_pFilter(m_iFilterLength), - m_dCalibration(1.0), - m_dLastValue(0.0), - m_iCalibrationCount(0) { - for (int i = 0; i < m_iFilterLength; ++i) { - m_pFilter[i] = 0.; - } -} - -/* Note: There's probably a bug in this function (or this class) somewhere. - The filter function seems to be the cause of the "drifting" bug in the Hercules stuff. - What happens is that filter() gets called to do some magic to a value that's returned - from the Hercules device, and that magic adds "momentum" to it's motion (ie. it doesn't - stop dead when you stop spinning the jog wheels.) The problem with this "magic" is that - when herculeslinux.cpp passes the filtered value off to the wheel ControlObject (or what - have you), the ControlObject's internal value never goes back to zero properly. - - Albert (March 13, 2007) - */ -double Rotary::filter(double dValue) { - // Update filter buffer - m_pFilter[m_iFilterPos] = dValue/m_dCalibration; - m_iFilterPos = (m_iFilterPos+1)%m_iFilterLength; - - double dMagnitude = 0.; - for (int i=0; i= m_filterHistory.size()) { + return 0; } - dMagnitude /= (double)m_iFilterLength; - //qDebug() << "filter in " << dValue << ", out " << dMagnitude; - - m_dLastValue = dMagnitude; - - return dMagnitude; -} - -double Rotary::fillBuffer(double dValue) { - for (int i=0; i(m_filterHistory.size()); } -double Rotary::calibrateEnd() { - m_dCalibration /= (double)m_iCalibrationCount; - - qDebug() << "Calibration " << m_dCalibration << ", count " << m_iCalibrationCount; - - return m_dCalibration; -} - -void Rotary::setCalibration(double c) { - m_dCalibration = c; -} - -double Rotary::getCalibration() { - return m_dCalibration; -} - -void Rotary::setFilterLength(int i) { - if (i > kiRotaryFilterMaxLen) { - m_iFilterLength = kiRotaryFilterMaxLen; - } else if (i < 1) { - m_iFilterLength = 1; - } else { - m_iFilterLength = i; - } -} - -int Rotary::getFilterLength() { - return m_iFilterLength; +/* Note: There's probably a bug in this function (or this class) somewhere. + The filter function seems to be the cause of the "drifting" bug in the Hercules stuff. + What happens is that filter() gets called to do some magic to a value that's returned + from the Hercules device, and that magic adds "momentum" to it's motion (ie. it doesn't + stop dead when you stop spinning the jog wheels.) The problem with this "magic" is that + when herculeslinux.cpp passes the filtered value off to the wheel ControlObject (or what + have you), the ControlObject's internal value never goes back to zero properly. + - Albert (March 13, 2007) +*/ +double Rotary::filter(double v) { + append(v); + return calculate(); } diff --git a/src/util/rotary.h b/src/util/rotary.h index 52c73264223..b191a74c525 100644 --- a/src/util/rotary.h +++ b/src/util/rotary.h @@ -2,39 +2,25 @@ #include +#include "util/assert.h" + +// Simple moving average class Rotary { - public: - Rotary(); + using Buffer = std::vector; + using index_type = Buffer::size_type; - // Start calibration measurement - void calibrateStart(); - // End calibration measurement - double calibrateEnd(); - // Set calibration - void setCalibration(double c); - // Get calibration - double getCalibration(); + public: + Rotary(qsizetype filterLength) + : m_filterHistory(filterLength, 0.0) { + DEBUG_ASSERT(filterLength > 0); + }; // Low pass filtered rotary event - double filter(double dValue); - // Hard set event value - double fillBuffer(double dValue); - // Collect calibration data - void calibrate(double dValue); - // Set filter length - void setFilterLength(int i); - // Get filter length - int getFilterLength(); + double filter(double value); - protected: - // Length of filter - int m_iFilterLength; - // Update position in filter - int m_iFilterPos; - // Pointer to rotary filter buffer - std::vector m_pFilter; - // Calibration value - double m_dCalibration; - // Last value - double m_dLastValue; - int m_iCalibrationCount; + private: + index_type nextIndex(index_type); + void append(double v); + double calculate() const; + Buffer m_filterHistory; + index_type m_headIndex; }; diff --git a/src/util/semanticversion.cpp b/src/util/semanticversion.cpp index 3e0053f18f4..39e7bbe81b2 100644 --- a/src/util/semanticversion.cpp +++ b/src/util/semanticversion.cpp @@ -1,37 +1,27 @@ #include "util/semanticversion.h" #include +#include +#include namespace { - -QRegularExpression regex("(?\\d+)\\.(?\\d+)\\.(?\\d+)"); +// thread local because SemanticVersion constructors below accesses it mutably. +// making it thread_local should avoid a datarace without having to introduce locking. +thread_local QRegularExpression regex( + QStringLiteral("(?\\d+)\\.(?\\d+)\\.(?\\d+)")); } // anonymous namespace namespace mixxx { -SemanticVersion::SemanticVersion(unsigned int majorVersion, - unsigned int minorVersion, - unsigned int patchVersion) - : majorVersion(majorVersion), - minorVersion(minorVersion), - patchVersion(patchVersion) { -} - SemanticVersion::SemanticVersion(const QString& versionString) - : majorVersion(0), - minorVersion(0), - patchVersion(0) { + : SemanticVersion() { QRegularExpressionMatch match = regex.match(versionString); if (match.hasMatch()) { - majorVersion = match.captured(QStringLiteral("major")).toUInt(); - minorVersion = match.captured(QStringLiteral("minor")).toUInt(); - patchVersion = match.captured(QStringLiteral("patch")).toUInt(); + majorVersion = match.capturedView(QStringView(u"major")).toUInt(); + minorVersion = match.capturedView(QStringView(u"minor")).toUInt(); + patchVersion = match.capturedView(QStringView(u"patch")).toUInt(); } } -bool SemanticVersion::isValid() const { - return !(majorVersion == 0 && minorVersion == 0 && patchVersion == 0); -} - } // namespace mixxx diff --git a/src/util/semanticversion.h b/src/util/semanticversion.h index 9ef99cf2d9a..c8a9a9f276e 100644 --- a/src/util/semanticversion.h +++ b/src/util/semanticversion.h @@ -1,38 +1,60 @@ #pragma once -#include +#include #include +class QString; + namespace mixxx { // "major" and "minor" clash with symbols in glibc, so use more verbose variable names. class SemanticVersion { public: - SemanticVersion(unsigned int majorVersion, + constexpr SemanticVersion(unsigned int majorVersion, unsigned int minorVersion, - unsigned int patchVersion); - SemanticVersion(const QString& versionString); + unsigned int patchVersion) + : majorVersion(majorVersion), + minorVersion(minorVersion), + patchVersion(patchVersion) { + } - bool isValid() const; + SemanticVersion(const QString& versionString); - unsigned int majorVersion, minorVersion, patchVersion; + constexpr bool isValid() const { + return !(majorVersion == 0 && minorVersion == 0 && patchVersion == 0); + } + + friend constexpr std::strong_ordering operator<=>( + const SemanticVersion&, const SemanticVersion&) noexcept; + + friend constexpr bool operator==( + const SemanticVersion&, const SemanticVersion&) noexcept; + + // Do not change the order because the synthesized comparison operators + // depend on it! + unsigned int majorVersion; + unsigned int minorVersion; + unsigned int patchVersion; + + private: + // you should not be able to create an invalid version easily from the outside + constexpr SemanticVersion() + : SemanticVersion(0, 0, 0){}; + // make tuple, which is used for the implementation of the comparison operators + constexpr std::tuple makeTuple() const { + return std::tie(majorVersion, minorVersion, patchVersion); + } }; -inline bool operator<(const SemanticVersion& a, const SemanticVersion& b) { - return std::tie(a.majorVersion, a.minorVersion, a.patchVersion) < - std::tie(b.majorVersion, b.minorVersion, b.patchVersion); -} - -inline bool operator>(const SemanticVersion& a, const SemanticVersion& b) { - return b < a; -} - -inline bool operator<=(const SemanticVersion& a, const SemanticVersion& b) { - return !(a > b); +// TODO: replace with = default (synthesized) implementations once widely +// supported on target compilers. +constexpr std::strong_ordering operator<=>( + const SemanticVersion& lhs, const SemanticVersion& rhs) noexcept { + return lhs.makeTuple() <=> rhs.makeTuple(); } -inline bool operator>=(const SemanticVersion& a, const SemanticVersion& b) { - return !(a < b); +constexpr bool operator==( + const SemanticVersion& lhs, const SemanticVersion& rhs) noexcept { + return lhs.makeTuple() == rhs.makeTuple(); } - } // namespace mixxx diff --git a/src/util/task.cpp b/src/util/task.cpp index 6b4906e20a8..6a437fb27df 100644 --- a/src/util/task.cpp +++ b/src/util/task.cpp @@ -3,13 +3,9 @@ #include #include "moc_task.cpp" -#include "util/compatibility/qatomic.h" - -TaskWatcher::TaskWatcher(QObject* pParent) : QObject(pParent) { -} TaskWatcher::~TaskWatcher() { - if (atomicLoadRelaxed(m_activeTasks) > 0) { + if (m_activeTasks.loadRelaxed() > 0) { qWarning() << "TaskWatcher destroyed before all tasks were done."; } } diff --git a/src/util/task.h b/src/util/task.h index 4fae197e74b..908e2317e0c 100644 --- a/src/util/task.h +++ b/src/util/task.h @@ -5,11 +5,14 @@ // Waits for a number of tasks to complete and emits allTasksDone() once all are // complete. +// Deprecated: This is just a unnecessarily heavy counter. You should probably refrain +// from using this in new code in favor of appropriate QtConcurrent primitives. class TaskWatcher : public QObject { Q_OBJECT public: - TaskWatcher(QObject* pParent=NULL); - virtual ~TaskWatcher(); + TaskWatcher(QObject* pParent = nullptr) + : QObject(pParent){}; + ~TaskWatcher() override; // Increment the number of active tasks by one and watch pTask for // doneSignal. This should be called before the task starts to prevent a diff --git a/src/util/threadcputimer.cpp b/src/util/threadcputimer.cpp deleted file mode 100644 index a40cb7b021a..00000000000 --- a/src/util/threadcputimer.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "util/threadcputimer.h" - -#if defined(__APPLE__) -#include -#include -#include -#elif defined(__UNIX__) -#include -#include -#elif defined(_WIN32) -#include -#endif - - -////////////////////////////// Unix ////////////////////////////// -#if defined(Q_OS_UNIX) - -#if (_POSIX_THREAD_CPUTIME-0 != 0) -static const bool threadCpuTimeChecked = true; -static const bool threadCpuTimeAvailable = _POSIX_THREAD_CPUTIME > 0; -#else -static int threadCpuTimeChecked = false; -static int threadCpuTimeAvailable = false; -#endif - -#ifdef Q_CC_GNU -# define is_likely(x) __builtin_expect((x), 1) -#else -# define is_likely(x) (x) -#endif -#define load_acquire(x) ((volatile const int&)(x)) -#define store_release(x,v) ((volatile int&)(x) = (v)) - -static void unixCheckClockType() -{ -#if (_POSIX_THREAD_CPUTIME-0 == 0) - if (is_likely(load_acquire(threadCpuTimeChecked))) { - return; - } - -# if defined(_SC_THREAD_CPUTIME) - // detect if the system support monotonic timers - long x = sysconf(_SC_THREAD_CPUTIME); - store_release(threadCpuTimeAvailable, x >= 200112L); -# endif - - store_release(threadCpuTimeChecked, true); -#endif -} - -static inline void do_gettime(qint64 *sec, qint64 *frac) -{ -#if (_POSIX_MONOTONIC_CLOCK-0 >= 0) - unixCheckClockType(); - if (is_likely(threadCpuTimeAvailable)) { - timespec ts; - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); - *sec = ts.tv_sec; - *frac = ts.tv_nsec; - return; - } -#else - Q_UNUSED(threadCpuTimeChecked); - Q_UNUSED(threadCpuTimeAvailable); - Q_UNUSED(unixCheckClockType); -#endif - *sec = 0; - *frac = 0; -} - -void ThreadCpuTimer::start() -{ - do_gettime(&t1, &t2); -} - -mixxx::Duration ThreadCpuTimer::elapsed() const -{ - qint64 sec, frac; - do_gettime(&sec, &frac); - sec = sec - t1; - frac = frac - t2; - - return mixxx::Duration::fromNanos(sec * Q_INT64_C(1000000000) + frac); -} - -mixxx::Duration ThreadCpuTimer::restart() -{ - qint64 sec, frac; - sec = t1; - frac = t2; - do_gettime(&t1, &t2); - sec = t1 - sec; - frac = t2 - frac; - return mixxx::Duration::fromNanos(sec * Q_INT64_C(1000000000) + frac); -} - -////////////////////////////// Default ////////////////////////////// -#else - -// default implementation (no hi-perf timer) does nothing -void ThreadCpuTimer::start() -{ -} - -mixxx::Duration ThreadCpuTimer::elapsed() const -{ - return mixxx::Duration::fromNanos(0); -} - -mixxx::Duration ThreadCpuTimer::restart() -{ - return mixxx::Duration::fromNanos(0); -} - -#endif diff --git a/src/util/threadcputimer.h b/src/util/threadcputimer.h deleted file mode 100644 index bb8c3922f3e..00000000000 --- a/src/util/threadcputimer.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "util/duration.h" - -class ThreadCpuTimer { - public: - void start(); - mixxx::Duration elapsed() const; - mixxx::Duration restart(); - private: -#if defined(Q_OS_UNIX) - qint64 t1; - qint64 t2; -#endif -}; diff --git a/src/util/time.h b/src/util/time.h index 87dad6d7b85..8c13566b701 100644 --- a/src/util/time.h +++ b/src/util/time.h @@ -4,13 +4,11 @@ #include "util/duration.h" #include "util/performancetimer.h" -#include "util/threadcputimer.h" namespace mixxx { class Time { using LLTIMER = PerformanceTimer; - // using LLTIMER = ThreadCpuTimer; public: using rep = LLTIMER::ClockT::rep; diff --git a/src/util/trace.h b/src/util/trace.h index 4c9615bb867..09b07eb42a1 100644 --- a/src/util/trace.h +++ b/src/util/trace.h @@ -11,8 +11,7 @@ class Trace { public: - Trace(const char* tag, const char* arg=NULL, - bool writeToStdout=false, bool time=true) + Trace(const char* tag, const char* arg = nullptr, bool writeToStdout = false, bool time = true) : m_writeToStdout(writeToStdout), m_time(time) { if (writeToStdout || CmdlineArgs::Instance().getDeveloper()) { @@ -20,15 +19,6 @@ class Trace { } } - Trace(const char* tag, int arg, - bool writeToStdout=false, bool time=true) - : m_writeToStdout(writeToStdout), - m_time(time) { - if (writeToStdout || CmdlineArgs::Instance().getDeveloper()) { - initialize(tag, QString::number(arg)); - } - } - Trace(const char* tag, const QString& arg, bool writeToStdout=false, bool time=true) : m_writeToStdout(writeToStdout), @@ -38,7 +28,7 @@ class Trace { } } - virtual ~Trace() { + ~Trace() { // Proxy for whether initialize was called. if (m_tag.isEmpty()) { return; @@ -86,16 +76,7 @@ class Trace { } QString m_tag; - const bool m_writeToStdout, m_time; PerformanceTimer m_timer; - -}; - -class DebugTrace : public Trace { - public: - DebugTrace(const char* tag, bool time=true) - : Trace(tag, "", CmdlineArgs::Instance().getDeveloper(), time) { - } - virtual ~DebugTrace() { - } + bool m_writeToStdout; + bool m_time; }; diff --git a/src/util/types.h b/src/util/types.h index c026e38fdb1..d4a6194f2e3 100644 --- a/src/util/types.h +++ b/src/util/types.h @@ -1,10 +1,9 @@ #pragma once +#include #include #include -#include "util/math.h" - // Signed integer type for POT array indices, sizes and pointer // arithmetic. Its size (32-/64-bit) depends on the CPU architecture. // This should be used for all CSAMLE operations since it is fast and @@ -25,28 +24,29 @@ constexpr SAMPLE SAMPLE_MAXIMUM = SHRT_MAX; // amplitude of 1.0. No min/max constants here to // emphasize the symmetric value range of CSAMPLE // data! -typedef float CSAMPLE; +using CSAMPLE = float; constexpr CSAMPLE CSAMPLE_ZERO = 0.0f; constexpr CSAMPLE CSAMPLE_ONE = 1.0f; constexpr CSAMPLE CSAMPLE_PEAK = CSAMPLE_ONE; +static_assert(sizeof(CSAMPLE) == 4); // 32 bits == 4 bytes // Limits the range of a CSAMPLE value to [-CSAMPLE_PEAK, CSAMPLE_PEAK]. -inline -CSAMPLE CSAMPLE_clamp(CSAMPLE in) { - return math_clamp(in, -CSAMPLE_PEAK, CSAMPLE_PEAK); +constexpr CSAMPLE CSAMPLE_clamp(CSAMPLE in) { + static_assert(-CSAMPLE_PEAK <= CSAMPLE_PEAK); + return std::clamp(in, -CSAMPLE_PEAK, CSAMPLE_PEAK); } // Gain values for weighted calculations of CSAMPLE // data in the range [0.0, 1.0]. Same data type as // CSAMPLE to avoid type conversions in calculations. -typedef CSAMPLE CSAMPLE_GAIN; +using CSAMPLE_GAIN = CSAMPLE; constexpr float CSAMPLE_GAIN_ZERO = CSAMPLE_ZERO; constexpr float CSAMPLE_GAIN_ONE = CSAMPLE_ONE; constexpr float CSAMPLE_GAIN_MIN = CSAMPLE_GAIN_ZERO; constexpr float CSAMPLE_GAIN_MAX = CSAMPLE_GAIN_ONE; // Limits the range of a CSAMPLE_GAIN value to [CSAMPLE_GAIN_MIN, CSAMPLE_GAIN_MAX]. -inline -CSAMPLE_GAIN CSAMPLE_GAIN_clamp(CSAMPLE_GAIN in) { - return math_clamp(in, CSAMPLE_GAIN_MIN, CSAMPLE_GAIN_MAX); +constexpr CSAMPLE_GAIN CSAMPLE_GAIN_clamp(CSAMPLE_GAIN in) { + static_assert(CSAMPLE_GAIN_MIN <= CSAMPLE_GAIN_MAX); + return std::clamp(in, CSAMPLE_GAIN_MIN, CSAMPLE_GAIN_MAX); } diff --git a/src/util/valuetransformer.cpp b/src/util/valuetransformer.cpp index 60c60fe08b0..eeff1ca0cb9 100644 --- a/src/util/valuetransformer.cpp +++ b/src/util/valuetransformer.cpp @@ -1,14 +1,94 @@ #include "util/valuetransformer.h" -ValueTransformer::ValueTransformer() { -} +#include +#include +#include +#include + +#include "skin/legacy/skincontext.h" + +class TransformNode { + public: + TransformNode() { + } + virtual ~TransformNode() { + } -void ValueTransformer::addTransformer(TransformNode* pTransformer) { - m_transformers.append(pTransformer); + virtual double transform(double argument) const = 0; + virtual double transformInverse(double argument) const = 0; +}; + +namespace { + +class TransformAdd : public TransformNode { + public: + TransformAdd(double addend) + : m_addend(addend) { + } + + double transform(double argument) const override { + return argument + m_addend; + } + + double transformInverse(double argument) const override { + return argument - m_addend; + } + + private: + double m_addend; +}; + +class TransformInvert : public TransformNode { + public: + double transform(double argument) const override { + return -argument; + } + + double transformInverse(double argument) const override { + return -argument; + } +}; + +class TransformNot : public TransformNode { + public: + double transform(double argument) const override { + return !static_cast(argument); + } + + double transformInverse(double argument) const override { + return !static_cast(argument); + } +}; + +class TransformIsEqual : public TransformNode { + public: + TransformIsEqual(double compareValue) + : m_compareValue(compareValue) { + } + + double transform(double argument) const override { + return argument == m_compareValue; + } + + double transformInverse(double argument) const override { + if (argument > 0.0) { + return m_compareValue; + } + return 0.0; + } + + private: + double m_compareValue; +}; + +} // namespace + +void ValueTransformer::addTransformer(std::unique_ptr pTransformer) { + m_transformers.push_back(std::move(pTransformer)); } double ValueTransformer::transform(double argument) const { - foreach (const TransformNode* pNode, m_transformers) { + for (const auto& pNode : m_transformers) { argument = pNode->transform(argument); } return argument; @@ -16,20 +96,29 @@ double ValueTransformer::transform(double argument) const { double ValueTransformer::transformInverse(double argument) const { for (int i = m_transformers.size() - 1; i >= 0; --i) { - const TransformNode* pNode = m_transformers[i]; - argument = pNode->transformInverse(argument); + argument = m_transformers[i]->transformInverse(argument); } return argument; } // static -ValueTransformer* ValueTransformer::parseFromXml(const QDomElement& transformElement, - const SkinContext& context) { +std::unique_ptr ValueTransformer::parseFromXml( + const QDomElement& transformElement, const SkinContext& context) { if (transformElement.isNull() || !transformElement.hasChildNodes()) { return nullptr; } - ValueTransformer* pTransformer = new ValueTransformer(); + auto pTransformer = std::unique_ptr(new ValueTransformer()); + + auto maybeAddFromElement = [&](auto element) { + QString valueStr = context.nodeToString(element); + bool ok = false; + double value = valueStr.toDouble(&ok); + if (ok) { + pTransformer->addTransformer(std::make_unique(value)); + } + }; + QDomNodeList children = transformElement.childNodes(); for (int i = 0; i < children.count(); ++i) { QDomNode node = children.at(i); @@ -38,32 +127,21 @@ ValueTransformer* ValueTransformer::parseFromXml(const QDomElement& transformEle } QDomElement element = node.toElement(); - if (element.nodeName() == "Invert") { - pTransformer->addTransformer(new TransformInvert()); - } else if (element.nodeName() == "Add") { - QString value = context.nodeToString(element); - bool ok = false; - double addend = value.toDouble(&ok); - if (ok) { - pTransformer->addTransformer(new TransformAdd(addend)); - } - } else if (element.nodeName() == "Not") { - pTransformer->addTransformer(new TransformNot()); - } else if (element.nodeName() == "IsEqual") { - QString value = context.nodeToString(element); - bool ok = false; - double compareValue = value.toDouble(&ok); - if (ok) { - pTransformer->addTransformer(new TransformIsEqual(compareValue)); - } + QString name = element.nodeName(); + if (name == "Invert") { + pTransformer->addTransformer(std::make_unique()); + } else if (name == "Add") { + maybeAddFromElement.operator()(element); + } else if (name == "Not") { + pTransformer->addTransformer(std::make_unique()); + } else if (name == "IsEqual") { + maybeAddFromElement.operator()(element); } } return pTransformer; } -ValueTransformer::~ValueTransformer() { - foreach (TransformNode* node, m_transformers) { - delete node; - } -} +ValueTransformer::ValueTransformer() = default; + +ValueTransformer::~ValueTransformer() = default; diff --git a/src/util/valuetransformer.h b/src/util/valuetransformer.h index e3069ff2e91..5f824ce3b27 100644 --- a/src/util/valuetransformer.h +++ b/src/util/valuetransformer.h @@ -1,95 +1,25 @@ #pragma once -#include -#include +#include +#include -#include "skin/legacy/skincontext.h" - -class TransformNode { - public: - TransformNode() {} - virtual ~TransformNode() {} - - virtual double transform(double argument) const = 0; - virtual double transformInverse(double argument) const = 0; -}; - -class TransformAdd : public TransformNode { - public: - TransformAdd(double addend) : m_addend(addend) {} - - double transform(double argument) const { - return argument + m_addend; - } - - double transformInverse(double argument) const { - return argument - m_addend; - } - - private: - double m_addend; -}; - -class TransformInvert : public TransformNode { - public: - TransformInvert() {} - - double transform(double argument) const { - return -argument; - } - - double transformInverse(double argument) const { - return -argument; - } -}; - -class TransformNot : public TransformNode { - public: - TransformNot() {} - - double transform(double argument) const { - return !static_cast(argument); - } - - double transformInverse(double argument) const { - return !static_cast(argument); - } -}; - -class TransformIsEqual : public TransformNode { - public: - TransformIsEqual(double compareValue) : - m_compareValue(compareValue) { - } - - double transform(double argument) const { - return argument == m_compareValue; - } - - double transformInverse(double argument) const { - if (argument > 0.0) { - return m_compareValue; - } - return 0.0; - } - - private: - double m_compareValue; -}; +class SkinContext; +class TransformNode; +class QDomElement; class ValueTransformer { public: ~ValueTransformer(); + double transform(double argument) const; double transformInverse(double argument) const; - static ValueTransformer* parseFromXml(const QDomElement& transformElement, + static std::unique_ptr parseFromXml(const QDomElement& transformElement, const SkinContext& context); private: - ValueTransformer(); - - void addTransformer(TransformNode* pTransformer); + ValueTransformer(); // only accessible from parseFromXml, not deleted + void addTransformer(std::unique_ptr pTransformer); - QList m_transformers; + std::vector> m_transformers; }; diff --git a/src/util/xml.cpp b/src/util/xml.cpp index ccfee0fb986..264d5218d2c 100644 --- a/src/util/xml.cpp +++ b/src/util/xml.cpp @@ -1,7 +1,12 @@ +#include "util/xml.h" + +#include +#include +#include #include +#include #include -#include "util/xml.h" #include "errordialoghandler.h" int XmlParse::selectNodeInt(const QDomNode& nodeHeader, diff --git a/src/util/xml.h b/src/util/xml.h index 5bbb4196680..3218c6c9de6 100644 --- a/src/util/xml.h +++ b/src/util/xml.h @@ -1,60 +1,61 @@ #pragma once -#include -#include -#include - -class XmlParse { - public: - // Searches for and returns a node named sNode in the children of - // nodeHeader. Returns a null QDomNode if one is not found. - static QDomNode selectNode(const QDomNode& nodeHeader, - const QString& sNode); - - // Searches for and returns an element named sNode in the children of - // nodeHeader. Returns a null QDomElement if one is not found. - static QDomElement selectElement(const QDomNode& nodeHeader, - const QString& sNode); - - // Searches for an element named sNode in the children of nodeHeader and - // parses the text value of its children as an integer. Returns 0 if sNode - // is not found in nodeHeader's children. - static int selectNodeInt(const QDomNode& nodeHeader, - const QString& sNode, bool* ok = 0); - - // Searches for an element named sNode in the children of nodeHeader and - // parses the text value of its children as a float. Returns 0.0f if sNode - // is not found in nodeHeader's children. - static float selectNodeFloat(const QDomNode& nodeHeader, - const QString& sNode, bool* ok = 0); - - // Searches for an element named sNode in the children of nodeHeader and - // parses the text value of its children as a double. Returns 0.0 if sNode - // is not found in nodeHeader's children. - static double selectNodeDouble(const QDomNode& nodeHeader, - const QString& sNode, bool* ok = 0); - - // Searches for an element named sNode in the children of nodeHeader and - // parses the text value of its children as a bool. Returns false if sNode - // is not found in nodeHeader's children. - static bool selectNodeBool(const QDomNode& nodeHeader, - const QString& sNode); - - // Searches for an element named sNode in the children of nodeHeader and - // returns the text value of its children. Returns the empty string if sNode - // is not found in nodeHeader's children. - static QString selectNodeQString(const QDomNode& nodeHeader, - const QString& sNode); - - // Open an XML file. - static QDomElement openXMLFile(const QString& path, const QString& name); - - // Add an element named elementName to the provided header element with a - // child text node with the value textValue. Returns the created element. - static QDomElement addElement(QDomDocument& document, QDomElement& header, - const QString& elementName, const QString& textValue); - - private: - XmlParse() {} - ~XmlParse() {} -}; +class QDomNode; +class QString; +class QDomElement; +class QDomDocument; + +namespace XmlParse { +// Searches for and returns a node named sNode in the children of +// nodeHeader. Returns a null QDomNode if one is not found. +QDomNode selectNode(const QDomNode& nodeHeader, + const QString& sNode); + +// Searches for and returns an element named sNode in the children of +// nodeHeader. Returns a null QDomElement if one is not found. +QDomElement selectElement(const QDomNode& nodeHeader, + const QString& sNode); + +// Searches for an element named sNode in the children of nodeHeader and +// parses the text value of its children as an integer. Returns 0 if sNode +// is not found in nodeHeader's children. +int selectNodeInt(const QDomNode& nodeHeader, + const QString& sNode, + bool* ok = nullptr); + +// Searches for an element named sNode in the children of nodeHeader and +// parses the text value of its children as a float. Returns 0.0f if sNode +// is not found in nodeHeader's children. +float selectNodeFloat(const QDomNode& nodeHeader, + const QString& sNode, + bool* ok = nullptr); + +// Searches for an element named sNode in the children of nodeHeader and +// parses the text value of its children as a double. Returns 0.0 if sNode +// is not found in nodeHeader's children. +double selectNodeDouble(const QDomNode& nodeHeader, + const QString& sNode, + bool* ok = nullptr); + +// Searches for an element named sNode in the children of nodeHeader and +// parses the text value of its children as a bool. Returns false if sNode +// is not found in nodeHeader's children. +bool selectNodeBool(const QDomNode& nodeHeader, + const QString& sNode); + +// Searches for an element named sNode in the children of nodeHeader and +// returns the text value of its children. Returns the empty string if sNode +// is not found in nodeHeader's children. +QString selectNodeQString(const QDomNode& nodeHeader, + const QString& sNode); + +// Open an XML file. +QDomElement openXMLFile(const QString& path, const QString& name); + +// Add an element named elementName to the provided header element with a +// child text node with the value textValue. Returns the created element. +QDomElement addElement(QDomDocument& document, + QDomElement& header, + const QString& elementName, + const QString& textValue); +} // namespace XmlParse diff --git a/src/waveform/renderers/waveformwidgetrenderer.h b/src/waveform/renderers/waveformwidgetrenderer.h index 47cd21b67a6..c99833a39ee 100644 --- a/src/waveform/renderers/waveformwidgetrenderer.h +++ b/src/waveform/renderers/waveformwidgetrenderer.h @@ -181,7 +181,7 @@ class WaveformWidgetRenderer { void setPlayMarkerPosition(double newPos) { VERIFY_OR_DEBUG_ASSERT(newPos >= 0.0 && newPos <= 1.0) { - newPos = math_clamp(newPos, 0.0, 1.0); + newPos = std::clamp(newPos, 0.0, 1.0); } m_playMarkerPosition = newPos; } diff --git a/src/widget/whotcuebutton.cpp b/src/widget/whotcuebutton.cpp index 0e91f1812ad..b37a7874364 100644 --- a/src/widget/whotcuebutton.cpp +++ b/src/widget/whotcuebutton.cpp @@ -4,6 +4,7 @@ #include "mixer/playerinfo.h" #include "moc_whotcuebutton.cpp" +#include "skin/legacy/skincontext.h" #include "track/track.h" #include "widget/controlwidgetconnection.h" diff --git a/src/widget/wpushbutton.cpp b/src/widget/wpushbutton.cpp index 5cc3c188203..07f81be7d5d 100644 --- a/src/widget/wpushbutton.cpp +++ b/src/widget/wpushbutton.cpp @@ -11,6 +11,7 @@ #include "control/controlobject.h" #include "control/controlpushbutton.h" #include "moc_wpushbutton.cpp" +#include "skin/legacy/skincontext.h" #include "util/debug.h" #include "widget/controlwidgetconnection.h" #include "widget/wpixmapstore.h" diff --git a/src/widget/wpushbutton.h b/src/widget/wpushbutton.h index 1e4ff3ddf09..94fbad7e6b4 100644 --- a/src/widget/wpushbutton.h +++ b/src/widget/wpushbutton.h @@ -5,7 +5,7 @@ #include #include -#include "control/controlpushbutton.h" +#include "control/controlbuttonmode.h" #include "util/fpclassify.h" #include "util/performancetimer.h" #include "widget/wpixmapstore.h" diff --git a/src/widget/wslidercomposed.cpp b/src/widget/wslidercomposed.cpp index 52c6c0c60d8..e6eef93cf87 100644 --- a/src/widget/wslidercomposed.cpp +++ b/src/widget/wslidercomposed.cpp @@ -6,6 +6,7 @@ #include #include "moc_wslidercomposed.cpp" +#include "skin/legacy/skincontext.h" #include "util/debug.h" #include "widget/controlwidgetconnection.h" #include "widget/wpixmapstore.h"