diff --git a/docs/CMake API.md b/docs/CMake API.md index 63ec4224b5..d3ae2ee542 100644 --- a/docs/CMake API.md +++ b/docs/CMake API.md @@ -434,6 +434,15 @@ attributes directly to these creation functions, rather than adding them later. are set on a JUCE target. By default, we don't link StoreKit because you might not need it, but if you get linker or include errors that reference StoreKit, just set this argument to `TRUE`. +`NEEDS_WINDOWS_MIDI_SERVICES` +- On Windows, JUCE can use the Windows MIDI Services library to support MIDI 2.0 protocol + communications with hardware and other applications. By default this is not enabled because the + MIDI services require additional packages to be installed in order to function, both at build-time + and at run-time. If you enable this flag but don't have the correct dependencies installed, CMake + will emit an error message during configuration explaining how to get everything set up. This + option will automatically set the JUCE_USE_WINDOWS_MIDI_SERVICES=1 preprocessor definition on the + new target. + `PUSH_NOTIFICATIONS_ENABLED` - Sets app entitlements to allow push notifications. May be either `TRUE` or `FALSE`. Defaults to `FALSE`. diff --git a/extras/Build/CMake/FindCppwinrt.cmake b/extras/Build/CMake/FindCppwinrt.cmake new file mode 100644 index 0000000000..a877c0050a --- /dev/null +++ b/extras/Build/CMake/FindCppwinrt.cmake @@ -0,0 +1,95 @@ +# ============================================================================== +# +# This file is part of the JUCE framework. +# Copyright (c) Raw Material Software Limited +# +# JUCE is an open source framework subject to commercial or open source +# licensing. +# +# By downloading, installing, or using the JUCE framework, or combining the +# JUCE framework with any other source code, object code, content or any other +# copyrightable work, you agree to the terms of the JUCE End User Licence +# Agreement, and all incorporated terms including the JUCE Privacy Policy and +# the JUCE Website Terms of Service, as applicable, which will bind you. If you +# do not agree to the terms of these agreements, we will not license the JUCE +# framework to you, and you must discontinue the installation or download +# process and cease use of the JUCE framework. +# +# JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/ +# JUCE Privacy Policy: https://juce.com/juce-privacy-policy +# JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/ +# +# Or: +# +# You may also use this code under the terms of the AGPLv3: +# https://www.gnu.org/licenses/agpl-3.0.en.html +# +# THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL +# WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF +# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. +# +# ============================================================================== + +include(FindPackageHandleStandardArgs) + +if(JUCE_CPPWINRT_PACKAGE_LOCATION) + set(initial_search_dir ${JUCE_CPPWINRT_PACKAGE_LOCATION}) +else() + set(initial_search_dir "$ENV{USERPROFILE}/AppData/Local/PackageManagement/NuGet/Packages") +endif() + +file(GLOB subdirs "${initial_search_dir}/Microsoft.Windows.CppWinRT.*") + +if(subdirs) + list(GET subdirs 0 search_dir) + list(LENGTH subdirs num_midi2_packages) + + if(num_midi2_packages GREATER 1) + message(WARNING "Multiple Windows MIDI Services packages found in the local NuGet folder. Proceeding with ${search_dir}.") + endif() + + find_path(cppwinrt_root_dir bin/cppwinrt.exe HINTS ${search_dir}) + set(cppwinrt_exe "${cppwinrt_root_dir}/bin/cppwinrt.exe") +elseif(NOT cppwinrt_FIND_QUIETLY) + message(WARNING "Cppwinrt wasn't found in the local packages folder.\n" + "\n" + "In order to use cppwinrt functionality, you must install this package." + "To install NuGet and the CppWinRT package containing the statically linked library, " + "open a PowerShell and issue the following commands" + "\n" + "> Register-PackageSource -provider NuGet -name nugetRepository -location https://www.nuget.org/api/v2\n" + "> Install-Package Microsoft.Windows.CppWinRT -Scope CurrentUser -Source nugetRepository\n" + "\n" + "Alternatively you can use the JUCE_CPPWINRT_PACKAGE_LOCATION CMake variable to specify the directory " + "where this find script is looking for the *Microsoft.Windows.CppWinRT* package directory.") +endif() + +find_package_handle_standard_args(CppWinRT DEFAULT_MSG cppwinrt_exe) + +if(CppWinRT_FOUND) + mark_as_advanced(cppwinrt_root_dir cppwinrt_exe) + + if(NOT TARGET jcppwinrt) + add_executable(jcppwinrt IMPORTED GLOBAL) + set_target_properties(jcppwinrt PROPERTIES IMPORTED_LOCATION "${cppwinrt_exe}") + endif() + + if(NOT TARGET juce_winrt_headers) + get_target_property(cppwinrt_command jcppwinrt IMPORTED_LOCATION) + set(cppwinrt_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/cppwinrt_projection") + + execute_process(COMMAND "${cppwinrt_command}" -input sdk -output "${cppwinrt_INCLUDE_DIRS}" + OUTPUT_VARIABLE command_output + ERROR_VARIABLE command_output + RESULT_VARIABLE result_variable) + + if(result_variable) + message(FATAL_ERROR "Failed to run CppWinRT to generate Windows SDK headers\n${command_output}") + endif() + + add_library(juce_winrt_headers INTERFACE) + add_library(juce::juce_winrt_headers ALIAS juce_winrt_headers) + target_link_libraries(juce_winrt_headers INTERFACE runtimeobject) + target_include_directories(juce_winrt_headers INTERFACE ${cppwinrt_INCLUDE_DIRS}) + endif() +endif() diff --git a/extras/Build/CMake/FindWindowsMIDIServices.cmake b/extras/Build/CMake/FindWindowsMIDIServices.cmake new file mode 100644 index 0000000000..5a9d1e9227 --- /dev/null +++ b/extras/Build/CMake/FindWindowsMIDIServices.cmake @@ -0,0 +1,89 @@ +# ============================================================================== +# +# This file is part of the JUCE framework. +# Copyright (c) Raw Material Software Limited +# +# JUCE is an open source framework subject to commercial or open source +# licensing. +# +# By downloading, installing, or using the JUCE framework, or combining the +# JUCE framework with any other source code, object code, content or any other +# copyrightable work, you agree to the terms of the JUCE End User Licence +# Agreement, and all incorporated terms including the JUCE Privacy Policy and +# the JUCE Website Terms of Service, as applicable, which will bind you. If you +# do not agree to the terms of these agreements, we will not license the JUCE +# framework to you, and you must discontinue the installation or download +# process and cease use of the JUCE framework. +# +# JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/ +# JUCE Privacy Policy: https://juce.com/juce-privacy-policy +# JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/ +# +# Or: +# +# You may also use this code under the terms of the AGPLv3: +# https://www.gnu.org/licenses/agpl-3.0.en.html +# +# THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL +# WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF +# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. +# +# ============================================================================== + +include(FindPackageHandleStandardArgs) + +if(JUCE_WINDOWS_MIDI_SERVICES_PACKAGE_LOCATION) + set(initial_search_dir ${JUCE_WINDOWS_MIDI_SERVICES_PACKAGE_LOCATION}) +else() + set(initial_search_dir "$ENV{USERPROFILE}/AppData/Local/PackageManagement/NuGet/Packages") +endif() + +file(GLOB subdirs "${initial_search_dir}/Microsoft.Windows.Devices.Midi2.*") + +if(subdirs) + list(GET subdirs 0 search_dir) + list(LENGTH subdirs num_midi2_packages) + + if(num_midi2_packages GREATER 1) + message(WARNING "Multiple Windows MIDI Services packages found in the local NuGet folder. Proceeding with ${search_dir}.") + endif() + + find_path(WindowsMIDIServices_root_dir ref/native/Microsoft.Windows.Devices.Midi2.winmd HINTS ${search_dir}) + set(WindowsMIDIServices_winmd "${WindowsMIDIServices_root_dir}/ref/native/Microsoft.Windows.Devices.Midi2.winmd") +elseif(NOT WindowsMIDIServices_FIND_QUIETLY) + message(WARNING + "Windows MIDI Services wasn't found in the the local NuGet folder." + "\n" + "TODO(reuk) At the moment the WMS package isn't in the public nuget repo so it needs to be installed from a local source.") +endif() + +find_package_handle_standard_args(WindowsMIDIServices DEFAULT_MSG WindowsMIDIServices_winmd) + +if(WindowsMIDIServices_FOUND) + set(WindowsMIDIServices_INCLUDE_DIRS ${WindowsMIDIServices_include_dirs}) + + mark_as_advanced(WindowsMIDIServices_include_dirs WindowsMIDIServices_root_dir) + + if(NOT TARGET juce_windows_midi_services) + get_target_property(cppwinrt_command jcppwinrt IMPORTED_LOCATION) + execute_process(COMMAND "${cppwinrt_command}" + -reference sdk + -input "${WindowsMIDIServices_winmd}" + -output "${CMAKE_BINARY_DIR}/winmidi_projection" + OUTPUT_VARIABLE command_output + ERROR_VARIABLE command_output + RESULT_VARIABLE result_variable) + + if(result_variable) + message(FATAL_ERROR "Failed to run cppwinrt to generate Windows MIDI Services headers\n${command_output}") + endif() + + add_library(juce_windows_midi_services INTERFACE) + add_library(juce::juce_windows_midi_services ALIAS juce_windows_midi_services) + target_link_libraries(juce_windows_midi_services INTERFACE juce_winrt_headers) + target_include_directories(juce_windows_midi_services INTERFACE + "${CMAKE_BINARY_DIR}/winmidi_projection" + "${WindowsMIDIServices_root_dir}/build/native/include") + target_compile_definitions(juce_windows_midi_services INTERFACE JUCE_USE_WINDOWS_MIDI_SERVICES=1) + endif() +endif() diff --git a/extras/Build/CMake/JUCEUtils.cmake b/extras/Build/CMake/JUCEUtils.cmake index 28ea187c85..9c09161bcb 100644 --- a/extras/Build/CMake/JUCEUtils.cmake +++ b/extras/Build/CMake/JUCEUtils.cmake @@ -300,6 +300,20 @@ function(_juce_link_optional_libraries target) find_package(WebView2 REQUIRED) target_link_libraries(${target} PRIVATE juce::juce_webview2) endif() + + get_target_property(needs_windows_midi_services ${target} JUCE_NEEDS_WINDOWS_MIDI_SERVICES) + + if(needs_windows_midi_services) + if(NOT ("${JUCE_CMAKE_UTILS_DIR}" IN_LIST CMAKE_MODULE_PATH)) + list(APPEND CMAKE_MODULE_PATH "${JUCE_CMAKE_UTILS_DIR}") + endif() + + find_package(CppWinRT REQUIRED) + target_link_libraries(${target} PRIVATE juce::juce_winrt_headers) + + find_package(WindowsMIDIServices REQUIRED) + target_link_libraries(${target} PRIVATE juce::juce_windows_midi_services) + endif() endif() endfunction() @@ -1999,6 +2013,7 @@ function(_juce_initialise_target target) NEEDS_WEB_BROWSER # Set this true if you want to link webkit on Linux NEEDS_WEBVIEW2 # Set this true if you want to link WebView2 statically on Windows NEEDS_STORE_KIT # Set this true if you want in-app-purchases on Mac + NEEDS_WINDOWS_MIDI_SERVICES # Set this true If you want to support the newest Windows MIDI backend PUSH_NOTIFICATIONS_ENABLED NETWORK_MULTICAST_ENABLED HARDENED_RUNTIME_ENABLED