diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000000..3e996b06ee5 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,277 @@ +name: Build + +on: + push: + pull_request: + +jobs: + build: + strategy: + matrix: + include: + - name: Ubuntu 18.04 (gcc) + os: ubuntu-18.04 + cmake_args: >- + -DFAAD=ON + -DKEYFINDER=ON + -DLOCALECOMPARE=ON + -DMAD=ON + -DMODPLUG=ON + -DWAVPACK=ON + cmake_generator: Unix Makefiles + ctest_args: + compiler_cache: ccache + compiler_cache_path: ~/.ccache + cpack_generator: DEB + buildenv_basepath: /home/runner/buildenv + buildenv_script: tools/ubuntu_buildenv.sh + artifacts_name: Ubuntu 18.04 DEB + artifacts_path: cmake_build/*.deb + qt_qpa_platform: offscreen + - name: Ubuntu 20.04 (gcc) + os: ubuntu-20.04 + cmake_args: >- + -DFFMPEG=ON + -DKEYFINDER=ON + -DLOCALECOMPARE=ON + -DMAD=ON + -DMODPLUG=ON + -DWAVPACK=ON + cmake_generator: Unix Makefiles + ctest_args: + compiler_cache: ccache + compiler_cache_path: ~/.ccache + cpack_generator: DEB + buildenv_basepath: /home/runner/buildenv + buildenv_script: tools/ubuntu_buildenv.sh + artifacts_name: Ubuntu 20.04 DEB + artifacts_path: cmake_build/*.deb + qt_qpa_platform: offscreen + - name: macOS 10.15 + os: macos-10.15 + cmake_args: >- + -DCOREAUDIO=ON + -DHSS1394=ON + -DMACOS_BUNDLE=ON + cmake_generator: Unix Makefiles + # TODO: Fix this broken test on macOS + ctest_args: --exclude-regex DirectoryDAOTest.relocateDirectory + cpack_generator: DragNDrop + compiler_cache: ccache + compiler_cache_path: /Users/runner/Library/Caches/ccache + buildenv_basepath: /Users/runner/buildenv + buildenv_script: tools/macos_buildenv.sh + artifacts_name: macOS DMG + artifacts_path: cmake_build/*.dmg + qt_qpa_platform: offscreen + - name: Windows 2019 (MSVC) + os: windows-2019 + cmake_args: >- + -DHSS1394=ON + -DKEYFINDER=OFF + -DLOCALECOMPARE=ON + -DMAD=ON + -DMEDIAFOUNDATION=ON + -DSTATIC_DEPS=ON + cc: cl + cxx: cl + cmake_generator: Ninja + # TODO: Fix these broken tests on Windows + ctest_args: --exclude-regex '^AutoDJProcessorTest.*$' + cpack_generator: WIX + compiler_cache: clcache + compiler_cache_path: ${{ github.workspace }}\clcache + buildenv_basepath: C:\buildenv + buildenv_script: tools/windows_buildenv.bat + artifacts_name: Windows Installer + artifacts_path: cmake_build/*.msi + qt_qpa_platform: windows + + env: + # macOS codesigning + APPLE_CODESIGN_IDENTITY: 2C2B5D3EDCE82BA55E22E9A67F16F8D03E390870 + MACOS_CODESIGN_OPENSSL_PASSWORD: ${{ secrets.MACOS_CODESIGN_OPENSSL_PASSWORD }} + MACOS_CODESIGN_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CODESIGN_CERTIFICATE_PASSWORD }} + + runs-on: ${{ matrix.os }} + name: ${{ matrix.name }} + steps: + - name: "Check out repository" + uses: actions/checkout@v2 + + - name: "Set up cmake" + uses: jwlawson/actions-setup-cmake@v1.4 + with: + # This should always match the mininum required version in + # our CMakeLists.txt + cmake-version: '3.13.x' + + - name: "[Windows] Install additional build tools" + if: runner.os == 'Windows' + run: python -m pip install ninja git+https://github.com/frerich/clcache.git + + - name: "[Windows] Set up MSVC Developer Command Prompt" + if: runner.os == 'Windows' + uses: seanmiddleditch/gha-setup-vsdevenv@v3 + + - name: "[macOS/Windows] Get build environment name" + if: runner.os != 'Linux' + id: buildenv_name + run: ${{ matrix.buildenv_script }} name + + - name: "[macOS/Windows] Set up build environment cache" + if: runner.os != 'Linux' + uses: actions/cache@v2 + with: + path: ${{ matrix.buildenv_basepath }} + key: ${{ runner.os }}-buildenv-${{ env.BUILDENV_NAME }} + + - name: "[macOS] Import Apple code signing identity" + id: apple_codesign + if: runner.os == 'macOS' && env.MACOS_CODESIGN_OPENSSL_PASSWORD != null && env.MACOS_CODESIGN_CERTIFICATE_PASSWORD != null + run: | + # Decrypt the certificate + openssl enc -aes-256-cbc -d -md sha512 \ + -k "${MACOS_CODESIGN_OPENSSL_PASSWORD}" \ + -in /Users/runner/work/mixxx/mixxx/cmake/macos_developer_id_codesign_certificate.p12.enc \ + -out ~/certificate.p12 + + # Create a temporary keychain for the certificate and import it. + security create-keychain -p mixxx Mixxx.keychain + security unlock-keychain -p mixxx Mixxx.keychain + security import ~/certificate.p12 -k Mixxx.keychain \ + -P "${MACOS_CODESIGN_CERTIFICATE_PASSWORD}" -A + security set-key-partition-list -S "apple-tool:,apple:" -k mixxx Mixxx.keychain + # Add keychain to search list + security list-keychains -s Mixxx.keychain + # Prevent keychain access from timing out + security set-keychain-settings Mixxx.keychain + echo "CMAKE_ARGS_EXTRA=${CMAKE_ARGS_EXTRA} -DAPPLE_CODESIGN_IDENTITY=${APPLE_CODESIGN_IDENTITY}" >> "${GITHUB_ENV}" + + - name: "[Windows] Set up Windows code signing" + env: + WINDOWS_CODESIGN_CERTIFICATE_PATH: ${{ github.workspace }}\build\certificates\windows_sectigo_codesign_certificate.pfx + WINDOWS_CODESIGN_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_CERTIFICATE_PASSWORD }} + WINDOWS_CODESIGN_SECURE_FILE_SALT: ${{ secrets.WINDOWS_CODESIGN_SECURE_FILE_SALT }} + WINDOWS_CODESIGN_SECURE_FILE_SECRET: ${{ secrets.WINDOWS_CODESIGN_SECURE_FILE_SECRET }} + if: runner.os == 'Windows' && env.WINDOWS_CODESIGN_SECURE_FILE_SALT != null && env.WINDOWS_CODESIGN_SECURE_FILE_SECRET != null + run: | + iex ((New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/appveyor/secure-file/master/install.ps1')) + appveyor-tools/secure-file -decrypt "$Env:WINDOWS_CODESIGN_CERTIFICATE_PATH.enc" -secret "$Env:WINDOWS_CODESIGN_SECURE_FILE_SECRET" -salt "$Env:WINDOWS_CODESIGN_SECURE_FILE_SALT" + Add-Content -Path "$Env:GITHUB_ENV" -Value "WINDOWS_CODESIGN_CERTIFICATE_PATH=$Env:WINDOWS_CODESIGN_CERTIFICATE_PATH" + Add-Content -Path "$Env:GITHUB_ENV" -Value "WINDOWS_CODESIGN_CERTIFICATE_PASSWORD=$Env:WINDOWS_CODESIGN_CERTIFICATE_PASSWORD" + Add-Content -Path "$Env:GITHUB_ENV" -Value "CMAKE_ARGS_EXTRA=-DWINDOWS_CODESIGN=ON" + + - name: "Set up build environment" + id: buildenv + run: ${{ matrix.buildenv_script }} setup + env: + BUILDENV_BASEPATH: ${{ matrix.buildenv_basepath }} + + - name: "Set compiler cache size limit" + # Set size to 2 GiB + run: ${{ matrix.compiler_cache }} -M 2097152 + + - name: "Set up compiler cache" + uses: actions/cache@v2 + with: + path: ${{ matrix.compiler_cache_path }} + key: ${{ matrix.os }}-${{ matrix.compiler_cache }}-${{ github.head_ref }}-${{ github.run_number }} + restore-keys: | + ${{ matrix.os }}-${{ matrix.compiler_cache }}-${{ github.head_ref }} + ${{ matrix.os }}-${{ matrix.compiler_cache }} + + - name: "Create build directory" + run: mkdir cmake_build + + - name: "Configure" + run: >- + cmake + -G "${{ matrix.cmake_generator }}" + -DCMAKE_BUILD_TYPE=Release + "-DCMAKE_PREFIX_PATH=${{ env.CMAKE_PREFIX_PATH }}" + -DDEBUG_ASSERTIONS_FATAL=ON + -DQt5_DIR=${{ env.QT_PATH }} ${{ matrix.cmake_args }} ${{ env.CMAKE_ARGS_EXTRA }} + -DBATTERY=ON + -DBROADCAST=ON + -DBULK=ON + -DHID=ON + -DLILV=ON + -DOPUS=ON + -DQTKEYCHAIN=ON + -DVINYLCONTROL=ON + .. + working-directory: cmake_build + env: + CC: ${{ matrix.cc }} + CXX: ${{ matrix.cxx }} + + - name: "[Ubuntu/macOS] Set up gcc/clang problem matcher" + if: runner.os != 'Windows' + uses: ammaraskar/gcc-problem-matcher@master + + - name: "[Windows] Set up MSVC problem matcher" + if: runner.os == 'Windows' + uses: ammaraskar/msvc-problem-matcher@master + + - name: "Build" + run: cmake --build . + working-directory: cmake_build + env: + CC: ${{ matrix.cc }} + CXX: ${{ matrix.cxx }} + CMAKE_BUILD_PARALLEL_LEVEL: 2 + # GitHub Actions automatically zstd compresses caches + CCACHE_NOCOMPRESS: true + CLCACHE_COMPRESS: false + CLCACHE_HARDLINK: true + + - name: "Print compiler cache stats" + run: ${{ matrix.compiler_cache }} -s + + - name: "Test" + run: ctest --timeout 45 ${{ matrix.ctest_args }} + working-directory: cmake_build + env: + # Render analyzer waveform tests to an offscreen buffer + QT_QPA_PLATFORM: ${{ matrix.qt_qpa_platform }} + GTEST_COLOR: 1 + CTEST_PARALLEL_LEVEL: 2 + CTEST_OUTPUT_ON_FAILURE: 1 + + - name: Benchmark + run: cmake --build . --target mixxx-benchmark + working-directory: cmake_build + env: + # Render analyzer waveform tests to an offscreen buffer + QT_QPA_PLATFORM: ${{ matrix.qt_qpa_platform }} + + - name: "Package" + run: cpack -G ${{ matrix.cpack_generator }} -V + working-directory: cmake_build + + - name: "[macOS] Sign Package" + if: runner.os == 'macOS' && env.MACOS_CODESIGN_OPENSSL_PASSWORD != null && env.MACOS_CODESIGN_CERTIFICATE_PASSWORD != null + run: codesign --verbose=4 --options runtime --sign "${APPLE_CODESIGN_IDENTITY}" --entitlements ../build/osx/entitlements.plist *.dmg + working-directory: cmake_build + + - name: "[Windows] Sign Package" + if: runner.os == 'Windows' && env.WINDOWS_CODESIGN_CERTIFICATE_PATH != null && env.WINDOWS_CODESIGN_CERTIFICATE_PASSWORD != null + run: signtool sign /f $Env:WINDOWS_CODESIGN_CERTIFICATE_PATH /p $Env:WINDOWS_CODESIGN_CERTIFICATE_PASSWORD *.msi + working-directory: cmake_build + + - name: "[macOS] Upload build to downloads.mixxx.org" + # skip deploying Ubuntu builds to downloads.mixxx.org because these are deployed to the PPA + if: runner.os == 'macOS' && env.DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY_PASSWORD != null + run: tools/deploy.sh + env: + FILE_TO_DEPLOY: ${{ matrix.artifacts_path }} + OS: ${{ runner.os }} + DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY_PASSWORD: ${{ secrets.DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY_PASSWORD }} + SSH_KEY: build/certificates/downloads-hostgator.mixxx.org.key + + - name: "Upload GitHub Actions artifacts" + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.artifacts_name }} + path: ${{ matrix.artifacts_path }} diff --git a/.github/workflows/clazy.yml b/.github/workflows/clazy.yml index f64fe067865..59ea855cd0c 100644 --- a/.github/workflows/clazy.yml +++ b/.github/workflows/clazy.yml @@ -79,7 +79,8 @@ jobs: - name: Set up problem matcher uses: ammaraskar/gcc-problem-matcher@master - name: Build - run: cmake --build . -j $(nproc) + # Do not abort on errors and build/check the whole project + run: cmake --build . -j $(nproc) -- --keep-going working-directory: cmake_build env: - CLAZY_CHECKS: level1,no-rule-of-two-soft,no-non-pod-global-static,no-qproperty-without-notify,no-wrong-qevent-cast + CLAZY_CHECKS: level2,no-rule-of-two-soft,no-non-pod-global-static,no-qproperty-without-notify,no-wrong-qevent-cast,no-qstring-allocations,no-function-args-by-value,no-copyable-polymorphic,no-ctor-missing-parent-argument,no-missing-qobject-macro,no-rule-of-three,no-returning-void-expression,no-missing-typeinfo,no-base-class-event diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index e1f6e70933d..87e7b66f1c1 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -8,33 +8,48 @@ jobs: pre-commit: name: Detecting code style issues runs-on: ubuntu-latest - if: github.event_name == 'push' steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - name: "Check out repository" + uses: actions/checkout@v2 + with: + fetch-depth: 2 + + - name: "Set up Python" + uses: actions/setup-python@v2 + - name: Install clang-format run: sudo apt-get update && sudo apt-get install -y --no-install-recommends clang-format-10 - - uses: pre-commit/action@v2.0.0 + + - name: "Detect code style issues (push)" + uses: pre-commit/action@v2.0.0 + if: github.event_name == 'push' # There are too many files in the repo that have formatting issues. We'll # disable these checks for now when pushing directly (but still run these # on Pull Requests!). env: SKIP: end-of-file-fixer,trailing-whitespace,clang-format,eslint,no-commit-to-branch - pre-commit-pr: - name: Detecting code style issues - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 2 - - uses: actions/setup-python@v2 - - name: Install clang-format - run: sudo apt-get update && sudo apt-get install -y --no-install-recommends clang-format-10 - - uses: pre-commit/action@v2.0.0 + + - name: "Detect code style issues (pull_request)" + uses: pre-commit/action@v2.0.0 + if: github.event_name == 'pull_request' env: SKIP: no-commit-to-branch with: # HEAD is the not yet integrated PR merge commit +refs/pull/xxxx/merge # HEAD^1 is the PR target branch and HEAD^2 is the HEAD of the source branch extra_args: --from-ref HEAD^1 --to-ref HEAD + + - name: "Generate patch file" + if: failure() + run: | + git diff-index -p HEAD > "${PATCH_FILE}" + [ -s "${PATCH_FILE}" ] && echo "UPLOAD_PATCH_FILE=${PATCH_FILE}" >> "${GITHUB_ENV}" + env: + PATCH_FILE: pre-commit.patch + + - name: "Upload patch artifact" + if: failure() && env.UPLOAD_PATCH_FILE != null + uses: actions/upload-artifact@v2 + with: + name: ${{ env.UPLOAD_PATCH_FILE }} + path: ${{ env.UPLOAD_PATCH_FILE }} diff --git a/.gitignore b/.gitignore index 6b294dd1af7..40bfdd98f42 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,6 @@ compile_commands.json # Exclude documentation generated by Doxygen /doxygen/ + +# Exclude buildenv directory from our helper scripts +/buildenv/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index be362dd1030..37b908690c8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -47,7 +47,7 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v3.3.0 hooks: - - id: check-byte-order-marker + - id: fix-byte-order-marker exclude: ^.*(\.cbproj|\.groupproj|\.props|\.sln|\.vcxproj|\.vcxproj.filters)$ - id: check-case-conflict - id: check-json diff --git a/.travis.yml b/.travis.yml index ebbc68a195e..986e207cdb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -248,12 +248,3 @@ addons: notifications: webhooks: - https://mixxx.zulipchat.com/api/v1/external/travis?stream=travis&topic=build-status&api_key=$ZULIP_API_KEY - -deploy: - provider: script - skip_cleanup: true - # Deploy is executed from cmake_build. - script: ../build/travis/deploy.sh - on: - all_branches: true - condition: "\"${TRAVIS_JOB_NAME}\" =~ CMake" diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fc17dc6348..52de57bf3df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,10 @@ else() set(LLVM_CLANG false) endif() +if(APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS 10.14) + add_compile_options(-fno-aligned-allocation) +endif() + # CMake implicitly sets the variable MSVC to true for Microsoft # Visual C++ or another compiler simulating Visual C++. # https://cmake.org/cmake/help/latest/variable/MSVC.html @@ -935,6 +939,17 @@ if(GNU_GCC OR LLVM_CLANG) APPEND_STRING PROPERTY COMPILE_OPTIONS -Wno-unused-parameter -Wno-switch ) +elseif(MSVC) + set_property( + SOURCE src/library/rekordbox/rekordbox_anlz.cpp + APPEND_STRING + PROPERTY COMPILE_OPTIONS /w + ) + set_property( + SOURCE src/library/rekordbox/rekordbox_pdb.cpp + APPEND_STRING + PROPERTY COMPILE_OPTIONS /w + ) endif() option(WARNINGS_PEDANTIC "Let the compiler show even more warnings" OFF) @@ -943,6 +958,7 @@ if(MSVC) target_compile_options(mixxx-lib PUBLIC /W4) else() target_compile_options(mixxx-lib PUBLIC /W3) + target_compile_definitions(mixxx-lib PUBLIC _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING _CRT_SECURE_NO_WARNINGS) endif() else() target_compile_options(mixxx-lib PUBLIC -Wall -Wextra -Wfloat-conversion) @@ -1074,29 +1090,79 @@ if (APPLE) set(MACOS_BUNDLE_VERSION "${CMAKE_PROJECT_VERSION}") set(MACOS_BUNDLE_SHORTVERSION "${CMAKE_PROJECT_VERSION}") - set(MACOS_BUNDLE_MINOSVERSION "10.12.0") set_target_properties(mixxx PROPERTIES MACOSX_BUNDLE true MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos_bundle.plist.in" ) - else() - get_filename_component(QT_PLUGIN_DIR "${Qt5_DIR}/../../../plugins/" ABSOLUTE) - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-mixxx.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/run-mixxx.sh" @ONLY) - execute_process(COMMAND chmod +x "${CMAKE_CURRENT_BINARY_DIR}/run-mixxx.sh") endif() else() - include(InstallRequiredSystemLibraries) - install( - FILES - ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} - DESTINATION - "${MIXXX_INSTALL_BINDIR}" - COMPONENT - Libraries + include(InstallRequiredSystemLibraries) + install( + FILES + ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} + DESTINATION + "${MIXXX_INSTALL_BINDIR}" + COMPONENT + Libraries + ) +endif() + +if(WIN32) + option(WINDOWS_CODESIGN "Sign Windows executables and libraries with digital certificate" OFF) + mark_as_advanced(WINDOWS_CODESIGN) + if(WINDOWS_CODESIGN) + set(WINDOWS_CODESIGN_CERTIFICATE_PATH "$ENV{WINDOWS_CODESIGN_CERTIFICATE_PATH}" CACHE STRING "Path to signtool certificate") + set(WINDOWS_CODESIGN_CERTIFICATE_PASSWORD "$ENV{WINDOWS_CODESIGN_CERTIFICATE_PASSWORD}" CACHE STRING "Password of signtool certificate") + if("${WINDOWS_CODESIGN_CERTIFICATE_PATH}" STREQUAL "" AND "${WINDOWS_CODESIGN_CERTIFICATE_PASSWORD}" STREQUAL "") + set(WINDOWS_CODESIGN_ARGS /a /t http://timestamp.verisign.com/scripts/timstamp.dll CACHE STRING "parameters for signtool (list)") + else() + set(WINDOWS_CODESIGN_ARGS /f ${WINDOWS_CODESIGN_CERTIFICATE_PATH} /p ${WINDOWS_CODESIGN_CERTIFICATE_PASSWORD} CACHE STRING "parameters for signtool (list)") + endif() + find_program(SIGNTOOL_EXECUTABLE signtool) + if(NOT SIGNTOOL_EXECUTABLE) + message(FATAL_ERROR "signtool is not found. Signing executables not possible") + endif() + message(STATUS "Found signtool: ${SIGNTOOL_EXECUTABLE}") + + # Check if we're able to sign an executable + if(NOT DEFINED WINDOWS_CODESIGN_OK) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/testsign.c "int main(){return 0;}") + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/testsign) + try_compile( + RESULT ${CMAKE_CURRENT_BINARY_DIR}/testsign ${CMAKE_CURRENT_BINARY_DIR}/testsign.c + COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/testsign.exe + ) + execute_process( + COMMAND ${SIGNTOOL_EXECUTABLE} sign ${WINDOWS_CODESIGN_ARGS} ${CMAKE_CURRENT_BINARY_DIR}/testsign.exe + RESULT_VARIABLE ERR OUTPUT_QUIET + ) + if(ERR EQUAL 0) + message(STATUS "Windows codesigning via signtool is working") + set(WINDOWS_CODESIGN_OK 1 CACHE INTERNAL "Can sign executables") + else() + message(FATAL_ERROR "Could NOT codesign test sample (signtool failed)") + set(WINDOWS_CODESIGN_OK 0 CACHE INTERNAL "Invalid or missing certificate") + endif() + endif() + mark_as_advanced(SIGNTOOL_EXECUTABLE SIGNTOOL_ARGS) + endif() + + macro(windows_codesign_target CODESIGN_TARGET) + add_custom_command( + TARGET "${CODESIGN_TARGET}" POST_BUILD + COMMAND ${SIGNTOOL_EXECUTABLE} sign ${WINDOWS_CODESIGN_ARGS} $ + COMMENT "Signining target ${CODESIGN_TARGET}" + VERBATIM ) + endmacro() + + if(WINDOWS_CODESIGN) + windows_codesign_target(mixxx) + endif() endif() + install( TARGETS mixxx @@ -1131,21 +1197,6 @@ install( FILES_MATCHING PATTERN "*.qm" ) -if(WIN32) -install( - # I haven't seen a way to determine where the translations dir is, so I am making - # some assumptions here, and assuming that Qt5_DIR points to Qt-5.14.2/lib/cmake/Qt5 - # which is what my configuration tells me. - DIRECTORY - "${Qt5_DIR}/../../../translations" - DESTINATION - "${MIXXX_INSTALL_DATADIR}" - # QT 5 translations have been separated into several files, and most of the qt_xx.qm files - # contain just shortcuts to load the qtbase, qtmultimedia etc files. - FILES_MATCHING REGEX - "qt_.+\.qm|qtbase_.*\.qm|qtmultimedia_.*\.qm|qtscript_.*\.qm|qtxmlpatterns_.*\.qm" -) -endif() # Font files install( @@ -1545,8 +1596,8 @@ if(KEYFINDER) set(KeyFinder_LIBRARY "lib/${CMAKE_STATIC_LIBRARY_PREFIX}keyfinder${CMAKE_STATIC_LIBRARY_SUFFIX}") file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/download") ExternalProject_Add(libKeyFinder - URL "https://github.com/ibsh/libKeyFinder/archive/v2.2.2.zip" - URL_HASH SHA256=f04ff63c9710d969e79b71bde18abd720e886f537951a1045cc50cb497a72492 + URL "https://github.com/mixxxdj/libKeyFinder/archive/v2.2.3.zip" + URL_HASH SHA256=56887e7b51834223d4264f4ea9acf16f0b6a0c706c218478afbaf89ad1f9c6ea DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/download/libKeyFinder" INSTALL_DIR "${KeyFinder_INSTALL_DIR}" CMAKE_ARGS @@ -1656,15 +1707,16 @@ target_include_directories(mixxx-lib SYSTEM PUBLIC ${PortMidi_INCLUDE_DIRS}) target_link_libraries(mixxx-lib PUBLIC ${PortMidi_LIBRARIES}) # Protobuf +if(STATIC_DEPS) + set(Protobuf_USE_STATIC_LIBS ON) + mark_as_advanced(Protobuf_USE_STATIC_LIBS) +endif() add_subdirectory(src/proto) target_link_libraries(mixxx-lib PUBLIC mixxx-proto) -if(WIN32 AND NOT STATIC_DEPS) - target_compile_definitions(mixxx-lib PUBLIC PROTOBUF_USE_DLLS) -endif() # Rigtorp SPSC Queue # https://github.com/rigtorp/SPSCQueue -target_include_directories(mixxx-lib PUBLIC lib/rigtorp/SPSCQueue/include) +target_include_directories(mixxx-lib SYSTEM PUBLIC lib/rigtorp/SPSCQueue/include) # Qt find_package(Qt5 @@ -1737,8 +1789,6 @@ elseif(WIN32) # New libraries required by Qt5. dwmapi # qtwindows iphlpapi # qt5network - #libEGL # qt5opengl - #libGLESv2 # qt5opengl mpr # qt5core netapi32 # qt5core userenv # qt5core @@ -1799,6 +1849,32 @@ elseif(WIN32) endif() endif() +# Qt5_DIR is not set until now, so this cannot be moved above with the rest of the install commands +if(WIN32) + install( + # I haven't seen a way to determine where the translations dir is, so I am making + # some assumptions here, and assuming that Qt5_DIR points to Qt-5.14.2/lib/cmake/Qt5 + # which is what my configuration tells me. + DIRECTORY + "${Qt5_DIR}/../../../translations" + DESTINATION + "${MIXXX_INSTALL_DATADIR}" + # QT 5 translations have been separated into several files, and most of the qt_xx.qm files + # contain just shortcuts to load the qtbase, qtmultimedia etc files. + FILES_MATCHING REGEX + "qt_.+\.qm|qtbase_.*\.qm|qtmultimedia_.*\.qm|qtscript_.*\.qm|qtxmlpatterns_.*\.qm" + ) + + # ANGLE DLLs are dynamically linked even when the rest of Qt is built statically + install( + FILES + "${Qt5_DIR}/../../../bin/libEGL.dll" + "${Qt5_DIR}/../../../bin/libGLESv2.dll" + DESTINATION + "${MIXXX_INSTALL_DATADIR}" + ) +endif() + # QtScriptByteArray add_library(QtScriptByteArray STATIC EXCLUDE_FROM_ALL lib/qtscript-bytearray/bytearrayclass.cpp @@ -1806,7 +1882,7 @@ add_library(QtScriptByteArray STATIC EXCLUDE_FROM_ALL ) set_target_properties(QtScriptByteArray PROPERTIES AUTOMOC ON) target_link_libraries(QtScriptByteArray Qt5::Core) -target_include_directories(mixxx-lib PUBLIC lib/qtscript-bytearray) +target_include_directories(mixxx-lib SYSTEM PUBLIC lib/qtscript-bytearray) target_link_libraries(mixxx-lib PUBLIC QtScriptByteArray) # Queen Mary DSP @@ -1850,6 +1926,7 @@ add_library(QueenMaryDsp STATIC EXCLUDE_FROM_ALL # lib/qm-dsp/maths/pca/pca.c # lib/qm-dsp/thread/Thread.cpp ) + target_compile_definitions(QueenMaryDsp PRIVATE kiss_fft_scalar=double) if(UNIX) target_compile_definitions(QueenMaryDsp PRIVATE USE_PTHREADS) @@ -1924,9 +2001,8 @@ else() endif() # TagLib -find_package(Taglib REQUIRED) -target_include_directories(mixxx-lib SYSTEM PUBLIC ${TAGLIB_INCLUDE_DIRS}) -target_link_libraries(mixxx-lib PUBLIC ${TAGLIB_LIBRARIES}) +find_package(TagLib REQUIRED) +target_link_libraries(mixxx-lib PUBLIC TagLib::TagLib) if(WIN32 AND STATIC_DEPS) target_compile_definitions(mixxx-lib PUBLIC TAGLIB_STATIC) endif() @@ -2174,7 +2250,7 @@ if(BROADCAST) # Fall back to internal libraray in the lib tree message(STATUS "Using internal libshout") add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/lib/libshout") - target_include_directories(mixxx-lib PUBLIC lib/libshout/include) + target_include_directories(mixxx-lib SYSTEM PUBLIC lib/libshout/include) target_link_libraries(mixxx-lib PUBLIC shout_mixxx) else() target_link_libraries(mixxx-lib PUBLIC Shout::Shout) @@ -2303,7 +2379,7 @@ if(QTKEYCHAIN) endif() target_compile_definitions(mixxx-lib PUBLIC __QTKEYCHAIN__) target_link_libraries(mixxx-lib PUBLIC ${QTKEYCHAIN_LIBRARIES}) - target_include_directories(mixxx-lib PUBLIC ${QTKEYCHAIN_INCLUDE_DIRS}) + target_include_directories(mixxx-lib SYSTEM PUBLIC ${QTKEYCHAIN_INCLUDE_DIRS}) endif() # USB HID or/and Bulk controller support @@ -2398,7 +2474,7 @@ if(VINYLCONTROL) else() target_sources(mixxx-xwax PRIVATE lib/xwax/timecoder.c lib/xwax/lut.c) endif() - target_include_directories(mixxx-xwax PUBLIC lib/xwax) + target_include_directories(mixxx-xwax SYSTEM PUBLIC lib/xwax) target_link_libraries(mixxx-lib PUBLIC mixxx-xwax) endif() diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index afc0c4d07ef..00000000000 --- a/appveyor.yml +++ /dev/null @@ -1,331 +0,0 @@ ---- -version: '{branch}-{build}' -skip_tags: true -shallow_clone: true -max_jobs: 1 -image: - - Visual Studio 2017 - - Ubuntu2004 - -configuration: - - release-fastbuild - - release -# - debug - -platform: -# Disable x86 builds since we only get one concurrent build on AppVeyor and x86 -# failures will be caught by Jenkins. -# - x86 - - x64 - - -matrix: - exclude: - # Ubuntu doesn't support "release-fastbuild". - - image: Ubuntu2004 - configuration: release-fastbuild - # We only want "release-fastbuild" for Windows since "release" consumes too - # much memory due to link-time code generation / whole-program optimization. - - image: Visual Studio 2017 - configuration: release - -skip_commits: - files: - - doc/ - - .travis.yml - - LICENSE - - README - - README.md - - CHANGELOG - - COPYING - - CODE_OF_CONDUCT.md - -for: - -########## UBUNTU SPECIFIC CONFIGURATION ########## - -- - matrix: - only: - - image: Ubuntu2004 - - clone_folder: /home/appveyor/projects/mixxx - - cache: - - /home/appveyor/.ccache - - install: - - sudo apt update - - sudo apt -y install - ccache - cmake - libavcodec-dev - libavformat-dev - libavutil-dev - libchromaprint-dev - libebur128-dev - libfftw3-dev - libflac-dev - libid3tag0-dev - liblilv-dev - libmad0-dev - libmodplug-dev - libmp3lame-dev - libopus-dev - libopusfile-dev - libportmidi-dev - libprotobuf-dev - libqt5opengl5-dev - libqt5sql5-sqlite - libqt5svg5-dev - libqt5x11extras5-dev - librubberband-dev - libshout3-dev - libsndfile1-dev - libsoundtouch-dev - libsqlite3-dev - libswresample-dev - libtag1-dev - libupower-glib-dev - libusb-1.0-0-dev - libwavpack-dev - portaudio19-dev - protobuf-compiler - qt5-default - qtdeclarative5-dev - qt5keychain-dev - qtscript5-dev - xsltproc - - before_build: - # Limit cache size to 4 GB. - # AppVeyor allows 1 GB cache for the free plan but stores it compressed. - # Compression ratio is ~80%, so we could have ~10 GB uncompressed total cache. - # Split cache in half with Ubuntu ccache and underestimate compression ratio a little to - # avoid going over the limit. - - ccache -M 4G - - build_script: - - export CMAKE_BUILD_PARALLEL_LEVEL="$(nproc)" - - mkdir cmake_build - - cd cmake_build - # TODO: Set -DDEBUG_ASSERTIONS_FATAL=OFF before deploying CI builds as releases!!! - - cmake - -L - -DCMAKE_BUILD_TYPE=Release - -DWARNINGS_FATAL=ON - -DDEBUG_ASSERTIONS_FATAL=ON - -DBATTERY=ON - -DBROADCAST=ON - -DBULK=ON - -DFFMPEG=ON - -DHID=ON - -DLILV=ON - -DLOCALECOMPARE=ON - -DMAD=ON - -DMODPLUG=ON - -DOPUS=ON - -DQTKEYCHAIN=ON - -DVINYLCONTROL=ON - -DWAVPACK=ON - .. - - cmake --build . - - sudo cmake --build . --target install - - test_script: - - export CTEST_OUTPUT_ON_FAILURE=1 - - export QT_QPA_PLATFORM=offscreen - - ctest -T test --no-compress-output --timeout 45 - - cmake --build . --target benchmark - - after_test: - - xsltproc -o ctest-to-junit-results.xml ../cmake/ctest-to-junit.xsl Testing/*/Test.xml - - curl -F 'file=@ctest-to-junit-results.xml' "https://ci.appveyor.com/api/testresults/junit/$APPVEYOR_JOB_ID" - - ccache -s - -########## END UBUNTU SPECIFIC CONFIGURATION ########## - -########## WINDOWS SPECIFIC CONFIGURATION ########## - -- - matrix: - only: - - image: Visual Studio 2017 - fast_finish: false # set this flag to true to immediately finish build once one of the jobs fails. - - init: - - git config --global core.autocrlf input -# Uncomment the following line to show RDP info at beginning of job -# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - - clone_folder: c:\projects\mixxx - - cache: - # The Windows build environment is bigger than the 1 GB cache AppVeyor gives us for free. - #- C:\mixxx-buildserver - - C:\Users\appveyor\clcache - - environment: - ENVIRONMENTS_URL: https://downloads.mixxx.org/builds/buildserver/2.3.x-windows/ - ENVIRONMENTS_PATH: C:\mixxx-buildserver - MSVC_PATH: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community" - PATH: 'C:\Python37-x64;C:\Python37-x64\Scripts;%PATH%' - CODESIGN_CERTIFICATE_PATH: build\certificates\windows_sectigo_codesign_certificate.pfx - CODESIGN_CERTIFICATE_SECURE_FILE_SECRET: - secure: 1xzNVbLop/5/ySSgZxPzyOz5cm8nVMLEIEW4x0XOJjI= - CODESIGN_CERTIFICATE_SECURE_FILE_SALT: - secure: tw+bg3qfia7+WQdBdXtC301Z9Dv7yQ6SwpWcFJav9YC4zwyyGztev6pAbGE93sln4VO0WRCJ+4/KTviBMPXvXQ== - CODESIGN_CERTIFICATE_PASSWORD: - secure: EiAsLAgrsS+N3rr71AAkXPCrxIe2vLvlOvCipnTw6pg= - - install: - - set /P ENVIRONMENT_NAME= com.apple.security.cs.allow-jit + com.apple.security.cs.allow-unsigned-executable-memory + diff --git a/build/travis/deploy.sh b/build/travis/deploy.sh deleted file mode 100755 index 2ed0b36b87b..00000000000 --- a/build/travis/deploy.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# -# Deploy artifacts (e.g. dmg, deb files) built by Travis to downloads.mixxx.org. -# Run within the cmake_build directory. - -set -eu -o pipefail - -USER=mixxx -HOSTNAME=downloads-hostgator.mixxx.org -TRAVIS_DESTDIR=public_html/downloads/builds/travis -SSH_KEY=../build/certificates/downloads-hostgator.mixxx.org.key -SSH="ssh -i ${SSH_KEY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" -DEST_PATH=${TRAVIS_DESTDIR}/${TRAVIS_BRANCH}/ -TMP_PATH=${TRAVIS_DESTDIR}/.tmp/$TRAVIS_BUILD_ID/ - -echo "Deploying to $TMP_PATH, then to $DEST_PATH." - -# Remove permissions for group and other users so that ssh-keygen does not -# complain about the key not being protected. -chmod go-rwx ${SSH_KEY} - -# "Unlock" the key by removing its password. This is easier than messing with ssh-agent. -ssh-keygen -p -P ${DOWNLOADS_HOSTGATOR_DOT_MIXXX_DOT_ORG_KEY_PASSWORD} -N "" -f ${SSH_KEY} - -# Always upload to a temporary path. -shopt -s extglob -rsync -e "${SSH}" --rsync-path="mkdir -p ${TMP_PATH} && rsync" -r --delete-after --quiet ./*.@(deb|dmg) ${USER}@${HOSTNAME}:${TMP_PATH} - -# Move from the temporary path to the final destination. -$SSH ${USER}@${HOSTNAME} "mkdir -p ${DEST_PATH} && mv ${TMP_PATH}/* ${DEST_PATH} && rmdir ${TMP_PATH}" diff --git a/cmake/macos_build_environment b/cmake/macos_build_environment new file mode 100644 index 00000000000..f90fc303fb8 --- /dev/null +++ b/cmake/macos_build_environment @@ -0,0 +1,2 @@ +2.3-55d9a17-sdk10.15-macosminimum10.12-x86_64 +86c56d3aba24ec23923ad906f5a13084b0f784c955812448ecb43821fd907d50 diff --git a/cmake/macos_bundle.plist.in b/cmake/macos_bundle.plist.in index 1f8af6bb1e7..472b7554afd 100644 --- a/cmake/macos_bundle.plist.in +++ b/cmake/macos_bundle.plist.in @@ -36,6 +36,6 @@ public.app-category.music LSMinimumSystemVersion - @MACOS_BUNDLE_MINVERSION@ + @CMAKE_OSX_DEPLOYMENT_TARGET@ diff --git a/cmake/modules/FindTagLib.cmake b/cmake/modules/FindTagLib.cmake new file mode 100644 index 00000000000..36da772b011 --- /dev/null +++ b/cmake/modules/FindTagLib.cmake @@ -0,0 +1,87 @@ +# This file is part of Mixxx, Digital DJ'ing software. +# Copyright (C) 2001-2020 Mixxx Development Team +# Distributed under the GNU General Public Licence (GPL) version 2 or any later +# later version. See the LICENSE file for details. + +#[=======================================================================[.rst: +FindTagLib +----------- + +Finds the TagLib library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module provides the following imported targets, if found: + +``TagLib::TagLib`` + The TagLib library + +Result Variables +^^^^^^^^^^^^^^^^ + +This will define the following variables: + +``TagLib_FOUND`` + True if the system has the TagLib library. +``TagLib_INCLUDE_DIRS`` + Include directories needed to use TagLib. +``TagLib_LIBRARIES`` + Libraries needed to link to TagLib. +``TagLib_DEFINITIONS`` + Compile definitions needed to use TagLib. + +Cache Variables +^^^^^^^^^^^^^^^ + +The following cache variables may also be set: + +``TagLib_INCLUDE_DIR`` + The directory containing ``ebur128.h``. +``TagLib_LIBRARY`` + The path to the TagLib library. + +#]=======================================================================] + +find_package(PkgConfig QUIET) +if(PkgConfig_FOUND) + pkg_check_modules(PC_TagLib QUIET taglib) +endif() + +find_path(TagLib_INCLUDE_DIR + NAMES tag.h + PATHS ${PC_TagLib_INCLUDE_DIRS} + PATH_SUFFIXES taglib + DOC "TagLib include directory") +mark_as_advanced(TagLib_INCLUDE_DIR) + +find_library(TagLib_LIBRARY + NAMES tag + PATHS ${PC_TagLib_LIBRARY_DIRS} + DOC "TagLib library" +) +mark_as_advanced(TagLib_LIBRARY) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + TagLib + DEFAULT_MSG + TagLib_LIBRARY + TagLib_INCLUDE_DIR +) + +if(TagLib_FOUND) + set(TagLib_LIBRARIES "${TagLib_LIBRARY}") + set(TagLib_INCLUDE_DIRS "${TagLib_INCLUDE_DIR}") + set(TagLib_DEFINITIONS ${PC_TagLib_CFLAGS_OTHER}) + + if(NOT TARGET TagLib::TagLib) + add_library(TagLib::TagLib UNKNOWN IMPORTED) + set_target_properties(TagLib::TagLib + PROPERTIES + IMPORTED_LOCATION "${TagLib_LIBRARY}" + INTERFACE_COMPILE_OPTIONS "${PC_TagLib_CFLAGS_OTHER}" + INTERFACE_INCLUDE_DIRECTORIES "${TagLib_INCLUDE_DIR}" + ) + endif() +endif() diff --git a/cmake/modules/FindTaglib.cmake b/cmake/modules/FindTaglib.cmake deleted file mode 100644 index 0ed3b3d39fd..00000000000 --- a/cmake/modules/FindTaglib.cmake +++ /dev/null @@ -1,133 +0,0 @@ -# - Try to find the Taglib library -# Once done this will define -# -# TAGLIB_FOUND - system has the taglib library -# TAGLIB_CFLAGS - the taglib cflags -# TAGLIB_LIBRARIES - The libraries needed to use taglib - -# Copyright (c) 2006, Laurent Montel, -# -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - -if(NOT TAGLIB_MIN_VERSION) - set(TAGLIB_MIN_VERSION "1.7") -endif() - -if(NOT WIN32) - find_program(TAGLIBCONFIG_EXECUTABLE - NAMES taglib-config - PATHS ${BIN_INSTALL_DIR} - ) -endif() - -#reset vars -set(TAGLIB_LIBRARIES) -set(TAGLIB_CFLAGS) - -# if taglib-config has been found -if(TAGLIBCONFIG_EXECUTABLE) - - exec_program(${TAGLIBCONFIG_EXECUTABLE} ARGS --version RETURN_VALUE _return_VALUE OUTPUT_VARIABLE TAGLIB_VERSION) - - if(TAGLIB_VERSION VERSION_LESS "${TAGLIB_MIN_VERSION}") - message(STATUS "TagLib version too old: version searched :${TAGLIB_MIN_VERSION}, found ${TAGLIB_VERSION}") - set(TAGLIB_FOUND FALSE) - else() - - exec_program(${TAGLIBCONFIG_EXECUTABLE} ARGS --libs RETURN_VALUE _return_VALUE OUTPUT_VARIABLE TAGLIB_LIBRARIES) - - exec_program(${TAGLIBCONFIG_EXECUTABLE} ARGS --cflags RETURN_VALUE _return_VALUE OUTPUT_VARIABLE TAGLIB_CFLAGS) - - if(TAGLIB_LIBRARIES AND TAGLIB_CFLAGS) - set(TAGLIB_FOUND TRUE) - endif() - - string(REGEX REPLACE " *-I" ";" TAGLIB_INCLUDE_DIRS "${TAGLIB_CFLAGS}") - string(SUBSTRING ${TAGLIB_INCLUDE_DIRS} 0 -1 TAGLIB_INCLUDE_DIRS) #we remove the initial ; -endif() - -mark_as_advanced(TAGLIB_CFLAGS TAGLIB_LIBRARIES TAGLIB_INCLUDES) - -else() - - find_path(TAGLIB_INCLUDE_DIRS - NAMES tag.h - PATH_SUFFIXES taglib - PATHS ${INCLUDE_INSTALL_DIR} - ) - - if(NOT WIN32) - # on non-win32 we don't need to take care about WIN32_DEBUG_POSTFIX - find_library(TAGLIB_LIBRARIES tag PATHS ${LIB_INSTALL_DIR}) - - else() - - # 1. get all possible libnames - set(args PATHS ${LIB_INSTALL_DIR}) - set(newargs "") - set(libnames_release "") - set(libnames_debug "") - - list(LENGTH args listCount) - - # just one name - list(APPEND libnames_release "tag") - list(APPEND libnames_debug "tagd") - - set(newargs ${args}) - - # search the release lib - find_library(TAGLIB_LIBRARIES_RELEASE - NAMES ${libnames_release} - ${newargs} - ) - - # search the debug lib - find_library(TAGLIB_LIBRARIES_DEBUG - NAMES ${libnames_debug} - ${newargs} - ) - - if(TAGLIB_LIBRARIES_RELEASE AND TAGLIB_LIBRARIES_DEBUG) - - # both libs found - set(TAGLIB_LIBRARIES optimized ${TAGLIB_LIBRARIES_RELEASE} - debug ${TAGLIB_LIBRARIES_DEBUG} - ) - - else() - - if(TAGLIB_LIBRARIES_RELEASE) - # only release found - set(TAGLIB_LIBRARIES ${TAGLIB_LIBRARIES_RELEASE}) - - else() - # only debug (or nothing) found - set(TAGLIB_LIBRARIES ${TAGLIB_LIBRARIES_DEBUG}) - - endif() - - endif() - - mark_as_advanced(TAGLIB_LIBRARIES_RELEASE) - mark_as_advanced(TAGLIB_LIBRARIES_DEBUG) - - endif() - - include(FindPackageMessage) - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(Taglib DEFAULT_MSG TAGLIB_LIBRARIES TAGLIB_INCLUDE_DIRS) - -endif() - - -if(TAGLIB_FOUND) - if(NOT Taglib_FIND_QUIETLY AND TAGLIBCONFIG_EXECUTABLE) - message(STATUS "Taglib found: ${TAGLIB_LIBRARIES}") - endif() -else() - if(Taglib_FIND_REQUIRED) - message(FATAL_ERROR "Could not find Taglib") - endif() -endif() diff --git a/cmake/run-mixxx.sh.in b/cmake/run-mixxx.sh.in deleted file mode 100644 index 4db8d96be5b..00000000000 --- a/cmake/run-mixxx.sh.in +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -QT_QPA_PLATFORM_PLUGIN_PATH="@QT_PLUGIN_DIR@" "@CMAKE_CURRENT_BINARY_DIR@/mixxx" $@ diff --git a/build/windows/golden_environment b/cmake/windows_build_environment_name similarity index 100% rename from build/windows/golden_environment rename to cmake/windows_build_environment_name diff --git a/res/controllers/Denon-MC7000-scripts.js b/res/controllers/Denon-MC7000-scripts.js index a8afcd83616..fea38f8b2e4 100644 --- a/res/controllers/Denon-MC7000-scripts.js +++ b/res/controllers/Denon-MC7000-scripts.js @@ -23,7 +23,7 @@ * the MC7000 internal audio interface is not available out-of-the-box for * older Linux Kernels. You should upgrade your Kernel to minimum versions * LTS: 4.19.105 or 5.4.21, stable branch 5.5.5 or current 5.6 (2020-Feb-19). - * Newer Kernels will surely also provide native audio support for this controller. + * Newer Kernels will provide native audio support for this controller. **/ var MC7000 = {}; @@ -37,11 +37,12 @@ var MC7000 = {}; // can be true or false (recommended: false) MC7000.needleSearchPlay = false; -// Possible pitchfader rateranges given in percent. -// can be cycled through be the RANGE buttons. +// Possible pitchfader rate ranges given in percent. +// can be cycled through by the RANGE buttons. MC7000.rateRanges = [ 4/100, // default: 4/100 6/100, // default: 6/100 + 8/100, // default: 8/100 10/100, // default: 10/100 16/100, // default: 16/100 24/100, // default: 24/100 @@ -67,8 +68,8 @@ MC7000.scratchParams = { // Sensitivity of the jog wheel (also depends on audio latency) MC7000.jogParams = { - // Lower values for less, higher values for more sensitive - jogSensitivity: 30, // default: 30 + // Sensitivity factor (0.5 for half, 2 for double sensitivity) + jogSensitivity: 1, // default: 1 // this will limit the parameter of "jog" (keep between 0.5 and 3) maxJogValue: 3 // default: 3 }; @@ -98,6 +99,9 @@ MC7000.currentRateRangeIndex = [0, 0, 0, 0]; // initialize the "factor" function for Spinback MC7000.factor = []; +//Set Shift button state to false for default +MC7000.shift = [false, false, false, false]; + // initialize the PAD Mode to Hot Cue and all others off when starting MC7000.PADModeCue = [true, true, true, true]; MC7000.PADModeCueLoop = [false, false, false, false]; @@ -141,17 +145,12 @@ MC7000.padColor = { /* DECK INITIALIZATION */ MC7000.init = function() { - // set default Master Volume to 85% to give a little head room for mixing - // engine.setValue("[Master]", "gain", 0.85); - - // The SysEx message to send to the controller to force the midi controller - // to send the status of every item on the control surface. - var ControllerStatusSysex = [0xF0, 0x00, 0x20, 0x7F, 0x03, 0x01, 0xF7]; + var i; - // After midi controller receive this Outbound Message request SysEx - // Message, midi controller will send the status of every item on the - // control surface. (Mixxx will be initialized with current values) - midi.sendSysexMsg(ControllerStatusSysex, ControllerStatusSysex.length); + // Softtakeover for Pitch Faders + for (i = 1; i <= 4; i++) { + engine.softTakeover("[Channel" + i + "]", "rate", true); + } // VU meters engine.makeConnection("[Channel1]", "VuMeter", MC7000.VuMeter); @@ -176,7 +175,7 @@ MC7000.init = function() { midi.sendShortMsg(0x93, 0x07, MC7000.isVinylMode ? 0x7F: 0x01); // HotCue Mode LEDs - for (var i = 1; i <= 8; i++) { + for (i = 1; i <= 8; i++) { engine.makeConnection("[Channel1]", "hotcue_"+i+"_enabled", MC7000.HotCueLED); engine.makeConnection("[Channel2]", "hotcue_"+i+"_enabled", MC7000.HotCueLED); engine.makeConnection("[Channel3]", "hotcue_"+i+"_enabled", MC7000.HotCueLED); @@ -189,267 +188,268 @@ MC7000.init = function() { engine.makeConnection("[Sampler"+i+"]", "play", MC7000.SamplerLED); } - // Sampler Volume Control - MC7000.samplerLevel = function(channel, control, value) { - // check if the Sampler Volume is at Zero and if so hide the sampler bank - if (value > 0x00) { - engine.setValue("[Samplers]", "show_samplers", true); - } else { - engine.setValue("[Samplers]", "show_samplers", false); - } - // get the Sampler Rows opened with its details - engine.setValue("[SamplerRow1]", "expanded", true); - engine.setValue("[SamplerRow2]", "expanded", true); + // Activate Timer for Controller Status SysEx to avoid conflicts with Softtakeover + engine.beginTimer(3000, MC7000.delayedSysEx, true); +}; - //control up to 16 sampler volumes with the one knob on the mixer - for (var i = 1; i <= 16; i++) { - engine.setValue("[Sampler"+i+"]", "pregain", script.absoluteNonLin(value, 0, 1.0, 4.0)); - } - }; +// SysEx message to receive all knob and fader positions +MC7000.delayedSysEx = function() { + var ControllerStatusSysex = [0xF0, 0x00, 0x20, 0x7F, 0x03, 0x01, 0xF7]; + midi.sendSysexMsg(ControllerStatusSysex, ControllerStatusSysex.length); +}; - // Activate Softtakeover for Pitch Faders - for (i = 1; i <= 4; i++) { - engine.softTakeover("[Channel" + i + "]", "rate", true); +// Sampler Volume Control +MC7000.samplerLevel = function(channel, control, value) { + // check if the Sampler Volume is at Zero and if so hide the sampler bank + if (value > 0) { + engine.setValue("[Samplers]", "show_samplers", true); + } else { + engine.setValue("[Samplers]", "show_samplers", false); + } + //control the 8 sampler volumes with the one knob on the mixer + for (var i = 1; i <= 8; i++) { + engine.setValue("[Sampler"+i+"]", "pregain", script.absoluteNonLin(value, 0, 1.0, 4.0)); } }; // PAD Mode Hot Cue MC7000.padModeCue = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages - if (value === 0x7F) { - // set HotCue Mode true - MC7000.PADModeCue[deckNumber] = true; - MC7000.PADModeCueLoop[deckNumber] = false; - MC7000.PADModeFlip[deckNumber] = false; - MC7000.PADModeRoll[deckNumber] = false; - MC7000.PADModeSavedLoop[deckNumber] = false; - MC7000.PADModeSlicer[deckNumber] = false; - MC7000.PADModeSlicerLoop[deckNumber] = false; - MC7000.PADModeSampler[deckNumber] = false; - MC7000.PADModeVelSamp[deckNumber] = false; - MC7000.PADModePitch[deckNumber] = false; } + MC7000.PADModeCue[deckNumber] = true; + MC7000.PADModeCueLoop[deckNumber] = false; + MC7000.PADModeFlip[deckNumber] = false; + MC7000.PADModeRoll[deckNumber] = false; + MC7000.PADModeSavedLoop[deckNumber] = false; + MC7000.PADModeSlicer[deckNumber] = false; + MC7000.PADModeSlicerLoop[deckNumber] = false; + MC7000.PADModeSampler[deckNumber] = false; + MC7000.PADModeVelSamp[deckNumber] = false; + MC7000.PADModePitch[deckNumber] = false; + // change PAD color when switching to Hot Cue Mode for (var i = 1; i <= 8; i++) { if (engine.getValue(group, "hotcue_" + i + "_enabled", true)) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.hotcueon); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.hotcueon); } else { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.hotcueoff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.hotcueoff); } } }; + // PAD Mode Cue Loop MC7000.padModeCueLoop = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages - if (value === 0x7F) { - MC7000.PADModeCue[deckNumber] = false; - MC7000.PADModeCueLoop[deckNumber] = true; - MC7000.PADModeFlip[deckNumber] = false; - MC7000.PADModeRoll[deckNumber] = false; - MC7000.PADModeSavedLoop[deckNumber] = false; - MC7000.PADModeSlicer[deckNumber] = false; - MC7000.PADModeSlicerLoop[deckNumber] = false; - MC7000.PADModeSampler[deckNumber] = false; - MC7000.PADModeVelSamp[deckNumber] = false; - MC7000.PADModePitch[deckNumber] = false; } + MC7000.PADModeCue[deckNumber] = false; + MC7000.PADModeCueLoop[deckNumber] = true; + MC7000.PADModeFlip[deckNumber] = false; + MC7000.PADModeRoll[deckNumber] = false; + MC7000.PADModeSavedLoop[deckNumber] = false; + MC7000.PADModeSlicer[deckNumber] = false; + MC7000.PADModeSlicerLoop[deckNumber] = false; + MC7000.PADModeSampler[deckNumber] = false; + MC7000.PADModeVelSamp[deckNumber] = false; + MC7000.PADModePitch[deckNumber] = false; + + // switch off PAD illumination for (var i = 1; i <= 8; i++) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.alloff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.alloff); } }; + // PAD Mode Flip MC7000.padModeFlip = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages - if (value === 0x7F) { - MC7000.PADModeCue[deckNumber] = false; - MC7000.PADModeCueLoop[deckNumber] = false; - MC7000.PADModeFlip[deckNumber] = true; - MC7000.PADModeRoll[deckNumber] = false; - MC7000.PADModeSavedLoop[deckNumber] = false; - MC7000.PADModeSlicer[deckNumber] = false; - MC7000.PADModeSlicerLoop[deckNumber] = false; - MC7000.PADModeSampler[deckNumber] = false; - MC7000.PADModeVelSamp[deckNumber] = false; - MC7000.PADModePitch[deckNumber] = false; } + MC7000.PADModeCue[deckNumber] = false; + MC7000.PADModeCueLoop[deckNumber] = false; + MC7000.PADModeFlip[deckNumber] = true; + MC7000.PADModeRoll[deckNumber] = false; + MC7000.PADModeSavedLoop[deckNumber] = false; + MC7000.PADModeSlicer[deckNumber] = false; + MC7000.PADModeSlicerLoop[deckNumber] = false; + MC7000.PADModeSampler[deckNumber] = false; + MC7000.PADModeVelSamp[deckNumber] = false; + MC7000.PADModePitch[deckNumber] = false; + + // switch off PAD illumination for (var i = 1; i <= 8; i++) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, - MC7000.padColor.alloff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, MC7000.padColor.alloff); } }; + // PAD Mode Roll MC7000.padModeRoll = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages - if (value === 0x7F) { - MC7000.PADModeCue[deckNumber] = false; - MC7000.PADModeCueLoop[deckNumber] = false; - MC7000.PADModeFlip[deckNumber] = false; - MC7000.PADModeRoll[deckNumber] = true; - MC7000.PADModeSavedLoop[deckNumber] = false; - MC7000.PADModeSlicer[deckNumber] = false; - MC7000.PADModeSlicerLoop[deckNumber] = false; - MC7000.PADModeSampler[deckNumber] = false; - MC7000.PADModeVelSamp[deckNumber] = false; - MC7000.PADModePitch[deckNumber] = false; } + MC7000.PADModeCue[deckNumber] = false; + MC7000.PADModeCueLoop[deckNumber] = false; + MC7000.PADModeFlip[deckNumber] = false; + MC7000.PADModeRoll[deckNumber] = true; + MC7000.PADModeSavedLoop[deckNumber] = false; + MC7000.PADModeSlicer[deckNumber] = false; + MC7000.PADModeSlicerLoop[deckNumber] = false; + MC7000.PADModeSampler[deckNumber] = false; + MC7000.PADModeVelSamp[deckNumber] = false; + MC7000.PADModePitch[deckNumber] = false; + + // change PAD color when switching to Roll Mode for (var i = 1; i <= 8; i++) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.rolloff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.rolloff); } }; + // PAD Mode Saved Loop MC7000.padModeSavedLoop = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages - if (value === 0x7F) { - MC7000.PADModeCue[deckNumber] = false; - MC7000.PADModeCueLoop[deckNumber] = false; - MC7000.PADModeFlip[deckNumber] = false; - MC7000.PADModeRoll[deckNumber] = false; - MC7000.PADModeSavedLoop[deckNumber] = true; - MC7000.PADModeSlicer[deckNumber] = false; - MC7000.PADModeSlicerLoop[deckNumber] = false; - MC7000.PADModeSampler[deckNumber] = false; - MC7000.PADModeVelSamp[deckNumber] = false; - MC7000.PADModePitch[deckNumber] = false; } + MC7000.PADModeCue[deckNumber] = false; + MC7000.PADModeCueLoop[deckNumber] = false; + MC7000.PADModeFlip[deckNumber] = false; + MC7000.PADModeRoll[deckNumber] = false; + MC7000.PADModeSavedLoop[deckNumber] = true; + MC7000.PADModeSlicer[deckNumber] = false; + MC7000.PADModeSlicerLoop[deckNumber] = false; + MC7000.PADModeSampler[deckNumber] = false; + MC7000.PADModeVelSamp[deckNumber] = false; + MC7000.PADModePitch[deckNumber] = false; + + // switch off PAD illumination for (var i = 1; i <= 8; i++) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.alloff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.alloff); } }; + // PAD Mode Slicer MC7000.padModeSlicer = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages - if (value === 0x7F) { - MC7000.PADModeCue[deckNumber] = false; - MC7000.PADModeCueLoop[deckNumber] = false; - MC7000.PADModeFlip[deckNumber] = false; - MC7000.PADModeRoll[deckNumber] = false; - MC7000.PADModeSavedLoop[deckNumber] = false; - MC7000.PADModeSlicer[deckNumber] = true; - MC7000.PADModeSlicerLoop[deckNumber] = false; - MC7000.PADModeSampler[deckNumber] = false; - MC7000.PADModeVelSamp[deckNumber] = false; - MC7000.PADModePitch[deckNumber] = false; } + MC7000.PADModeCue[deckNumber] = false; + MC7000.PADModeCueLoop[deckNumber] = false; + MC7000.PADModeFlip[deckNumber] = false; + MC7000.PADModeRoll[deckNumber] = false; + MC7000.PADModeSavedLoop[deckNumber] = false; + MC7000.PADModeSlicer[deckNumber] = true; + MC7000.PADModeSlicerLoop[deckNumber] = false; + MC7000.PADModeSampler[deckNumber] = false; + MC7000.PADModeVelSamp[deckNumber] = false; + MC7000.PADModePitch[deckNumber] = false; + + // change PAD color when switching to Slicer Mode for (var i = 1; i <= 8; i++) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.sliceron); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.sliceron); } }; + // PAD Mode Slicer Loop MC7000.padModeSlicerLoop = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages - if (value === 0x7F) { - MC7000.PADModeCue[deckNumber] = false; - MC7000.PADModeCueLoop[deckNumber] = false; - MC7000.PADModeFlip[deckNumber] = false; - MC7000.PADModeRoll[deckNumber] = false; - MC7000.PADModeSavedLoop[deckNumber] = false; - MC7000.PADModeSlicer[deckNumber] = false; - MC7000.PADModeSlicerLoop[deckNumber] = true; - MC7000.PADModeSampler[deckNumber] = false; - MC7000.PADModeVelSamp[deckNumber] = false; - MC7000.PADModePitch[deckNumber] = false; } + MC7000.PADModeCue[deckNumber] = false; + MC7000.PADModeCueLoop[deckNumber] = false; + MC7000.PADModeFlip[deckNumber] = false; + MC7000.PADModeRoll[deckNumber] = false; + MC7000.PADModeSavedLoop[deckNumber] = false; + MC7000.PADModeSlicer[deckNumber] = false; + MC7000.PADModeSlicerLoop[deckNumber] = true; + MC7000.PADModeSampler[deckNumber] = false; + MC7000.PADModeVelSamp[deckNumber] = false; + MC7000.PADModePitch[deckNumber] = false; + + // switch off PAD illumination for (var i = 1; i <= 8; i++) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.alloff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.alloff); } }; + // PAD Mode Sampler MC7000.padModeSampler = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages - if (value === 0x7F) { - MC7000.PADModeCue[deckNumber] = false; - MC7000.PADModeCueLoop[deckNumber] = false; - MC7000.PADModeFlip[deckNumber] = false; - MC7000.PADModeRoll[deckNumber] = false; - MC7000.PADModeSavedLoop[deckNumber] = false; - MC7000.PADModeSlicer[deckNumber] = false; - MC7000.PADModeSlicerLoop[deckNumber] = false; - MC7000.PADModeSampler[deckNumber] = true; - MC7000.PADModeVelSamp[deckNumber] = false; - MC7000.PADModePitch[deckNumber] = false; } + MC7000.PADModeCue[deckNumber] = false; + MC7000.PADModeCueLoop[deckNumber] = false; + MC7000.PADModeFlip[deckNumber] = false; + MC7000.PADModeRoll[deckNumber] = false; + MC7000.PADModeSavedLoop[deckNumber] = false; + MC7000.PADModeSlicer[deckNumber] = false; + MC7000.PADModeSlicerLoop[deckNumber] = false; + MC7000.PADModeSampler[deckNumber] = true; + MC7000.PADModeVelSamp[deckNumber] = false; + MC7000.PADModePitch[deckNumber] = false; + // change PAD color when switching to Sampler Mode for (var i = 1; i <= 8; i++) { if (engine.getValue("[Sampler" + i + "]", "play")) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.samplerplay); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.samplerplay); } else if (engine.getValue("[Sampler" + i + "]", "track_loaded") === 0) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.sampleroff); - } else if (engine.getValue("[Sampler" + i + "]", "track_loaded") === 1 && - engine.getValue("[Sampler" + i + "]", "play") === 0) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.samplerloaded); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.sampleroff); + } else if (engine.getValue("[Sampler" + i + "]", "track_loaded") === 1 && engine.getValue("[Sampler" + i + "]", "play") === 0) { + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.samplerloaded); } } }; + // PAD Mode Velocity Sampler MC7000.padModeVelSamp = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages - if (value === 0x7F) { - MC7000.PADModeCue[deckNumber] = false; - MC7000.PADModeCueLoop[deckNumber] = false; - MC7000.PADModeFlip[deckNumber] = false; - MC7000.PADModeRoll[deckNumber] = false; - MC7000.PADModeSavedLoop[deckNumber] = false; - MC7000.PADModeSlicer[deckNumber] = false; - MC7000.PADModeSlicerLoop[deckNumber] = false; - MC7000.PADModeSampler[deckNumber] = false; - MC7000.PADModeVelSamp[deckNumber] = true; - MC7000.PADModePitch[deckNumber] = false; } + MC7000.PADModeCue[deckNumber] = false; + MC7000.PADModeCueLoop[deckNumber] = false; + MC7000.PADModeFlip[deckNumber] = false; + MC7000.PADModeRoll[deckNumber] = false; + MC7000.PADModeSavedLoop[deckNumber] = false; + MC7000.PADModeSlicer[deckNumber] = false; + MC7000.PADModeSlicerLoop[deckNumber] = false; + MC7000.PADModeSampler[deckNumber] = false; + MC7000.PADModeVelSamp[deckNumber] = true; + MC7000.PADModePitch[deckNumber] = false; + + // switch off PAD illumination for (var i = 1; i <= 8; i++) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.alloff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.alloff); } }; + // PAD Mode Pitch MC7000.padModePitch = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages - if (value === 0x7F) { - MC7000.PADModeCue[deckNumber] = false; - MC7000.PADModeCueLoop[deckNumber] = false; - MC7000.PADModeFlip[deckNumber] = false; - MC7000.PADModeRoll[deckNumber] = false; - MC7000.PADModeSavedLoop[deckNumber] = false; - MC7000.PADModeSlicer[deckNumber] = true; - MC7000.PADModeSlicerLoop[deckNumber] = false; - MC7000.PADModeSampler[deckNumber] = false; - MC7000.PADModeVelSamp[deckNumber] = false; - MC7000.PADModePitch[deckNumber] = true; } + MC7000.PADModeCue[deckNumber] = false; + MC7000.PADModeCueLoop[deckNumber] = false; + MC7000.PADModeFlip[deckNumber] = false; + MC7000.PADModeRoll[deckNumber] = false; + MC7000.PADModeSavedLoop[deckNumber] = false; + MC7000.PADModeSlicer[deckNumber] = true; + MC7000.PADModeSlicerLoop[deckNumber] = false; + MC7000.PADModeSampler[deckNumber] = false; + MC7000.PADModeVelSamp[deckNumber] = false; + MC7000.PADModePitch[deckNumber] = true; + + // switch off PAD illumination for (var i = 1; i <= 8; i++) { - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, - MC7000.padColor.alloff); - midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, - MC7000.padColor.alloff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i - 1, MC7000.padColor.alloff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, MC7000.padColor.alloff); } }; @@ -458,8 +458,7 @@ MC7000.PadButtons = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); // activate and clear Hot Cues - if (MC7000.PADModeCue[deckNumber] && - engine.getValue(group, "track_loaded") === 1) { + if (MC7000.PADModeCue[deckNumber] && engine.getValue(group, "track_loaded") === 1) { for (var i = 1; i <= 8; i++) { if (control === 0x14 + i - 1 && value >= 0x01) { engine.setValue(group, "hotcue_" + i + "_activate", true); @@ -468,8 +467,7 @@ MC7000.PadButtons = function(channel, control, value, status, group) { } if (control === 0x1C + i - 1 && value >= 0x01) { engine.setValue(group, "hotcue_" + i + "_clear", true); - midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, - MC7000.padColor.hotcueoff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, MC7000.padColor.hotcueoff); } } } else if (MC7000.PADModeCueLoop[deckNumber]) { @@ -481,15 +479,11 @@ MC7000.PadButtons = function(channel, control, value, status, group) { // check for actual beatloop_size and apply back after a PAD Roll i = control - 0x14; if (control === 0x14 + i && value > 0x00) { - engine.setValue( - group, "beatlooproll_" + MC7000.beatLoopRoll[i] + "_activate", - true); - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i, - MC7000.padColor.rollon); + engine.setValue(group, "beatlooproll_" + MC7000.beatLoopRoll[i] + "_activate", true); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i, MC7000.padColor.rollon); } else if (control === 0x14 + i && value === 0x00) { engine.setValue(group, "beatlooproll_activate", false); - midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i, - MC7000.padColor.rolloff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x14 + i, MC7000.padColor.rolloff); } } else if (MC7000.PADModeSavedLoop[deckNumber]) { return; @@ -498,16 +492,13 @@ MC7000.PadButtons = function(channel, control, value, status, group) { var beats = 1 << (control % 4); if (control > 0x17) { engine.setValue(group, "beatjump_" + beats + "_backward", value); - midi.sendShortMsg(0x94 + deckNumber - 1, control, - MC7000.padColor.slicerJumpBack); + midi.sendShortMsg(0x94 + deckNumber - 1, control, MC7000.padColor.slicerJumpBack); } else { engine.setValue(group, "beatjump_" + beats + "_forward", value); - midi.sendShortMsg(0x94 + deckNumber - 1, control, - MC7000.padColor.slicerJumpFwd); + midi.sendShortMsg(0x94 + deckNumber - 1, control, MC7000.padColor.slicerJumpFwd); } } else { - midi.sendShortMsg(0x94 + deckNumber - 1, control, - MC7000.padColor.sliceron); + midi.sendShortMsg(0x94 + deckNumber - 1, control, MC7000.padColor.sliceron); } } else if (MC7000.PADModeSlicerLoop[deckNumber]) { return; @@ -516,19 +507,16 @@ MC7000.PadButtons = function(channel, control, value, status, group) { if (control === 0x14 + i - 1 && value >= 0x01) { if (engine.getValue("[Sampler" + i + "]", "track_loaded") === 0) { engine.setValue("[Sampler" + i + "]", "LoadSelectedTrack", 1); - } else if (engine.getValue("[Sampler" + i + "]", "track_loaded") === - 1) { + } else if (engine.getValue("[Sampler" + i + "]", "track_loaded") === 1) { engine.setValue("[Sampler" + i + "]", "cue_gotoandplay", 1); } } else if (control === 0x1C + i - 1 && value >= 0x01) { if (engine.getValue("[Sampler" + i + "]", "play") === 1) { engine.setValue("[Sampler" + i + "]", "cue_gotoandstop", 1); - midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, - MC7000.padColor.samplerloaded); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, MC7000.padColor.samplerloaded); } else { engine.setValue("[Sampler" + i + "]", "eject", 1); - midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, - MC7000.padColor.sampleroff); + midi.sendShortMsg(0x94 + deckNumber - 1, 0x1C + i - 1, MC7000.padColor.sampleroff); engine.setValue("[Sampler" + i + "]", "eject", 0); } } @@ -540,23 +528,64 @@ MC7000.PadButtons = function(channel, control, value, status, group) { } }; +// Toggle Shift Button +MC7000.shiftButton = function(channel, control, value, status, group) { + var deckNumber = script.deckFromGroup(group); + MC7000.shift[deckNumber - 1] = ! MC7000.shift[deckNumber - 1]; + midi.sendShortMsg(0x90 + deckNumber - 1, 0x32, + MC7000.shift[deckNumber - 1] ? 0x7F : 0x01); +}; + // Toggle Vinyl Mode MC7000.vinylModeToggle = function(channel, control, value, status, group) { - if (value === 0x00) + if (value === 0x00) { return; // don't respond to note off messages + } + var deckNumber = script.deckFromGroup(group); + MC7000.isVinylMode[deckNumber - 1] = !MC7000.isVinylMode[deckNumber - 1]; + midi.sendShortMsg(0x90 + deckNumber - 1, 0x07, + MC7000.isVinylMode[deckNumber - 1] ? 0x7F : 0x01); +}; + +// Use select button to load and eject track from deck +MC7000.loadLongPress = false; +MC7000.loadTimer = 0; + +MC7000.loadAssertLongPress = function() { + MC7000.loadLongPress = true; + MC7000.loadTimer = 0; +}; + +MC7000.loadDown = function() { + MC7000.loadLongPress = false; + MC7000.loadTimer = engine.beginTimer(500, MC7000.loadAssertLongPress, true); +}; +MC7000.loadUp = function(group) { + if (MC7000.loadTimer !== 0) { + engine.stopTimer(MC7000.loadTimer); + MC7000.loadTimer = 0; + } + if (MC7000.loadLongPress) { + script.triggerControl(group, "eject", 100); + } else { + script.triggerControl(group, "LoadSelectedTrack", 100); + } +}; + +MC7000.loadButton = function(channel, control, value, status, group) { + //LOAD hold <500ms: load track, >500ms: eject if (value === 0x7F) { - var deckNumber = script.deckFromGroup(group); - MC7000.isVinylMode[deckNumber] = !MC7000.isVinylMode[deckNumber]; - midi.sendShortMsg(0x90 + channel, 0x07, - MC7000.isVinylMode[deckNumber] ? 0x7F : 0x01); + MC7000.loadDown(); + } else { + MC7000.loadUp(group); } }; // The button that enables/disables scratching MC7000.wheelTouch = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - if (MC7000.isVinylMode[deckNumber]) { + if (MC7000.isVinylMode[deckNumber - 1]) { if (value === 0x7F) { engine.scratchEnable(deckNumber, MC7000.jogWheelTicksPerRevolution, MC7000.scratchParams.recordSpeed, @@ -577,14 +606,16 @@ MC7000.wheelTurn = function(channel, control, value, status, group) { // Scratch! engine.scratchTick(deckNumber, numTicks); } else { - // Pitch bend - var jogDelta = numTicks / MC7000.jogWheelTicksPerRevolution * - MC7000.jogParams.jogSensitivity; - var jogAbsolute = jogDelta + engine.getValue(group, "jog"); - engine.setValue( - group, "jog", - Math.max(-MC7000.jogParams.maxJogValue, - Math.min(MC7000.jogParams.maxJogValue, jogAbsolute))); + if (MC7000.shift[deckNumber - 1]) { + // While Shift Button pressed -> Search through track + var jogSearch = 5000 * numTicks / MC7000.jogWheelTicksPerRevolution * MC7000.jogParams.jogSensitivity; + engine.setValue(group, "jog", jogSearch); + } else { + // While Shift Button released -> Pitch Bend + var jogDelta = numTicks / MC7000.jogWheelTicksPerRevolution * MC7000.jogParams.jogSensitivity * 30; + var jogAbsolute = jogDelta + engine.getValue(group, "jog"); + engine.setValue(group, "jog", Math.max(-MC7000.jogParams.maxJogValue, Math.min(MC7000.jogParams.maxJogValue, jogAbsolute))); + } } }; @@ -592,8 +623,7 @@ MC7000.wheelTurn = function(channel, control, value, status, group) { MC7000.needleSearchTouch = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); if (engine.getValue(group, "play")) { - MC7000.needleSearchTouched[deckNumber] = - MC7000.needleSearchPlay && (!!value); + MC7000.needleSearchTouched[deckNumber] = MC7000.needleSearchPlay && (!!value); } else { MC7000.needleSearchTouched[deckNumber] = !!value; } @@ -616,10 +646,8 @@ MC7000.needleSearchStripPosition = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); if (MC7000.needleSearchTouched[deckNumber]) { - var fullValue = (MC7000.needleDropMSB << 7) + - value; // move MSB 7 binary gigits to the left and add LSB - var position = (fullValue / 0x3FFF); // divide by all possible positions to - // get relative between 0 - 1 + var fullValue = (MC7000.needleDropMSB << 7) + value; // move MSB 7 binary gigits to the left and add LSB + var position = (fullValue / 0x3FFF); // divide by all possible positions to get relative between 0 - 1 engine.setParameter(group, "playposition", position); } }; @@ -632,46 +660,69 @@ MC7000.pitchFaderMSB = function(channel, control, value) { // Pitch Fader Position (MSB + LSB) MC7000.pitchFaderPosition = function(channel, control, value, status, group) { var fullValue = (MC7000.pitchMSB << 7) + value; - var position = - 1 - (fullValue / 0x3FFF); // 1 - () to turn around the direction + var position = 1 - (fullValue / 0x3FFF); // 1 - () to turn around the direction engine.setParameter(group, "rate", position); }; // Next Rate range toggle MC7000.nextRateRange = function(midichan, control, value, status, group) { - if (value === 0) + if (value === 0) { return; // don't respond to note off messages + } var deckNumber = script.deckFromGroup(group); // increment currentRateRangeIndex and check for overflow if (++MC7000.currentRateRangeIndex[deckNumber - 1] === MC7000.rateRanges.length) { MC7000.currentRateRangeIndex[deckNumber - 1] = 0; } - engine.setValue( - group, "rateRange", - MC7000.rateRanges[MC7000.currentRateRangeIndex[deckNumber - 1]]); + engine.setValue(group, "rateRange", MC7000.rateRanges[MC7000.currentRateRangeIndex[deckNumber - 1]]); }; // Previous Rate range toggle MC7000.prevRateRange = function(midichan, control, value, status, group) { - if (value === 0) + if (value === 0) { return; // don't respond to note off messages + } var deckNumber = script.deckFromGroup(group); // decrement currentRateRangeIndex and check for underflow if (--MC7000.currentRateRangeIndex[deckNumber - 1] < 0) { MC7000.currentRateRangeIndex[deckNumber - 1] = MC7000.rateRanges.length - 1; } - engine.setValue( - group, "rateRange", - MC7000.rateRanges[MC7000.currentRateRangeIndex[deckNumber - 1]]); + engine.setValue(group, "rateRange", MC7000.rateRanges[MC7000.currentRateRangeIndex[deckNumber - 1]]); }; -// Key Select +// Key & Waveform zoom Select MC7000.keySelect = function(midichan, control, value, status, group) { - if (value === 0x01) { - engine.setValue(group, "pitch_up", true); - } else if (value === 0x7F) { - engine.setValue(group, "pitch_down", true); + var deckNumber = script.deckFromGroup(group); + // While Shift Button is pressed: Waveform Zoom + if (MC7000.shift[deckNumber - 1]) { + if (value === 0x7F) { + script.triggerControl(group, "waveform_zoom_up", 100); + } else { + script.triggerControl(group, "waveform_zoom_down", 100); + } + // While Shift Button is released: Key Select + } else { + if (value === 0x7F) { + script.triggerControl(group, "pitch_down", 100); + } else { + script.triggerControl(group, "pitch_up", 100); + } + } +}; + +// Key & Waveform zoom Reset +MC7000.keyReset = function(channel, control, value, status, group) { + var deckNumber = script.deckFromGroup(group); + if (value === 0x00) { + return; + } + // While Shift Button is pressed: Waveform Zoom Reset + if (MC7000.shift[deckNumber - 1]) { + script.triggerControl(group, "waveform_zoom_set_default", 100); + // While Shift Button is released: Key Reset + } else { + script.triggerControl(group, "reset_key", 100); } }; @@ -696,33 +747,53 @@ MC7000.stopTime = function(channel, control, value, status, group) { }; // Use the CENSOR button as Spinback with STOP TIME adjusted length -MC7000.censor = function(channel, control, value, status, group) { +MC7000.reverse = function(channel, control, value, status, group) { var deckNumber = script.deckFromGroup(group); - var deck = - parseInt(group.substring(8, 9)); // work out which deck we are using - engine.brake(deck, value > 0, MC7000.factor[deckNumber], - -15); // start at a rate of -15 and decrease by "factor" + if (value > 0) { + // while the button is pressed spin back + engine.brake(deckNumber, true, MC7000.factor[deckNumber], -15); // start at a rate of -15 and decrease by "factor" + } else { + // when releasing the button the track starts softly again + engine.softStart(deckNumber, true, MC7000.factor[deckNumber]); + } +}; + +// Use of Reverse w/ and w/o Slip mode +MC7000.censor = function(channel, control, value, status, group) { + if (engine.getValue(group, "slip_enabled")) { + // This would be the "normal" CENSOR function" + if (value > 0) { + engine.setValue(group, "reverseroll", 1); + } else { + engine.setValue(group, "reverseroll", 0); + } + } else { + // reverse play while button pressed + if (value > 0) { + engine.setValue(group, "reverse", 1); + } else { + engine.setValue(group, "reverse", 0); + } + } }; -/* SET CROSSFADER CURVE */ +// Set Crossfader Curve MC7000.crossFaderCurve = function(control, value) { script.crossfaderCurve(value); }; -/* Set FX wet/dry value */ -MC7000.fxWetDry = function(midichan, control, value, status, group) { +// Set FX wet/dry value +MC7000.fxWetDry = function(channel, control, value, status, group) { var numTicks = (value < 0x64) ? value: (value - 128); var newVal = engine.getValue(group, "mix") + numTicks/64*2; engine.setValue(group, "mix", Math.max(0, Math.min(1, newVal))); - - }; +// Sort the library for Artist, Title, BPM and Key MC7000.sortLibrary = function(channel, control, value) { if (value === 0) { return; } - var sortColumn; switch (control) { case 0x12: // TITLE @@ -744,25 +815,26 @@ MC7000.sortLibrary = function(channel, control, value) { /* LEDs for VuMeter */ // VuMeters only for Channel 1-4 / Master is on Hardware MC7000.VuMeter = function(value, group) { - var VULevelOutValue = engine.getValue(group, "PeakIndicator") ? MC7000.VuMeterLEDPeakValue : value*value*value*value*0x69, - deckNumber = script.deckFromGroup(group); + var deckNumber = script.deckFromGroup(group), + vuLevelOutValue = engine.getValue(group, "PeakIndicator") ? MC7000.VuMeterLEDPeakValue : Math.pow(value, 4) * (MC7000.VuMeterLEDPeakValue - 1); - midi.sendShortMsg(0xB0 + deckNumber - 1, 0x1F, VULevelOutValue); + midi.sendShortMsg(0xB0 + deckNumber - 1, 0x1F, vuLevelOutValue); }; /* LEDs around Jog wheel */ MC7000.JogLed = function(value, group) { - var deckNumber = script.deckFromGroup(group); // do nothing before track starts - if (value < 0) return; - - var trackDuration = engine.getValue(group, "duration"), + if (value === 0) { + return; + } + var deckNumber = script.deckFromGroup(group), + trackDuration = engine.getValue(group, "duration"), position = value * trackDuration / 60 * MC7000.scratchParams.recordSpeed, // LED ring contains 48 segments with each LED activated by the next even number - LEDmidiSignal = 48 * 2, - activeLED = MC7000.isVinylMode[deckNumber] ? Math.round(position * LEDmidiSignal) % LEDmidiSignal : value * LEDmidiSignal; + jogLedOutValue = 48 * 2, + activeLED = MC7000.isVinylMode[deckNumber - 1] ? Math.round(position * jogLedOutValue) % jogLedOutValue : value * jogLedOutValue; - midi.sendShortMsg(0x90 + deckNumber -1, 0x06, activeLED); + midi.sendShortMsg(0x90 + deckNumber - 1, 0x06, activeLED); }; // initial HotCue LED when loading a track with already existing hotcues diff --git a/res/controllers/Denon-MC7000.midi.xml b/res/controllers/Denon-MC7000.midi.xml index 42b470298e1..1f661b723bc 100644 --- a/res/controllers/Denon-MC7000.midi.xml +++ b/res/controllers/Denon-MC7000.midi.xml @@ -3,11 +3,12 @@ Denon MC7000 OsZ - Denon MC7000 mapping. Check your Linux Kernel version to get the Audio Interface working - see WIKI page. - https://www.mixxx.org/forums/ + Denon MC7000 mapping. Check your Linux Kernel version to get the Audio Interface working - see WIKI + https://mixxx.discourse.group/t/denon-mc7000-mapping/18235 + https://github.com/mixxxdj/mixxx/wiki/Denon-MC7000 denon_mc7000 - + @@ -414,6 +415,46 @@ + + [Channel1] + MC7000.shiftButton + Shift Button + 0x90 + 0x32 + + + + + + [Channel2] + MC7000.shiftButton + Shift Button + 0x91 + 0x32 + + + + + + [Channel3] + MC7000.shiftButton + Shift Button + 0x92 + 0x32 + + + + + + [Channel4] + MC7000.shiftButton + Shift Button + 0x93 + 0x32 + + + + [Channel1] @@ -1842,11 +1883,11 @@ - + [Channel1] - beatjump_8_backward - MIDI Learned from 10 messages. + stars_down + 0x94 0x28 @@ -1855,8 +1896,8 @@ [Channel1] - beatjump_8_forward - MIDI Learned from 2 messages. + stars_up + 0x94 0x29 @@ -1864,9 +1905,9 @@ - [Channel1] - beatjump_32_backward - MIDI Learned from 8 messages. + [Library] + track_color_prev + 0x94 0x2A @@ -1874,9 +1915,9 @@ - [Channel1] - beatjump_32_forward - MIDI Learned from 6 messages. + [Library] + track_color_next + 0x94 0x2B @@ -1885,8 +1926,8 @@ [Channel2] - beatjump_8_backward - MIDI Learned from 10 messages. + stars_down + 0x95 0x28 @@ -1895,8 +1936,8 @@ [Channel2] - beatjump_8_forward - MIDI Learned from 2 messages. + stars_up + 0x95 0x29 @@ -1904,9 +1945,9 @@ - [Channel2] - beatjump_32_backward - MIDI Learned from 8 messages. + [Library] + track_color_prev + 0x95 0x2A @@ -1914,9 +1955,9 @@ - [Channel2] - beatjump_32_forward - MIDI Learned from 6 messages. + [Library] + track_color_next + 0x95 0x2B @@ -1925,8 +1966,8 @@ [Channel3] - beatjump_8_backward - MIDI Learned from 10 messages. + stars_down + 0x96 0x28 @@ -1935,8 +1976,8 @@ [Channel3] - beatjump_8_forward - MIDI Learned from 2 messages. + stars_up + 0x96 0x29 @@ -1944,9 +1985,9 @@ - [Channel3] - beatjump_32_backward - MIDI Learned from 8 messages. + [Library] + track_color_prev + 0x96 0x2A @@ -1954,9 +1995,9 @@ - [Channel3] - beatjump_32_forward - MIDI Learned from 6 messages. + [Library] + track_color_next + 0x96 0x2B @@ -1965,8 +2006,8 @@ [Channel4] - beatjump_8_backward - MIDI Learned from 10 messages. + stars_down + 0x97 0x28 @@ -1975,8 +2016,8 @@ [Channel4] - beatjump_8_forward - MIDI Learned from 2 messages. + stars_up + 0x97 0x29 @@ -1984,9 +2025,9 @@ - [Channel4] - beatjump_32_backward - MIDI Learned from 8 messages. + [Library] + track_color_prev + 0x97 0x2A @@ -1994,9 +2035,9 @@ - [Channel4] - beatjump_32_forward - MIDI Learned from 6 messages. + [Library] + track_color_next + 0x97 0x2B @@ -2026,42 +2067,42 @@ [Channel1] - LoadSelectedTrack + MC7000.loadButton MIDI Learned from 2 messages. 0x9F 0x02 - + [Channel2] - LoadSelectedTrack + MC7000.loadButton MIDI Learned from 2 messages. 0x9F 0x03 - + [Channel3] - LoadSelectedTrack + MC7000.loadButton MIDI Learned from 2 messages. 0x9F 0x04 - + [Channel4] - LoadSelectedTrack + MC7000.loadButton MIDI Learned from 2 messages. 0x9F 0x05 - + @@ -2079,7 +2120,7 @@ MoveFocusForward change active panel 0x9F - 0x06 + 0x07 @@ -2089,7 +2130,7 @@ MoveFocusBackward change active panel 0x9F - 0x07 + 0x06 @@ -2593,42 +2634,42 @@ [Channel1] - reverse + MC7000.reverse Reverse Ch1 0x90 0x11 - + [Channel2] - reverse + MC7000.reverse Reverse Ch2 0x91 0x11 - + [Channel3] - reverse + MC7000.reverse Reverse Ch3 0x92 0x11 - + [Channel4] - reverse + MC7000.reverse Reverse Ch4 0x93 0x11 - + @@ -2714,42 +2755,42 @@ [Channel1] - reset_key + MC7000.keyReset Default Key 0x90 0x2A - + [Channel2] - reset_key + MC7000.keyReset Default Key 0x91 0x2A - + [Channel3] - reset_key + MC7000.keyReset Default Key 0x92 0x2A - + [Channel4] - reset_key + MC7000.keyReset Default Key 0x93 0x2A - + diff --git a/res/controllers/midi-components-0.0.js b/res/controllers/midi-components-0.0.js index 792cd737e9b..ff8ed18e02b 100644 --- a/res/controllers/midi-components-0.0.js +++ b/res/controllers/midi-components-0.0.js @@ -748,6 +748,8 @@ this.setCurrentUnit = function(newNumber) { this.currentUnitNumber = newNumber; + this.group = "[EffectRack1_EffectUnit" + newNumber + "]"; + if (allowFocusWhenParametersHidden) { engine.setValue(this.group, "show_focus", 0); } else { @@ -758,8 +760,6 @@ } engine.setValue(this.group, "controller_input_active", 0); - this.group = "[EffectRack1_EffectUnit" + newNumber + "]"; - if (allowFocusWhenParametersHidden) { engine.setValue(this.group, "show_focus", 1); } else { @@ -867,6 +867,7 @@ }; this.EffectUnitKnob.prototype = new Pot({ group: this.group, + number: this.currentUnitNumber, unshift: function() { this.input = function(channel, control, value, _status, _group) { if (this.MSB !== undefined) { diff --git a/res/skins/Deere/deck_controls_row.xml b/res/skins/Deere/deck_controls_row.xml index 99c6899948a..7e076dcdbed 100644 --- a/res/skins/Deere/deck_controls_row.xml +++ b/res/skins/Deere/deck_controls_row.xml @@ -38,7 +38,7 @@ stacked me,me -