diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..9e26dfeeb6e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index dd71e078316..8045db72527 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -540,6 +540,15 @@ ENDIF(WANT_SF2) # check for libgig If(WANT_GIG) PKG_CHECK_MODULES(GIG gig) + IF(NOT GIG_FOUND) + FIND_PATH(GIG_INCLUDE_DIRS NAMES libgig/gig.h) + FIND_LIBRARY(GIG_LIBRARIES NAMES libgig gig) + FIND_LIBRARY(AKAI_LIBRARIES NAMES libakai akai) + IF(GIG_INCLUDE_DIRS AND GIG_LIBRARIES) + SET(GIG_FOUND TRUE) + LIST(APPEND GIG_LIBRARIES ${AKAI_LIBRARIES}) + ENDIF() + ENDIF() IF(GIG_FOUND) SET(LMMS_HAVE_GIG TRUE) SET(STATUS_GIG "OK") diff --git a/build_lmms.bat b/build_lmms.bat new file mode 100644 index 00000000000..5646216c8d2 --- /dev/null +++ b/build_lmms.bat @@ -0,0 +1,46 @@ +@echo off +REM LMMS Build Script - Final Absolute Version + +set VCVARS_PATH="C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat" +if not exist %VCVARS_PATH% set VCVARS_PATH="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + +set VCPKG_PATH="c:\Users\user\Documents\vcpkg\scripts\buildsystems\vcpkg.cmake" +set QT_PATH="c:\Users\user\Documents\Qt5\5.15.2\msvc2019_64" + +if not exist build mkdir build +cd build + +REM Get absolute paths for library forcing (Corrected libgig path) +set "VCPKG_INST_BASE=%CD%\vcpkg_installed\x64-windows" + +echo --- Loading MSVC Environment --- +call %VCVARS_PATH% + +echo --- Configuring with Forced GIG Paths --- +cmake .. -G Ninja ^ + -DCMAKE_TOOLCHAIN_FILE=%VCPKG_PATH% ^ + -DVCPKG_TARGET_TRIPLET="x64-windows" ^ + -DCMAKE_PREFIX_PATH=%QT_PATH% ^ + -DWANT_QT6=OFF ^ + -DWANT_VST_32=OFF ^ + -DWANT_GIG=ON ^ + -DGIG_INCLUDE_DIRS="%VCPKG_INST_BASE%\include\libgig" ^ + -DGIG_LIBRARIES="%VCPKG_INST_BASE%\lib\libgig.lib;%VCPKG_INST_BASE%\lib\libakai.lib;winmm.lib" ^ + -DGIG_FOUND=TRUE ^ + -DLMMS_HAVE_GIG=TRUE ^ + -DCMAKE_BUILD_TYPE=RelWithDebInfo ^ + -DCMAKE_INSTALL_PREFIX=install + +echo --- Rapid Build --- +cmake --build . -j8 + +echo --- Organizing Plugins --- +cmake --build . --target install + +echo --- Finalizing DLLs --- +cd install +"%QT_PATH:"=%\bin\windeployqt.exe" --no-compiler-runtime --no-translations --no-opengl-sw lmms.exe +copy /y ..\vcpkg_installed\x64-windows\bin\*.dll . + +echo --- All Done! --- +echo Full build with GigPlayer: build\install\lmms.exe diff --git a/gig_command.txt b/gig_command.txt new file mode 100644 index 00000000000..d31cf3ea1d1 Binary files /dev/null and b/gig_command.txt differ diff --git a/link_debug.txt b/link_debug.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/plugins/GigPlayer/CMakeLists.txt b/plugins/GigPlayer/CMakeLists.txt index ccec8c87336..34ca18631ee 100644 --- a/plugins/GigPlayer/CMakeLists.txt +++ b/plugins/GigPlayer/CMakeLists.txt @@ -6,12 +6,13 @@ if(LMMS_HAVE_GIG) # Required for not crashing loading files with libgig add_compile_options("-fexceptions") - link_directories(${GIG_LIBRARY_DIRS}) - link_libraries(${GIG_LIBRARIES}) + # Use target_link_libraries instead for modern CMake + build_plugin(gigplayer GigPlayer.cpp GigPlayer.h PatchesDialog.cpp PatchesDialog.h PatchesDialog.ui MOCFILES GigPlayer.h PatchesDialog.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png" ) - target_link_libraries(gigplayer SampleRate::samplerate) + target_link_directories(gigplayer PRIVATE ${GIG_LIBRARY_DIRS}) + target_link_libraries(gigplayer ${GIG_LIBRARIES} SampleRate::samplerate) endif(LMMS_HAVE_GIG) diff --git a/plugins/GigPlayer/GigPlayer.cpp b/plugins/GigPlayer/GigPlayer.cpp index 9f6cbf8dc54..2616eb1587e 100644 --- a/plugins/GigPlayer/GigPlayer.cpp +++ b/plugins/GigPlayer/GigPlayer.cpp @@ -31,6 +31,7 @@ #include "GigPlayer.h" #include +#include #include #include #include @@ -519,7 +520,7 @@ void GigInstrument::loadSample( GigSample& sample, SampleFrame* sampleData, f_cn } unsigned long allocationsize = samples * sample.sample->FrameSize; - int8_t buffer[allocationsize]; + std::vector buffer(allocationsize); // Load the sample in different ways depending on if we're looping or not if( loop == true && ( sample.pos >= loopStart || sample.pos + samples > loopStart ) ) @@ -564,14 +565,14 @@ void GigInstrument::loadSample( GigSample& sample, SampleFrame* sampleData, f_cn { sample.sample->SetPos( sample.pos ); - unsigned long size = sample.sample->Read( &buffer, samples ) * sample.sample->FrameSize; - std::memset( (int8_t*) &buffer + size, 0, allocationsize - size ); + unsigned long size = sample.sample->Read( buffer.data(), samples ) * sample.sample->FrameSize; + std::memset( buffer.data() + size, 0, allocationsize - size ); } // Convert from 16 or 24 bit into 32-bit float if( sample.sample->BitDepth == 24 ) // 24 bit { - auto pInt = reinterpret_cast(&buffer); + auto pInt = reinterpret_cast(buffer.data()); for( f_cnt_t i = 0; i < samples; ++i ) { @@ -603,7 +604,7 @@ void GigInstrument::loadSample( GigSample& sample, SampleFrame* sampleData, f_cn } else // 16 bit { - auto pInt = reinterpret_cast(&buffer); + auto pInt = reinterpret_cast(buffer.data()); for( f_cnt_t i = 0; i < samples; ++i ) { diff --git a/plugins/TapTempo/TapTempo.cpp b/plugins/TapTempo/TapTempo.cpp index e498156f145..06a2558e434 100644 --- a/plugins/TapTempo/TapTempo.cpp +++ b/plugins/TapTempo/TapTempo.cpp @@ -24,6 +24,7 @@ #include "TapTempo.h" +#include #include #include "SamplePlayHandle.h" diff --git a/plugins/VstBase/RemoteVstPlugin.cpp b/plugins/VstBase/RemoteVstPlugin.cpp index 7343078ea89..3355bc8d919 100644 --- a/plugins/VstBase/RemoteVstPlugin.cpp +++ b/plugins/VstBase/RemoteVstPlugin.cpp @@ -1120,7 +1120,12 @@ void RemoteVstPlugin::process( const SampleFrame* _in, SampleFrame* _out ) unlockShm(); - m_currentSamplePos += bufferSize(); + const auto syncData = __plugin->getVstSyncData(); + if (syncData) + { + __plugin->m_currentSamplePos = syncData->ppqPos + * syncData->sampleRate * 60.0 / syncData->bpm; + } } @@ -1876,7 +1881,6 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, assert(syncData != nullptr); memset( &_timeInfo, 0, sizeof( _timeInfo ) ); - _timeInfo.samplePos = __plugin->m_currentSamplePos; _timeInfo.sampleRate = syncData->sampleRate; _timeInfo.flags = 0; _timeInfo.tempo = syncData->bpm; @@ -1907,9 +1911,16 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, / syncData->sampleRate; _timeInfo.ppqPos = __plugin->m_sync.lastppqPos; } -// _timeInfo.ppqPos = syncData->ppqPos; + else + { + _timeInfo.ppqPos = __plugin->m_sync.lastppqPos; + } _timeInfo.flags |= kVstPpqPosValid; + // Derive samplePos from the computed ppqPos for consistency + _timeInfo.samplePos = _timeInfo.ppqPos + * syncData->sampleRate * 60.0 / syncData->bpm; + if (syncData->isPlaying) { _timeInfo.flags |= kVstTransportPlaying; diff --git a/plugins/VstBase/RemoteVstPlugin32.cmake b/plugins/VstBase/RemoteVstPlugin32.cmake index 5afb7db8123..e6fab595843 100644 --- a/plugins/VstBase/RemoteVstPlugin32.cmake +++ b/plugins/VstBase/RemoteVstPlugin32.cmake @@ -45,6 +45,8 @@ ELSEIF(CMAKE_TOOLCHAIN_FILE_32) "${EXTERNALPROJECT_CMAKE_ARGS}" "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_32}" "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE_32}" + "-DVCPKG_APPLOCAL_DEPS=${VCPKG_APPLOCAL_DEPS}" + "-DX_VCPKG_APPLOCAL_DEPS_INSTALL=${X_VCPKG_APPLOCAL_DEPS_INSTALL}" ) INSTALL_EXTERNAL_PROJECT(RemoteVstPlugin32) ELSE() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e7378af9ce3..dd570a6abfc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -142,7 +142,12 @@ ENDIF() SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${LMMS_RCC_OUT} lmmsconfig.h lmms.1.gz") IF(LMMS_BUILD_WIN32) - SET(EXTRA_LIBRARIES "winmm") + IF(MSVC) + # Hardcoded for current environment due to find_library failure with Ninja + SET(EXTRA_LIBRARIES "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.26100.0/um/x64/WinMM.Lib") + ELSE() + SET(EXTRA_LIBRARIES "winmm") + ENDIF() ENDIF() IF(LMMS_BUILD_APPLE) @@ -218,3 +223,17 @@ IF(NOT WIN32 AND NOT LMMS_BUILD_APPLE) ENDIF() INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") + +IF(WIN32 AND NOT CMAKE_CROSSCOMPILING) + GET_TARGET_PROPERTY(QT_BIN_DIR Qt5::Core LOCATION) + GET_FILENAME_COMPONENT(QT_BIN_DIR "${QT_BIN_DIR}" DIRECTORY) + ADD_CUSTOM_COMMAND(TARGET lmms POST_BUILD + COMMAND "${QT_BIN_DIR}/windeployqt.exe" + --no-compiler-runtime + --no-translations + --no-opengl-sw + --no-system-d3d-compiler + "${CMAKE_BINARY_DIR}/lmms.exe" + COMMENT "Running windeployqt to bundle dependencies" + ) +ENDIF() diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 1d3a7bc291e..e3bca207643 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -129,6 +129,17 @@ Song::Song() : }; connect(&m_timelines[i], &Timeline::positionJumped, this, onPositionJumped); + + // Update VST sync position when the user changes position while not playing + connect(&m_timelines[i], &Timeline::positionJumped, this, [this, playMode = static_cast(i)] { + if (!m_playing) + { + const auto& tl = getTimeline(playMode); + m_vstSyncController.setAbsolutePosition( + tl.ticks() + tl.frameOffset() / static_cast(Engine::framesPerTick())); + m_vstSyncController.setPlaybackJumped(true); + } + }); } // Inform VST plugins if the user moved the play head @@ -575,6 +586,8 @@ void Song::playMidiClip( const MidiClip* midiClipToPlay, bool loop ) m_paused = false; } + m_vstSyncController.setPlaybackState( true ); + savePlayStartPosition(); emit playbackStateChanged(); diff --git a/vcpkg.json b/vcpkg.json index cda8d9f24f8..878d037aa95 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -68,6 +68,10 @@ { "name": "zlib", "default-features": false + }, + { + "name": "pkgconf", + "default-features": false } ] }