diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 65fe8225a..9c3e6560f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -168,11 +168,7 @@ jobs: key: "homebrew-${{ matrix.arch }}\ -${{ hashFiles('Brewfile.lock.json') }}" mingw: - strategy: - fail-fast: false - matrix: - arch: ['32', '64'] - name: mingw${{ matrix.arch }} + name: mingw64 runs-on: ubuntu-latest container: ghcr.io/lmms/linux.mingw:20.04 env: @@ -201,11 +197,11 @@ jobs: - name: Cache ccache data uses: actions/cache@v3 with: - key: "ccache-${{ github.job }}-${{ matrix.arch }}-${{ github.ref }}\ + key: "ccache-${{ github.job }}-64-${{ github.ref }}\ -${{ github.run_id }}" restore-keys: | - ccache-${{ github.job }}-${{ matrix.arch }}-${{ github.ref }}- - ccache-${{ github.job }}-${{ matrix.arch }}- + ccache-${{ github.job }}-64-${{ github.ref }}- + ccache-${{ github.job }}-64- path: ~/.ccache - name: Configure run: | @@ -213,7 +209,7 @@ jobs: cmake -S . \ -B build \ -DCMAKE_INSTALL_PREFIX=./install \ - -DCMAKE_TOOLCHAIN_FILE="./cmake/toolchains/MinGW-W64-${{ matrix.arch }}.cmake" \ + -DCMAKE_TOOLCHAIN_FILE="./cmake/toolchains/MinGW-W64-64.cmake" \ $CMAKE_OPTS - name: Build run: cmake --build build @@ -222,7 +218,7 @@ jobs: - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: mingw${{ matrix.arch }} + name: mingw64 path: build/lmms-*.exe - name: Trim ccache and print statistics run: | @@ -234,11 +230,7 @@ jobs: env: CCACHE_MAXSIZE: 500M msvc: - strategy: - fail-fast: false - matrix: - arch: ['x86', 'x64'] - name: msvc-${{ matrix.arch }} + name: msvc-x64 runs-on: windows-2019 env: CCACHE_MAXSIZE: 0 @@ -259,19 +251,19 @@ jobs: id: cache-deps uses: actions/cache@v3 with: - key: vcpkg-${{ matrix.arch }}-${{ hashFiles('vcpkg.json') }} + key: vcpkg-x64-${{ hashFiles('vcpkg.json') }} restore-keys: | - vcpkg-${{ matrix.arch }}- + vcpkg-x64- path: build\vcpkg_installed - name: Cache ccache data uses: actions/cache@v3 with: # yamllint disable rule:line-length - key: "ccache-${{ github.job }}-${{ matrix.arch }}-${{ github.ref }}\ + key: "ccache-${{ github.job }}-x64-${{ github.ref }}\ -${{ github.run_id }}" restore-keys: | - ccache-${{ github.job }}-${{ matrix.arch }}-${{ github.ref }}- - ccache-${{ github.job }}-${{ matrix.arch }}- + ccache-${{ github.job }}-x64-${{ github.ref }}- + ccache-${{ github.job }}-x64- path: ~\AppData\Local\ccache # yamllint enable rule:line-length - name: Install tools @@ -280,21 +272,13 @@ jobs: uses: jurplel/install-qt-action@b3ea5275e37b734d027040e2c7fe7a10ea2ef946 with: version: '5.15.2' - arch: |- - ${{ - fromJSON(' - { - "x86": "win32_msvc2019", - "x64": "win64_msvc2019_64" - } - ')[matrix.arch] - }} + arch: "win64_msvc2019_64" archives: qtbase qtsvg qttools cache: true - name: Set up build environment uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 with: - arch: ${{ matrix.arch }} + arch: x64 - name: Configure run: | ccache --zero-stats @@ -307,8 +291,8 @@ jobs: -DCMAKE_BUILD_TYPE=RelWithDebInfo ` -DUSE_COMPILE_CACHE=ON ` -DUSE_WERROR=ON ` - -DVCPKG_TARGET_TRIPLET="${{ matrix.arch }}-windows" ` - -DVCPKG_HOST_TRIPLET="${{ matrix.arch }}-windows" ` + -DVCPKG_TARGET_TRIPLET="x64-windows" ` + -DVCPKG_HOST_TRIPLET="x64-windows" ` -DVCPKG_MANIFEST_INSTALL="${{ env.should_install_manifest }}" env: should_install_manifest: @@ -324,7 +308,7 @@ jobs: - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: msvc-${{ matrix.arch }} + name: msvc-x64 path: build\lmms-*.exe - name: Trim ccache and print statistics run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bb4adc4a..89320bd9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,7 @@ include(StaticDependencies) STRING(TOUPPER "${CMAKE_PROJECT_NAME}" PROJECT_NAME_UCASE) -SET(PROJECT_YEAR 2024) +SET(PROJECT_YEAR 2025) SET(PROJECT_AUTHOR "LMMS Developers") SET(PROJECT_URL "https://lmms.io") diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake index b9aa4c8c6..8d6b84af4 100644 --- a/cmake/modules/DetectMachine.cmake +++ b/cmake/modules/DetectMachine.cmake @@ -77,13 +77,15 @@ IF(WIN32) unset(MSVC_VER) else() # Cross-compiled - # TODO: Handle Windows ARM64 targets - IF(WIN64) - SET(IS_X86_64 TRUE) - SET(LMMS_BUILD_WIN64 TRUE) - ELSE(WIN64) - SET(IS_X86 TRUE) - ENDIF(WIN64) + if($ENV{MSYSTEM_CARCH} MATCHES "aarch64") + set(IS_ARM64 TRUE) + set(LMMS_BUILD_WIN64 TRUE) + elseif(WIN64) + set(IS_X86_64 TRUE) + set(LMMS_BUILD_WIN64 TRUE) + else() + set(IS_X86 TRUE) + endif() endif() ELSE() # Detect target architecture based on compiler target triple e.g. "x86_64-pc-linux" diff --git a/cmake/nsis/CMakeLists.txt b/cmake/nsis/CMakeLists.txt index e926e074d..8363cacf7 100644 --- a/cmake/nsis/CMakeLists.txt +++ b/cmake/nsis/CMakeLists.txt @@ -35,7 +35,11 @@ SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS " " PARENT_SCOPE) IF(WIN64) - SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-${WIN_PLATFORM}-win64") + if(IS_ARM64) + set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-${WIN_PLATFORM}-arm64") + else() + set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-${WIN_PLATFORM}-win64") + endif() SET(CPACK_INSTALL_FIX "$PROGRAMFILES64\\\\${CPACK_PACKAGE_INSTALL_DIRECTORY}\\\\") SET(CPACK_NSIS_DEFINES " ${CPACK_NSIS_DEFINES} diff --git a/include/InstrumentTrackWindow.h b/include/InstrumentTrackWindow.h index f44430d0e..d4b285ccd 100644 --- a/include/InstrumentTrackWindow.h +++ b/include/InstrumentTrackWindow.h @@ -34,6 +34,7 @@ class QLabel; class QLineEdit; class QWidget; +class QMdiSubWindow; namespace lmms { @@ -134,6 +135,9 @@ private: //! required to keep the old look when using a variable sized tab widget void adjustTabSize(QWidget *w); + QMdiSubWindow* findSubWindowInParents(); + void updateSubWindow(); + InstrumentTrack * m_track; InstrumentTrackView * m_itv; diff --git a/include/SubWindow.h b/include/SubWindow.h index c5e3f02d4..cc9ff38a3 100644 --- a/include/SubWindow.h +++ b/include/SubWindow.h @@ -71,6 +71,10 @@ public: int titleBarHeight() const; int frameWidth() const; + // TODO Needed to update the title bar when replacing instruments. + // Update works automatically if QMdiSubWindows are used. + void updateTitleBar(); + protected: // hook the QWidget move/resize events to update the tracked geometry void moveEvent( QMoveEvent * event ) override; diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 8bd3a776b..503a0b6a9 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -353,7 +353,7 @@ bool DataFile::writeFile(const QString& filename, bool withResources) if (QDir(bundleDir).exists()) { showError(SongEditor::tr("Operation denied"), - SongEditor::tr("A bundle folder with that name already eists on the " + SongEditor::tr("A bundle folder with that name already exists on the " "selected path. Can't overwrite a project bundle. Please select a different " "name.")); diff --git a/src/core/midi/MidiJack.cpp b/src/core/midi/MidiJack.cpp index 29e7e27ec..a549059ab 100644 --- a/src/core/midi/MidiJack.cpp +++ b/src/core/midi/MidiJack.cpp @@ -57,7 +57,7 @@ static void JackMidiShutdown(void *arg) //: When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) QString msg_short = MidiJack::tr("JACK server down"); //: When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) - QString msg_long = MidiJack::tr("The JACK server seems to be shuted down."); + QString msg_long = MidiJack::tr("The JACK server seems to be shut down."); QMessageBox::information(gui::getGUI()->mainWindow(), msg_short, msg_long); } diff --git a/src/gui/SubWindow.cpp b/src/gui/SubWindow.cpp index 1fa0f25a7..a76f4055e 100644 --- a/src/gui/SubWindow.cpp +++ b/src/gui/SubWindow.cpp @@ -246,6 +246,10 @@ int SubWindow::frameWidth() const } +void SubWindow::updateTitleBar() +{ + adjustTitleBar(); +} /** diff --git a/src/gui/editors/StepRecorderWidget.cpp b/src/gui/editors/StepRecorderWidget.cpp index ffb45aa53..93fd59cf7 100644 --- a/src/gui/editors/StepRecorderWidget.cpp +++ b/src/gui/editors/StepRecorderWidget.cpp @@ -94,7 +94,7 @@ void StepRecorderWidget::setEndPosition(TimePos pos) void StepRecorderWidget::showHint() { - TextFloat::displayMessage(tr( "Hint" ), tr("Move recording curser using arrows"), + TextFloat::displayMessage(tr( "Hint" ), tr("Move recording cursor using arrows"), embed::getIconPixmap("hint")); } diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index 221338138..f6f30d020 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -59,7 +59,6 @@ #include "MainWindow.h" #include "PianoView.h" #include "PluginFactory.h" -#include "PluginView.h" #include "Song.h" #include "StringPairDrag.h" #include "SubWindow.h" @@ -284,25 +283,12 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : updateInstrumentView(); QMdiSubWindow* subWin = getGUI()->mainWindow()->addWindowedWidget( this ); - Qt::WindowFlags flags = subWin->windowFlags(); - if (!m_instrumentView->isResizable()) { - flags |= Qt::MSWindowsFixedSizeDialogHint; - // any better way than this? - } else { - subWin->setMaximumSize(m_instrumentView->maximumHeight() + 12, m_instrumentView->maximumWidth() + 208); - subWin->setMinimumSize( m_instrumentView->minimumWidth() + 12, m_instrumentView->minimumHeight() + 208); - } - flags &= ~Qt::WindowMaximizeButtonHint; - subWin->setWindowFlags( flags ); + // The previous call should have given us a sub window parent. Therefore + // we can reuse this method. + updateSubWindow(); - // Hide the Size and Maximize options from the system menu - // since the dialog size is fixed. - QMenu * systemMenu = subWin->systemMenu(); - systemMenu->actions().at( 2 )->setVisible( false ); // Size - systemMenu->actions().at( 4 )->setVisible( false ); // Maximize - - subWin->setWindowIcon( embed::getIconPixmap( "instrument_track" ) ); + subWin->setWindowIcon(embed::getIconPixmap("instrument_track")); subWin->hide(); } @@ -406,6 +392,8 @@ void InstrumentTrackWindow::modelChanged() m_tuningView->keymapCombo()->setModel(m_track->m_microtuner.keymapModel()); m_tuningView->rangeImportCheckbox()->setModel(m_track->m_microtuner.keyRangeImportModel()); updateName(); + + updateSubWindow(); } @@ -710,5 +698,75 @@ void InstrumentTrackWindow::adjustTabSize(QWidget *w) w->update(); } +QMdiSubWindow* InstrumentTrackWindow::findSubWindowInParents() +{ + // TODO Move to helper? Does not seem to be provided by Qt. + auto p = parentWidget(); + + while (p != nullptr) + { + auto mdiSubWindow = dynamic_cast(p); + if (mdiSubWindow) + { + return mdiSubWindow; + } + else + { + p = p->parentWidget(); + } + } + + return nullptr; +} + +void InstrumentTrackWindow::updateSubWindow() +{ + auto subWindow = findSubWindowInParents(); + if (subWindow && m_instrumentView) + { + Qt::WindowFlags flags = subWindow->windowFlags(); + + const auto instrumentViewResizable = m_instrumentView->isResizable(); + + if (instrumentViewResizable) + { + // TODO As of writing SlicerT is the only resizable instrument. Is this code specific to SlicerT? + const auto extraSpace = QSize(12, 208); + subWindow->setMaximumSize(m_instrumentView->maximumSize() + extraSpace); + subWindow->setMinimumSize(m_instrumentView->minimumSize() + extraSpace); + + flags &= ~Qt::MSWindowsFixedSizeDialogHint; + flags |= Qt::WindowMaximizeButtonHint; + } + else + { + flags |= Qt::MSWindowsFixedSizeDialogHint; + flags &= ~Qt::WindowMaximizeButtonHint; + + // The sub window might be reused from an instrument that was maximized. Show the sub window + // as normal, i.e. not maximized, if the instrument view is not resizable. + if (subWindow->isMaximized()) + { + subWindow->showNormal(); + } + } + + subWindow->setWindowFlags(flags); + + // Show or hide the Size and Maximize options from the system menu depending on whether the view is resizable or not + QMenu * systemMenu = subWindow->systemMenu(); + systemMenu->actions().at(2)->setVisible(instrumentViewResizable); // Size + systemMenu->actions().at(4)->setVisible(instrumentViewResizable); // Maximize + + // TODO This is only needed if the sub window is implemented with LMMS' own SubWindow class. + // If an QMdiSubWindow is used everything works automatically. It seems that SubWindow is + // missing some implementation details that QMdiSubWindow has. + auto subWin = dynamic_cast(subWindow); + if (subWin) + { + subWin->updateTitleBar(); + } + } +} } // namespace lmms::gui