From 84f6380d0c9397af8da4f4dda443aeb36239d9dd Mon Sep 17 00:00:00 2001 From: RJ Skerry-Ryan Date: Mon, 23 Apr 2018 22:08:15 -0700 Subject: [PATCH 1/6] Fix lack of QAtomicPointer::operator T*() on Qt5. --- src/engine/loopingcontrol.cpp | 3 ++- src/util/compatibility.h | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/engine/loopingcontrol.cpp b/src/engine/loopingcontrol.cpp index 62a70de981..d8a92fc536 100644 --- a/src/engine/loopingcontrol.cpp +++ b/src/engine/loopingcontrol.cpp @@ -10,6 +10,7 @@ #include "engine/loopingcontrol.h" #include "engine/bpmcontrol.h" #include "engine/enginecontrol.h" +#include "util/compatibility.h" #include "util/math.h" #include "util/sample.h" @@ -790,7 +791,7 @@ void LoopingControl::notifySeek(double dNewPlaypos, bool adjustingPhase) { void LoopingControl::setLoopingEnabled(bool enabled) { m_bLoopingEnabled = enabled; m_pCOLoopEnabled->set(enabled); - BeatLoopingControl* pActiveBeatLoop = m_pActiveBeatLoop; + BeatLoopingControl* pActiveBeatLoop = load_atomic_pointer(m_pActiveBeatLoop); if (pActiveBeatLoop != nullptr) { if (enabled) { pActiveBeatLoop->activate(); diff --git a/src/util/compatibility.h b/src/util/compatibility.h index e4c92c7abe..9cf12004c8 100644 --- a/src/util/compatibility.h +++ b/src/util/compatibility.h @@ -2,6 +2,7 @@ #define COMPATABILITY_H #include +#include #include #include @@ -21,6 +22,15 @@ inline int load_atomic(const QAtomicInt& value) { #endif } +template +inline T* load_atomic_pointer(const QAtomicPointer& value) { +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + return value; +#else + return value.load(); +#endif +} + inline QLocale inputLocale() { #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) return QApplication::keyboardInputLocale(); From 62a034578ba5683562bcc77bf6909a64fcab3e2f Mon Sep 17 00:00:00 2001 From: RJ Skerry-Ryan Date: Tue, 24 Apr 2018 08:45:45 -0700 Subject: [PATCH 2/6] More qt5 compatibility fixes. How did these slip in? --- src/engine/sidechain/shoutconnection.cpp | 4 +-- src/mixer/playermanager.cpp | 45 +++++++++++++++++--------------- src/preferences/broadcastprofile.cpp | 5 ++-- src/soundio/soundmanager.cpp | 9 ++++--- 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/engine/sidechain/shoutconnection.cpp b/src/engine/sidechain/shoutconnection.cpp index 4b8c59ce73..b72b9dda6d 100644 --- a/src/engine/sidechain/shoutconnection.cpp +++ b/src/engine/sidechain/shoutconnection.cpp @@ -26,6 +26,7 @@ #include "preferences/usersettings.h" #include "recording/defs_recording.h" #include "track/track.h" +#include "util/compatibility.h" #include "util/logger.h" #include @@ -899,7 +900,7 @@ QSharedPointer> ShoutConnection::getOutputFifo() { } bool ShoutConnection::threadWaiting() { - return m_threadWaiting; + return load_atomic(m_threadWaiting); } void ShoutConnection::run() { @@ -996,4 +997,3 @@ void ShoutConnection::ignoreSigpipe() { #endif } #endif - diff --git a/src/mixer/playermanager.cpp b/src/mixer/playermanager.cpp index e57a2a9136..b1fb18729e 100644 --- a/src/mixer/playermanager.cpp +++ b/src/mixer/playermanager.cpp @@ -202,52 +202,55 @@ bool PlayerManager::isPreviewDeckGroup(const QString& group, int* number) { unsigned int PlayerManager::numDecks() { // We do this to cache the control once it is created so callers don't incur // a hashtable lookup every time they call this. - if (m_pCOPNumDecks == nullptr) { - ControlProxy* pNumCO = new ControlProxy(ConfigKey("[Master]", "num_decks")); - if (!pNumCO->valid()) { - delete pNumCO; - pNumCO = NULL; + ControlProxy* pCOPNumDecks = m_pCOPNumDecks.loadAcquire(); + if (pCOPNumDecks == nullptr) { + pCOPNumDecks = new ControlProxy(ConfigKey("[Master]", "num_decks")); + if (!pCOPNumDecks->valid()) { + delete pCOPNumDecks; + pCOPNumDecks = nullptr; } else { - m_pCOPNumDecks = pNumCO; + m_pCOPNumDecks = pCOPNumDecks; } } // m_pCOPNumDecks->get() fails on MacOs - return m_pCOPNumDecks ? (*m_pCOPNumDecks).get() : 0; + return pCOPNumDecks ? pCOPNumDecks->get() : 0; } // static unsigned int PlayerManager::numSamplers() { // We do this to cache the control once it is created so callers don't incur // a hashtable lookup every time they call this. - if (m_pCOPNumSamplers == nullptr) { - ControlProxy* pNumCO = new ControlProxy(ConfigKey("[Master]", "num_samplers")); - if (!pNumCO->valid()) { - delete pNumCO; - pNumCO = NULL; + ControlProxy* pCOPNumSamplers = m_pCOPNumSamplers.loadAcquire(); + if (pCOPNumSamplers == nullptr) { + pCOPNumSamplers = new ControlProxy(ConfigKey("[Master]", "num_samplers")); + if (!pCOPNumSamplers->valid()) { + delete pCOPNumSamplers; + pCOPNumSamplers = nullptr; } else { - m_pCOPNumSamplers = pNumCO; + m_pCOPNumSamplers = pCOPNumSamplers; } } // m_pCOPNumSamplers->get() fails on MacOs - return m_pCOPNumSamplers ? (*m_pCOPNumSamplers).get() : 0; + return pCOPNumSamplers ? pCOPNumSamplers->get() : 0; } // static unsigned int PlayerManager::numPreviewDecks() { // We do this to cache the control once it is created so callers don't incur // a hashtable lookup every time they call this. - if (m_pCOPNumPreviewDecks == NULL) { - ControlProxy* pNumCO = new ControlProxy( + ControlProxy* pCOPNumPreviewDecks = m_pCOPNumPreviewDecks.loadAcquire(); + if (pCOPNumPreviewDecks == nullptr) { + pCOPNumPreviewDecks = new ControlProxy( ConfigKey("[Master]", "num_preview_decks")); - if (!pNumCO->valid()) { - delete pNumCO; - pNumCO = NULL; + if (!pCOPNumPreviewDecks->valid()) { + delete pCOPNumPreviewDecks; + pCOPNumPreviewDecks = nullptr; } else { - m_pCOPNumPreviewDecks = pNumCO; + m_pCOPNumPreviewDecks = pCOPNumPreviewDecks; } } // m_pCOPNumPreviewDecks->get() fails on MacOs - return m_pCOPNumPreviewDecks ? (*m_pCOPNumPreviewDecks).get() : 0; + return pCOPNumPreviewDecks ? pCOPNumPreviewDecks->get() : 0; } void PlayerManager::slotNumDecksControlChanged(double v) { diff --git a/src/preferences/broadcastprofile.cpp b/src/preferences/broadcastprofile.cpp index 824d2e9364..0b8a1aa9c1 100644 --- a/src/preferences/broadcastprofile.cpp +++ b/src/preferences/broadcastprofile.cpp @@ -16,6 +16,7 @@ using namespace QKeychain; #include "broadcast/defs_broadcast.h" #include "defs_urls.h" +#include "util/compatibility.h" #include "util/xml.h" #include "util/memory.h" #include "util/logger.h" @@ -387,11 +388,11 @@ QString BroadcastProfile::getProfileName() const { void BroadcastProfile::setConnectionStatus(int newState) { m_connectionStatus = newState; - emit connectionStatusChanged(m_connectionStatus); + emit connectionStatusChanged(connectionStatus()); } int BroadcastProfile::connectionStatus() { - return m_connectionStatus; + return load_atomic(m_connectionStatus); } void BroadcastProfile::setSecureCredentialStorage(bool value) { diff --git a/src/soundio/soundmanager.cpp b/src/soundio/soundmanager.cpp index ce2cb5dd1f..bcd3b8752b 100644 --- a/src/soundio/soundmanager.cpp +++ b/src/soundio/soundmanager.cpp @@ -35,6 +35,7 @@ #include "soundio/sounddevicenotfound.h" #include "soundio/sounddeviceportaudio.h" #include "soundio/soundmanagerutil.h" +#include "util/compatibility.h" #include "util/cmdlineargs.h" #include "util/defs.h" #include "util/sample.h" @@ -363,8 +364,8 @@ SoundDeviceError SoundManager::setupDevices() { m_pMasterAudioLatencyOverloadCount->set(0); - // load with all configured devices. - // all found devices are removed below + // load with all configured devices. + // all found devices are removed below QSet devicesNotFound = m_config.getDevices(); // pair is isInput, isOutput @@ -692,14 +693,14 @@ int SoundManager::getConfiguredDeckCount() const { void SoundManager::processUnderflowHappened() { if (m_underflowUpdateCount == 0) { - if (m_underflowHappened) { + if (load_atomic(m_underflowHappened)) { m_pMasterAudioLatencyOverload->set(1.0); m_pMasterAudioLatencyOverloadCount->set( m_pMasterAudioLatencyOverloadCount->get() + 1); m_underflowUpdateCount = CPU_OVERLOAD_DURATION * m_config.getSampleRate() / m_config.getFramesPerBuffer() / 1000; - m_underflowHappened = 0; // reseting her is not thread save, + m_underflowHappened = 0; // resetting here is not thread safe, // but that is OK, because we count only // 1 underflow each 500 ms } else { From 39ac01179aa5da33d6326983858d497701edfd27 Mon Sep 17 00:00:00 2001 From: RJ Skerry-Ryan Date: Wed, 9 May 2018 03:37:51 -0700 Subject: [PATCH 3/6] Alow Qt5 build on Windows. --- build/depends.py | 68 ++++++++++++++++++++++++++++++++++++++++++------ build/qt5.py | 6 ++++- src/mixxxapplication.cpp | 17 ++++++++++++ 3 files changed, 82 insertions(+), 9 deletions(-) diff --git a/build/depends.py b/build/depends.py index 25f1dd425a..5a8b5af564 100644 --- a/build/depends.py +++ b/build/depends.py @@ -233,12 +233,32 @@ def find_framework_libdir(qtdir, qt5): def enabled_modules(build): qt5 = Qt.qt5_enabled(build) qt_modules = [ - 'QtCore', 'QtGui', 'QtOpenGL', 'QtXml', 'QtSvg', - 'QtSql', 'QtScript', 'QtNetwork', - 'QtTest', 'QtScriptTools' + # Keep alphabetized. + 'QtCore', + 'QtGui', + 'QtNetwork', + 'QtOpenGL', + 'QtScript', + 'QtScriptTools', + 'QtSql', + 'QtSvg', + 'QtTest', + 'QtXml', ] if qt5: - qt_modules.extend(['QtWidgets', 'QtConcurrent']) + qt_modules.extend([ + # Keep alphabetized. + 'QtConcurrent', + 'QtWidgets', + ]) + if build.platform_is_windows: + qt_modules.extend([ + # Keep alphabetized. + 'QtAccessibilitySupport', + 'QtEventDispatcherSupport', + 'QtFontDatabaseSupport', + 'QtThemeSupport', + ]) return qt_modules @staticmethod @@ -391,6 +411,22 @@ def configure(self, build, conf): # QtNetwork openssl-linked build.env.Append(LIBS = 'crypt32') + # New libraries required by Qt5. + if qt5: + build.env.Append(LIBS = 'dwmapi') # qtwindows + build.env.Append(LIBS = 'iphlpapi') # qt5network + build.env.Append(LIBS = 'libEGL') # qt5opengl + build.env.Append(LIBS = 'libGLESv2') # qt5opengl + build.env.Append(LIBS = 'netapi32') # qt5core + build.env.Append(LIBS = 'userenv') # qt5core + build.env.Append(LIBS = 'uxtheme') # ? + build.env.Append(LIBS = 'version') # ? + + build.env.Append(LIBS = 'qtfreetype') + build.env.Append(LIBS = 'qtharfbuzz') + build.env.Append(LIBS = 'qtlibpng') + build.env.Append(LIBS = 'qtpcre2') + # NOTE(rryan): If you are adding a plugin here, you must also # update src/mixxxapplication.cpp to define a Q_IMPORT_PLUGIN # for it. Not all imageformats plugins are built as .libs when @@ -409,11 +445,27 @@ def configure(self, build, conf): build.env.Append(LIBS = 'qico') build.env.Append(LIBS = 'qsvg') build.env.Append(LIBS = 'qtga') + build.env.Append(LIBS = 'qgif') + build.env.Append(LIBS = 'qjpeg') + + # accessibility plugins (gone in Qt5) + if not qt5: + build.env.Append(LIBPATH=[ + os.path.join(build.env['QTDIR'],'plugins/accessible')]) + build.env.Append(LIBS = 'qtaccessiblewidgets') + + # platform plugins (new in Qt5 for Windows) + if qt5: + build.env.Append(LIBPATH=[ + os.path.join(build.env['QTDIR'],'plugins/platforms')]) + build.env.Append(LIBS = 'qwindows') + + # sqldrivers (new in Qt5? or did we just start enabling them) + if qt5: + build.env.Append(LIBPATH=[ + os.path.join(build.env['QTDIR'],'plugins/sqldrivers')]) + build.env.Append(LIBS = 'qsqlite') - # accessibility plugins - build.env.Append(LIBPATH=[ - os.path.join(build.env['QTDIR'],'plugins/accessible')]) - build.env.Append(LIBS = 'qtaccessiblewidgets') # Set the rpath for linux/bsd/osx. diff --git a/build/qt5.py b/build/qt5.py index 674abef60a..c080e3243f 100644 --- a/build/qt5.py +++ b/build/qt5.py @@ -881,14 +881,18 @@ def enable_modules(self, modules, debug=False, crosscompiling=False, staticdeps= 'QtWebKitWidgets', 'QtWidgets', # Qt Add-Ons + 'QtAccessibilitySupport', 'QtConcurrent', 'QtDBus', + 'QtEventDispatcherSupport', + 'QtFontDatabaseSupport', 'QtOpenGL', 'QtPrintSupport', 'QtDeclarative', 'QtScript', 'QtScriptTools', 'QtSvg', + 'QtThemeSupport', 'QtUiTools', 'QtXml', 'QtXmlPatterns', @@ -967,7 +971,7 @@ def enable_modules(self, modules, debug=False, crosscompiling=False, staticdeps= modules.append("QtAssistantClient") self.AppendUnique(LIBS=['qtmain'+debugSuffix]) self.AppendUnique(LIBS=[lib.replace("Qt","Qt5")+debugSuffix for lib in modules if lib not in staticModules]) - self.PrependUnique(LIBS=[lib+debugSuffix for lib in modules if lib in staticModules]) + self.PrependUnique(LIBS=[lib.replace("Qt", "Qt5")+debugSuffix for lib in modules if lib in staticModules]) if 'QtOpenGL' in modules: self.AppendUnique(LIBS=['opengl32']) self.AppendUnique(CPPPATH=[ '$QT5DIR/include/']) diff --git a/src/mixxxapplication.cpp b/src/mixxxapplication.cpp index f6a2281f3a..c2d1c83ffa 100644 --- a/src/mixxxapplication.cpp +++ b/src/mixxxapplication.cpp @@ -11,6 +11,22 @@ // plugins we link in build/depends.py. #ifdef QT_NODLL #include +#if QT_VERSION >= 0x050000 +// sqldrivers plugins +Q_IMPORT_PLUGIN(QSQLiteDriverPlugin) +// platform plugins +Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) +// imageformats plugins +Q_IMPORT_PLUGIN(QSvgPlugin) +Q_IMPORT_PLUGIN(QSvgIconPlugin) +Q_IMPORT_PLUGIN(QICOPlugin) +Q_IMPORT_PLUGIN(QTgaPlugin) +Q_IMPORT_PLUGIN(QJpegPlugin) +Q_IMPORT_PLUGIN(QGifPlugin) +// accessible plugins +// TODO(rryan): This is supposed to exist but does not in our builds. +//Q_IMPORT_PLUGIN(AccessibleFactory) +#else // iconengines plugins Q_IMPORT_PLUGIN(qsvgicon) // imageformats plugins @@ -20,6 +36,7 @@ Q_IMPORT_PLUGIN(qtga) // accessible plugins Q_IMPORT_PLUGIN(qtaccessiblewidgets) #endif +#endif MixxxApplication::MixxxApplication(int& argc, char** argv) From 03ce46e29a2e83d38a82f6c4d55c540a9df792ce Mon Sep 17 00:00:00 2001 From: RJ Skerry-Ryan Date: Mon, 14 May 2018 23:36:59 -0700 Subject: [PATCH 4/6] One more missing library. --- build/depends.py | 1 + 1 file changed, 1 insertion(+) diff --git a/build/depends.py b/build/depends.py index 5a8b5af564..774c10cfd7 100644 --- a/build/depends.py +++ b/build/depends.py @@ -417,6 +417,7 @@ def configure(self, build, conf): build.env.Append(LIBS = 'iphlpapi') # qt5network build.env.Append(LIBS = 'libEGL') # qt5opengl build.env.Append(LIBS = 'libGLESv2') # qt5opengl + build.env.Append(LIBS = 'mpr') # qt5core build.env.Append(LIBS = 'netapi32') # qt5core build.env.Append(LIBS = 'userenv') # qt5core build.env.Append(LIBS = 'uxtheme') # ? From 0c857e60511b65cebb08821ecebd636af10d7a56 Mon Sep 17 00:00:00 2001 From: RJ Skerry-Ryan Date: Sat, 19 May 2018 20:54:17 -0700 Subject: [PATCH 5/6] Add QWindowsVistaStyle support. --- build/depends.py | 6 ++++++ src/mixxxapplication.cpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/build/depends.py b/build/depends.py index 774c10cfd7..fec53d681a 100644 --- a/build/depends.py +++ b/build/depends.py @@ -461,6 +461,12 @@ def configure(self, build, conf): os.path.join(build.env['QTDIR'],'plugins/platforms')]) build.env.Append(LIBS = 'qwindows') + # styles (new in Qt5 for Windows) + if qt5: + build.env.Append(LIBPATH=[ + os.path.join(build.env['QTDIR'],'plugins/styles')]) + build.env.Append(LIBS = 'qwindowsvistastyle') + # sqldrivers (new in Qt5? or did we just start enabling them) if qt5: build.env.Append(LIBPATH=[ diff --git a/src/mixxxapplication.cpp b/src/mixxxapplication.cpp index c2d1c83ffa..4b0ea8b353 100644 --- a/src/mixxxapplication.cpp +++ b/src/mixxxapplication.cpp @@ -16,6 +16,8 @@ Q_IMPORT_PLUGIN(QSQLiteDriverPlugin) // platform plugins Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) +// style plugins +Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin) // imageformats plugins Q_IMPORT_PLUGIN(QSvgPlugin) Q_IMPORT_PLUGIN(QSvgIconPlugin) From ed8b240c683a2ada65b11c092909d22469bd0c18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Thu, 24 May 2018 00:28:21 +0200 Subject: [PATCH 6/6] don't use loadAquire(), it is not available in Qt4 --- src/mixer/playermanager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mixer/playermanager.cpp b/src/mixer/playermanager.cpp index b1fb18729e..5835c480f7 100644 --- a/src/mixer/playermanager.cpp +++ b/src/mixer/playermanager.cpp @@ -202,7 +202,7 @@ bool PlayerManager::isPreviewDeckGroup(const QString& group, int* number) { unsigned int PlayerManager::numDecks() { // We do this to cache the control once it is created so callers don't incur // a hashtable lookup every time they call this. - ControlProxy* pCOPNumDecks = m_pCOPNumDecks.loadAcquire(); + ControlProxy* pCOPNumDecks = load_atomic_pointer(m_pCOPNumDecks); if (pCOPNumDecks == nullptr) { pCOPNumDecks = new ControlProxy(ConfigKey("[Master]", "num_decks")); if (!pCOPNumDecks->valid()) { @@ -220,7 +220,7 @@ unsigned int PlayerManager::numDecks() { unsigned int PlayerManager::numSamplers() { // We do this to cache the control once it is created so callers don't incur // a hashtable lookup every time they call this. - ControlProxy* pCOPNumSamplers = m_pCOPNumSamplers.loadAcquire(); + ControlProxy* pCOPNumSamplers = load_atomic_pointer(m_pCOPNumSamplers); if (pCOPNumSamplers == nullptr) { pCOPNumSamplers = new ControlProxy(ConfigKey("[Master]", "num_samplers")); if (!pCOPNumSamplers->valid()) { @@ -238,7 +238,7 @@ unsigned int PlayerManager::numSamplers() { unsigned int PlayerManager::numPreviewDecks() { // We do this to cache the control once it is created so callers don't incur // a hashtable lookup every time they call this. - ControlProxy* pCOPNumPreviewDecks = m_pCOPNumPreviewDecks.loadAcquire(); + ControlProxy* pCOPNumPreviewDecks = load_atomic_pointer(m_pCOPNumPreviewDecks); if (pCOPNumPreviewDecks == nullptr) { pCOPNumPreviewDecks = new ControlProxy( ConfigKey("[Master]", "num_preview_decks"));