diff --git a/.github/asiosdk-version.txt b/.github/asiosdk-version.txt new file mode 100644 index 0000000..31c8146 --- /dev/null +++ b/.github/asiosdk-version.txt @@ -0,0 +1,5 @@ +GitHub Actions uses the hash of this file as the cache key for the ASIO SDK. +Update this file when a new version of the ASIO SDK is released to trigger +a new download on GitHub Actions instead of using the old cache. + +asiosdk_2.3.3_2019-06-14.zip diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 68e4b6c..56d3e8f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -12,20 +12,55 @@ jobs: fail-fast: false matrix: include: - - name: Ubuntu + - name: Ubuntu GCC os: ubuntu-latest install_dir: ~/portaudio - - name: Ubuntu mingw64 + dependencies_extras: libjack-dev + cmake_generator: "Unix Makefiles" + cmake_options: + -DOSS=ON + - name: Ubuntu MinGW os: ubuntu-latest install_dir: ~/portaudio + asio_sdk_cache_path: asiosdk.zip dependencies_extras: mingw-w64 - cmake_extras: -DCMAKE_TOOLCHAIN_FILE=i686-w64-mingw32.cmake - - name: Windows + cmake_generator: "Unix Makefiles" + cmake_options: + -DASIO=ON + -DASIO_SDK_ZIP_PATH=asiosdk.zip + -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/i686-w64-mingw32.cmake + - name: Windows MSVC os: windows-latest install_dir: C:\portaudio - - name: macOS + cmake_generator: "Visual Studio 16 2019" + # ASIO_SDK_ZIP_PATH needs to be quoted or CMake will save the download to + # asiosdk instead of asiosdk.zip. + asio_sdk_cache_path: "asiosdk.zip" + cmake_options: + -DASIO=ON + -DASIO_SDK_ZIP_PATH="asiosdk.zip" + - name: Windows MinGW + os: windows-latest + install_dir: C:\portaudio + cmake_generator: "MinGW Makefiles" + # ASIO_SDK_ZIP_PATH needs to be quoted or CMake will save the download to + # asiosdk instead of asiosdk.zip. + asio_sdk_cache_path: "asiosdk.zip" + cmake_options: + -DASIO=ON + -DASIO_SDK_ZIP_PATH="asiosdk.zip" + - name: macOS Clang os: macOS-latest install_dir: ~/portaudio + cmake_generator: "Unix Makefiles" + cmake_options: + -DCMAKE_FRAMEWORK=OFF + - name: macOS Clang framework + os: macOS-latest + install_dir: ~/portaudio + cmake_generator: "Unix Makefiles" + cmake_options: + -DCMAKE_FRAMEWORK=ON runs-on: ${{ matrix.os }} name: ${{ matrix.name }} @@ -34,15 +69,30 @@ jobs: steps: - name: checkout Git repository uses: actions/checkout@v2 - - name: "[Ubuntu] install dependencies" - run: sudo apt-get install libasound2-dev libjack-dev ${{ matrix.dependencies_extras }} + - name: "[Ubuntu] install ALSA and JACK headers" + run: sudo apt-get install libasound2-dev ${{ matrix.dependencies_extras }} if: matrix.os == 'ubuntu-latest' + - name: "[macOS] install JACK from Homebrew" + run: brew install jack + if: matrix.os == 'macOS-latest' + - name: "[Windows MinGW] install MinGW from Chocolatey" + run: choco install mingw + if: startsWith(matrix.os, 'Windows MinGW') + - name: "[Windows/MinGW] set up ASIO SDK cache" + uses: actions/cache@v2 + if: matrix.asio_sdk_cache_path != null + with: + path: ${{ matrix.asio_sdk_cache_path }} + key: ${{ hashFiles('.github/asiosdk-version.txt') }} - name: configure - run: cmake ${{ matrix.cmake_extras }} + run: cmake + -G "${{ matrix.cmake_generator }}" + ${{ matrix.cmake_options }} -DCMAKE_INSTALL_PREFIX=${{ matrix.install_dir }} -DCMAKE_BUILD_TYPE=${{ env.cmake_build_type }} - -DPA_BUILD_TESTS=ON - -DPA_BUILD_EXAMPLES=ON + -DSKELETON=ON + -DBUILD_TESTING=ON + -DBUILD_EXAMPLES=ON -S . -B build - name: build diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c90862..4df23dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,98 +1,15 @@ -# $Id: $ +cmake_minimum_required(VERSION 3.1.0) +project(PortAudio VERSION 19.8) + # -# For a "How-To" please refer to the Portaudio documentation at: -# http://www.portaudio.com/trac/wiki/TutorialDir/Compile/CMake +# General PortAudio stuff # -CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0) +option(BUILD_SHARED_LIBS "Build dynamic library" ON) +option(BUILD_TESTING "Include test projects" OFF) +option(BUILD_EXAMPLES "Include example projects" OFF) -# Check if the user is building PortAudio stand-alone or as part of a larger -# project. If this is part of a larger project (i.e. the CMakeLists.txt has -# been imported by some other CMakeLists.txt), we don't want to trump over -# the top of that project's global settings. -IF(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_LIST_DIR}) - PROJECT(portaudio) - - # CMAKE_CONFIGURATION_TYPES only exists for multi-config generators (like - # Visual Studio or Xcode). For these projects, we won't define - # CMAKE_BUILD_TYPE as it does not make sense. - IF(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - MESSAGE(STATUS "Setting CMAKE_BUILD_TYPE type to 'Debug' as none was specified.") - SET(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) - SET_PROPERTY(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release") - ENDIF() - - SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON) - - IF(WIN32 AND MSVC) - OPTION(PA_DLL_LINK_WITH_STATIC_RUNTIME "Link with static runtime libraries (minimizes runtime dependencies)" ON) - IF(PA_DLL_LINK_WITH_STATIC_RUNTIME) - FOREACH(flag_var - CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - IF(${flag_var} MATCHES "/MD") - STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - ENDIF() - ENDFOREACH() - ENDIF() - ENDIF() -ENDIF() - -SET(PA_VERSION 19) -SET(PA_PKGCONFIG_VERSION ${PA_VERSION}) -SET(PA_SOVERSION "${PA_VERSION}.0") - -# Most of the code from this point onwards is related to populating the -# following variables: -# PA_PUBLIC_INCLUDES - This contains the list of public PortAudio header -# files. These files will be copied into /include paths on Unix'y -# systems when "make install" is invoked. -# PA_PRIVATE_INCLUDES - This contains the list of header files which -# are not part of PortAudio, but are required by the various hostapis. -# It is only used by CMake IDE generators (like Visual Studio) to -# provide quick-links to useful headers. It has no impact on build -# output. -# PA_PRIVATE_INCLUDE_PATHS - This contains the list of include paths which -# will be passed to the compiler while PortAudio is being built which -# are not required by applications using the PortAudio API. -# PA_PRIVATE_COMPILE_DEFINITIONS - This contains a list of preprocessor -# macro definitions which will be set when compiling PortAudio source -# files. -# PA_SOURCES - This contains the list of source files which will be built -# into the static and shared PortAudio libraries. -# PA_NON_UNICODE_SOURCES - This also contains a list of source files which -# will be build into the static and shared PortAudio libraries. However, -# these sources will not have any unicode compiler definitions added -# to them. This list should only contain external source dependencies. -# PA_EXTRA_SHARED_SOURCES - Contains a list of extra files which will be -# associated only with the shared PortAudio library. This only seems -# relevant for Windows shared libraries which require a list of export -# symbols. -# Where other PA_* variables are set, these are almost always only used to -# preserve the historic SOURCE_GROUP behavior (which again only has an impact -# on IDE-style generators for visual appearance) or store the output of -# find_library() calls. - -SET(PA_COMMON_INCLUDES - src/common/pa_allocation.h - src/common/pa_converters.h - src/common/pa_cpuload.h - src/common/pa_debugprint.h - src/common/pa_dither.h - src/common/pa_endianness.h - src/common/pa_hostapi.h - src/common/pa_memorybarrier.h - src/common/pa_process.h - src/common/pa_ringbuffer.h - src/common/pa_stream.h - src/common/pa_trace.h - src/common/pa_types.h - src/common/pa_util.h -) - -SET(PA_COMMON_SOURCES +add_library(PortAudio src/common/pa_allocation.c src/common/pa_converters.c src/common/pa_cpuload.c @@ -104,396 +21,363 @@ SET(PA_COMMON_SOURCES src/common/pa_stream.c src/common/pa_trace.c ) +target_include_directories(PortAudio PUBLIC + $ + $ +) +if(UNIX) + target_compile_options(PortAudio PRIVATE -fPIC) +endif() -SOURCE_GROUP("common" FILES ${PA_COMMON_INCLUDES} ${PA_COMMON_SOURCES}) +set(PORTAUDIO_PUBLIC_HEADERS include/portaudio.h) -SET(PA_PUBLIC_INCLUDES include/portaudio.h) +find_package(Threads REQUIRED) +target_link_libraries(PortAudio PRIVATE Threads::Threads) -SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake_support) +option(DEBUG_OUTPUT "Enable debug output for Portaudio" OFF) +if(DEBUG_OUTPUT) + target_compile_definitions(PortAudio PRIVATE PA_ENABLE_DEBUG_OUTPUT) +endif() -SET(PA_SKELETON_SOURCES src/hostapi/skeleton/pa_hostapi_skeleton.c) -SOURCE_GROUP("hostapi\\skeleton" ${PA_SKELETON_SOURCES}) -SET(PA_SOURCES ${PA_COMMON_SOURCES} ${PA_SKELETON_SOURCES}) -SET(PA_PRIVATE_INCLUDE_PATHS src/common ${CMAKE_CURRENT_BINARY_DIR}) +include(TestBigEndian) +TEST_BIG_ENDIAN(IS_BIG_ENDIAN) +if(IS_BIG_ENDIAN) + target_compile_definitions(PortAudio PRIVATE PA_BIG_ENDIAN) +else() + target_compile_definitions(PortAudio PRIVATE PA_LITTLE_ENDIAN) +endif() -IF(WIN32) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} _CRT_SECURE_NO_WARNINGS) +if(WIN32 AND MSVC AND BUILD_SHARED_LIBS + # Check if the user is building PortAudio stand-alone or as part of a larger + # project. If this is part of a larger project (i.e. the CMakeLists.txt has + # been imported by some other CMakeLists.txt), we don't want to override + # that project's global settings. + AND "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_LIST_DIR}") + option(DLL_LINK_WITH_STATIC_RUNTIME + "Link with static runtime libraries (minimizes runtime dependencies)" ON) + if(DLL_LINK_WITH_STATIC_RUNTIME) + foreach(flag_var + CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if(${flag_var} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + endif() + endforeach() + endif() +endif() - SET(PA_PLATFORM_SOURCES +# +# Host APIs +# + +option(SKELETON "Use skeleton host API" OFF) +if(SKELETON) + target_sources(PortAudio PRIVATE src/hostapi/skeleton/pa_hostapi_skeleton.c) + target_compile_definitions(PortAudio PRIVATE PA_USE_SKELETON=1) +endif() + +include(CMakeDependentOption) +set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") + +include(GNUInstallDirs) + +# JACK is most commonly used on Linux, but it is cross platform, so allow building it on any OS +# if the FindJACK.cmake module finds POSIX headers. +find_package(JACK) +cmake_dependent_option(JACK "Enable support for JACK Audio Connection Kit" ON JACK_FOUND OFF) +if(JACK) + target_link_libraries(PortAudio PRIVATE JACK::jack) + target_sources(PortAudio PRIVATE src/hostapi/jack/pa_jack.c) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_jack.h) + target_compile_definitions(PortAudio PRIVATE PA_USE_JACK=1) + set(PKGCONFIG_REQUIRES_PRIVATE "${PKGCONFIG_REQUIRES_PRIVATE} jack") + + # needed for PortAudioConfig.cmake so `find_package(PortAudio)` works in downstream projects + install(FILES cmake/modules/FindRegex.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/portaudio/modules") + install(FILES cmake/modules/FindJACK.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/portaudio/modules") +endif() + +if(WIN32) + target_sources(PortAudio PRIVATE src/os/win/pa_win_hostapis.c src/os/win/pa_win_util.c src/os/win/pa_win_waveformat.c - src/os/win/pa_win_wdmks_utils.c - src/os/win/pa_win_coinitialize.c) - SET(PA_PLATFORM_INCLUDES - src/os/win/pa_win_util.h - src/os/win/pa_win_coinitialize.h - src/os/win/pa_win_wdmks_utils.h) + src/os/win/pa_win_coinitialize.c + ) + target_include_directories(PortAudio PRIVATE src/os/win) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_win_waveformat.h) + target_link_libraries(PortAudio PRIVATE winmm) - IF(MSVC) - SET(PA_PLATFORM_SOURCES ${PA_PLATFORM_SOURCES} src/os/win/pa_x86_plain_converters.c) - SET(PA_PLATFORM_INCLUDES ${PA_PLATFORM_INCLUDES} src/os/win/pa_x86_plain_converters.h) - ELSE() - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} _WIN32_WINNT=0x0501 WINVER=0x0501) - SET(DEF_EXCLUDE_X86_PLAIN_CONVERTERS ";") - ENDIF() + if(MSVC) + target_sources(PortAudio PRIVATE src/os/win/pa_x86_plain_converters.c) + else() + target_compile_definitions(PortAudio PRIVATE _WIN32_WINNT=0x0501 WINVER=0x0501) + set(DEF_EXCLUDE_X86_PLAIN_CONVERTERS ";") + endif() - SOURCE_GROUP("os\\win" FILES ${PA_PLATFORM_SOURCES} ${PA_PLATFORM_INCLUDES}) - SET(PA_SOURCES ${PA_SOURCES} ${PA_PLATFORM_SOURCES}) - SET(PA_PRIVATE_INCLUDES ${PA_PRIVATE_INCLUDES} ${PA_PLATFORM_INCLUDES}) - SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} src/os/win) + target_compile_definitions(PortAudio PRIVATE _CRT_SECURE_NO_WARNINGS) - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} winmm) + option(ASIO "Enable support for ASIO" OFF) + if(ASIO) + find_package(ASIO) + # Automatically download the ASIO SDK ZIP if it is not found. The ASIO SDK license + # allows for downloading it from Steinberg and using it without charge, but it is + # not allowed to be redistributed. + # + # The file(ARCHIVE_EXTRACT) command needed to extract the ZIP archive was added in + # CMake 3.18, so do not bother downloading the ZIP archive for older CMake versions. + # Instead, FindASIO.cmake directs the user to manually extract the ZIP file to + # CMAKE_PREFIX_PATH or CMAKE_CURRENT_BINARY_DIR. + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18 AND NOT TARGET ASIO::host) + if(NOT ASIO_SDK_ZIP_PATH) + set(ASIO_SDK_ZIP_PATH "${CMAKE_CURRENT_BINARY_DIR}/asiosdk.zip") + endif() + message(STATUS "Downloading ASIO SDK... ${ASIO_SDK_ZIP_PATH}") + file(DOWNLOAD "https://www.steinberg.net/asiosdk" + "${ASIO_SDK_ZIP_PATH}" + STATUS ASIO_DOWNLOAD_STATUS + SHOW_PROGRESS + ) + if("${ASIO_DOWNLOAD_STATUS}" EQUAL 0) + find_package(ASIO) + else() + list(GET "${ASIO_DOWNLOAD_STATUS}" 1 DOWNLOAD_ERROR) + message(FATAL_ERROR "Error downloading ASIO SDK: ${DOWNLOAD_ERROR} " + "Reconfigure CMake with -DASIO=OFF to build without ASIO. " + "Alternatively, download the ZIP from https://www.steinberg.net/asiosdk " + "and put it in ${CMAKE_PREFIX_PATH} or ${CMAKE_CURRENT_BINARY_DIR}" + ) + endif() + endif() + endif() + if(ASIO AND TARGET ASIO::host) + target_link_libraries(PortAudio PRIVATE ASIO::host) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_asio.h) + target_compile_definitions(PortAudio PRIVATE PA_USE_ASIO=1) + target_sources(PortAudio PRIVATE + src/hostapi/asio/pa_asio.cpp + src/hostapi/asio/iasiothiscallresolver.cpp + ) + else() + set(DEF_EXCLUDE_ASIO_SYMBOLS ";") + endif() - # Try to find ASIO SDK (assumes that portaudio and asiosdk folders are side-by-side, see - # http://www.portaudio.com/trac/wiki/TutorialDir/Compile/WindowsASIOMSVC) - FIND_PACKAGE(ASIOSDK) - IF(ASIOSDK_FOUND) - OPTION(PA_USE_ASIO "Enable support for ASIO" ON) - ELSE() - OPTION(PA_USE_ASIO "Enable support for ASIO" OFF) - ENDIF() - IF(PA_USE_ASIO) - SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${ASIOSDK_ROOT_DIR}/common) - SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${ASIOSDK_ROOT_DIR}/host) - SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${ASIOSDK_ROOT_DIR}/host/pc) - SET(PA_ASIO_SOURCES src/hostapi/asio/pa_asio.cpp src/hostapi/asio/iasiothiscallresolver.cpp) - SET(PA_ASIOSDK_SOURCES ${ASIOSDK_ROOT_DIR}/common/asio.cpp ${ASIOSDK_ROOT_DIR}/host/pc/asiolist.cpp ${ASIOSDK_ROOT_DIR}/host/asiodrivers.cpp) - SOURCE_GROUP("hostapi\\ASIO" FILES ${PA_ASIO_SOURCES}) - SOURCE_GROUP("hostapi\\ASIO\\ASIOSDK" FILES ${PA_ASIOSDK_SOURCES}) - SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_asio.h) - SET(PA_SOURCES ${PA_SOURCES} ${PA_ASIO_SOURCES}) - SET(PA_NON_UNICODE_SOURCES ${PA_NON_UNICODE_SOURCES} ${PA_ASIOSDK_SOURCES}) - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ole32 uuid) - ELSE() - # Set variables for DEF file expansion - SET(DEF_EXCLUDE_ASIO_SYMBOLS ";") - ENDIF() + option(DIRECTSOUND "Enable support for DirectSound" ON) + if(DIRECTSOUND) + target_sources(PortAudio PRIVATE + src/hostapi/dsound/pa_win_ds.c + src/hostapi/dsound/pa_win_ds_dynlink.c + ) + target_include_directories(PortAudio PRIVATE src/hostapi/dsound) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_win_ds.h) + target_compile_definitions(PortAudio PRIVATE PA_USE_DS=1) + target_link_libraries(PortAudio PRIVATE dsound) + if(NOT MINGW) + target_compile_definitions(PortAudio PRIVATE PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE) + endif() + endif() - OPTION(PA_USE_DS "Enable support for DirectSound" ON) - IF(PA_USE_DS) - IF(MINGW) - MESSAGE(STATUS "DirectSound support will be built with DSound provided by MinGW.") - OPTION(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE "Use DirectSound full duplex create" OFF) - ELSE(MINGW) - OPTION(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE "Use DirectSound full duplex create" ON) - ENDIF(MINGW) - MARK_AS_ADVANCED(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE) - IF(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE) - ENDIF() - SET(PA_DS_INCLUDES src/hostapi/dsound/pa_win_ds_dynlink.h) - SET(PA_DS_SOURCES src/hostapi/dsound/pa_win_ds.c src/hostapi/dsound/pa_win_ds_dynlink.c) - SOURCE_GROUP("hostapi\\dsound" FILES ${PA_DS_INCLUDES} ${PA_DS_SOURCES}) - SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_ds.h include/pa_win_waveformat.h) - SET(PA_PRIVATE_INCLUDES ${PA_PRIVATE_INCLUDES} ${PA_DS_INCLUDES}) - SET(PA_SOURCES ${PA_SOURCES} ${PA_DS_SOURCES}) - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} dsound) - ENDIF(PA_USE_DS) + option(WMME "Enable support for WMME" ON) + if(WMME) + target_sources(PortAudio PRIVATE src/hostapi/wmme/pa_win_wmme.c) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_win_wmme.h) + target_compile_definitions(PortAudio PRIVATE PA_USE_WMME=1) + target_link_libraries(PortAudio PRIVATE ole32 uuid) + else() + set(DEF_EXCLUDE_WMME_SYMBOLS ";") + endif() - OPTION(PA_USE_WMME "Enable support for MME" ON) - IF(PA_USE_WMME) - SET(PA_WMME_SOURCES src/hostapi/wmme/pa_win_wmme.c) - SOURCE_GROUP("hostapi\\wmme" FILES ${PA_WMME_SOURCES}) - SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_wmme.h include/pa_win_waveformat.h) - SET(PA_SOURCES ${PA_SOURCES} ${PA_WMME_SOURCES}) - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ole32 uuid) - ENDIF() + option(WASAPI "Enable support for WASAPI" ON) + if(WASAPI) + target_sources(PortAudio PRIVATE src/hostapi/wasapi/pa_win_wasapi.c) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_win_wasapi.h) + target_compile_definitions(PortAudio PRIVATE PA_USE_WASAPI=1) + target_link_libraries(PortAudio PRIVATE ole32 uuid) + else() + set(DEF_EXCLUDE_WASAPI_SYMBOLS ";") + endif() - # MinGW versions below 4.93, especially non MinGW-w64 distributions may - # break in the wasapi build. If an older MinGW version is required, WASAPI- - # support needs to be disabled. - OPTION(PA_USE_WASAPI "Enable support for WASAPI" ON) - IF(PA_USE_WASAPI) - SET(PA_WASAPI_SOURCES src/hostapi/wasapi/pa_win_wasapi.c) - SOURCE_GROUP("hostapi\\wasapi" FILES ${PA_WASAPI_SOURCES}) - SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_wasapi.h include/pa_win_waveformat.h) - SET(PA_SOURCES ${PA_SOURCES} ${PA_WASAPI_SOURCES}) - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ole32 uuid) - ELSE() - SET(DEF_EXCLUDE_WASAPI_SYMBOLS ";") - ENDIF() + option(WDMKS "Enable support for WDMKS" ON) + if(WDMKS) + target_sources(PortAudio PRIVATE + src/os/win/pa_win_wdmks_utils.c + src/hostapi/wdmks/pa_win_wdmks.c + ) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_win_wdmks.h) + target_compile_definitions(PortAudio PRIVATE PA_USE_WDMKS=1) + target_link_libraries(PortAudio PRIVATE setupapi ole32 uuid) + endif() - OPTION(PA_USE_WDMKS "Enable support for WDMKS" ON) - IF(PA_USE_WDMKS) - SET(PA_WDMKS_SOURCES src/hostapi/wdmks/pa_win_wdmks.c) - SOURCE_GROUP("hostapi\\wdmks" FILES ${PA_WDMKS_SOURCES}) - SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_wdmks.h) - SET(PA_SOURCES ${PA_SOURCES} ${PA_WDMKS_SOURCES}) - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} setupapi ole32 uuid) - ENDIF() + option(WDMKS_DEVICE_INFO "Use WDM/KS API for device info" ON) + if(WDMKS_DEVICE_INFO) + target_compile_definitions(PortAudio PRIVATE PAWIN_USE_WDMKS_DEVICE_INFO) + endif() - OPTION(PA_USE_WDMKS_DEVICE_INFO "Use WDM/KS API for device info" ON) - MARK_AS_ADVANCED(PA_USE_WDMKS_DEVICE_INFO) - IF(PA_USE_WDMKS_DEVICE_INFO) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PAWIN_USE_WDMKS_DEVICE_INFO) - ENDIF() + if(BUILD_SHARED_LIBS) + configure_file(cmake/portaudio.def.in "${CMAKE_CURRENT_BINARY_DIR}/portaudio.def" @ONLY) + target_sources(PortAudio PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/portaudio.def") + endif() +elseif(UNIX) + target_sources(PortAudio PRIVATE + src/os/unix/pa_unix_hostapis.c + src/os/unix/pa_unix_util.c + ) + target_include_directories(PortAudio PRIVATE src/os/unix) + target_link_libraries(PortAudio PRIVATE m) + set(PKGCONFIG_LDFLAGS_PRIVATE "${PKGCONFIG_LDFLAGS_PUBLIC} -lm -lpthread") + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -pthread") - SET(GENERATED_MESSAGE "CMake generated file, do NOT edit! Use CMake-GUI to change configuration instead.") - CONFIGURE_FILE(cmake_support/template_portaudio.def ${CMAKE_CURRENT_BINARY_DIR}/portaudio_cmake.def @ONLY) - CONFIGURE_FILE(cmake_support/options_cmake.h.in ${CMAKE_CURRENT_BINARY_DIR}/options_cmake.h @ONLY) - SET(PA_PRIVATE_INCLUDES ${PA_PRIVATE_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}/options_cmake.h) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PORTAUDIO_CMAKE_GENERATED) - SOURCE_GROUP("cmake_generated" FILES ${CMAKE_CURRENT_BINARY_DIR}/portaudio_cmake.def ${CMAKE_CURRENT_BINARY_DIR}/options_cmake.h) + if(APPLE) + set(CMAKE_MACOSX_RPATH 1) + target_sources(PortAudio PRIVATE + src/hostapi/coreaudio/pa_mac_core.c + src/hostapi/coreaudio/pa_mac_core_blocking.c + src/hostapi/coreaudio/pa_mac_core_utilities.c + ) + target_include_directories(PortAudio PRIVATE src/hostapi/coreaudio) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_mac_core.h) - SET(PA_EXTRA_SHARED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/portaudio_cmake.def) + find_library(COREAUDIO_LIBRARY CoreAudio REQUIRED) + find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox REQUIRED) + find_library(AUDIOUNIT_LIBRARY AudioUnit REQUIRED) + find_library(COREFOUNDATION_LIBRARY CoreFoundation REQUIRED) + find_library(CORESERVICES_LIBRARY CoreServices REQUIRED) + target_link_libraries(PortAudio PRIVATE + "${COREAUDIO_LIBRARY}" + "${AUDIOTOOLBOX_LIBRARY}" + "${AUDIOUNIT_LIBRARY}" + "${COREFOUNDATION_LIBRARY}" + "${CORESERVICES_LIBRARY}" + ) + target_compile_definitions(PortAudio PRIVATE PA_USE_COREAUDIO=1) + set(PKGCONFIG_LDFLAGS_PRIVATE + "${PKGCONFIG_LDFLAGS_PRIVATE} -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreFoundation -framework CoreServices") + else() + # Some BSDs have a reimplementation of alsalib, so do not explicitly check for Linux. + find_package(ALSA) + cmake_dependent_option(ALSA "Enable support for ALSA" ON ALSA_FOUND OFF) + if(ALSA) + target_link_libraries(PortAudio PRIVATE "${ALSA_LIBRARIES}") + target_sources(PortAudio PRIVATE src/hostapi/alsa/pa_linux_alsa.c) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_linux_alsa.h) + target_compile_definitions(PortAudio PRIVATE PA_USE_ALSA=1) -ELSE() + option(ALSA_DYNAMIC "Enable dynamically loading libasound with dlopen using PaAlsa_SetLibraryPathName" OFF) + if(ALSA_DYNAMIC) + target_compile_definitions(PortAudio PRIVATE PA_ALSA_DYNAMIC) + target_link_libraries(PortAudio PRIVATE "${CMAKE_DL_LIBS}") + set(PKGCONFIG_LDFLAGS_PRIVATE "${PKGCONFIG_LDFLAGS_PRIVATE} -l${CMAKE_DL_LIBS}") + else() + set(PKGCONFIG_REQUIRES_PRIVATE "${PKGCONFIG_REQUIRES_PRIVATE} alsa") + endif() + endif() - SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} src/os/unix) - SET(PA_PLATFORM_SOURCES src/os/unix/pa_unix_hostapis.c src/os/unix/pa_unix_util.c) - SOURCE_GROUP("os\\unix" FILES ${PA_PLATFORM_SOURCES}) - SET(PA_SOURCES ${PA_SOURCES} ${PA_PLATFORM_SOURCES}) + # OSS is intentionally off by default to avoid confusing users of PortAudio + # applications. OSS builds but there are no devices available on modern + # Linux systems. + find_package(OSS) + cmake_dependent_option(OSS "Enable support for OSS" OFF "OSS_FOUND" OFF) + if(OSS) + target_sources(PortAudio PRIVATE src/hostapi/oss/pa_unix_oss.c) + target_compile_definitions(PortAudio PRIVATE PA_USE_OSS=1) + target_link_libraries(PortAudio PRIVATE OSS::oss) + # The FindOSS.cmake module does not need to be installed like the JACK modules because it + # does not link any library; it only adds an include directory and compile definition. + endif() + endif() +endif() - IF(APPLE) +# +# Installation +# - SET(CMAKE_MACOSX_RPATH 1) - OPTION(PA_USE_COREAUDIO "Enable support for CoreAudio" ON) - IF(PA_USE_COREAUDIO) - SET(PA_COREAUDIO_SOURCES - src/hostapi/coreaudio/pa_mac_core.c - src/hostapi/coreaudio/pa_mac_core_blocking.c - src/hostapi/coreaudio/pa_mac_core_utilities.c) - SET(PA_COREAUDIO_INCLUDES - src/hostapi/coreaudio/pa_mac_core_blocking.h - src/hostapi/coreaudio/pa_mac_core_utilities.h) - SOURCE_GROUP("hostapi\\coreaudio" FILES ${PA_COREAUDIO_SOURCES} ${PA_COREAUDIO_INCLUDES}) - SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_mac_core.h) - SET(PA_PRIVATE_INCLUDES ${PA_PRIVATE_INCLUDES} ${PA_COREAUDIO_INCLUDES}) - SET(PA_SOURCES ${PA_SOURCES} ${PA_COREAUDIO_SOURCES}) +include(CMakePackageConfigHelpers) - FIND_LIBRARY(COREAUDIO_LIBRARY CoreAudio REQUIRED) - FIND_LIBRARY(AUDIOTOOLBOX_LIBRARY AudioToolbox REQUIRED) - FIND_LIBRARY(AUDIOUNIT_LIBRARY AudioUnit REQUIRED) - FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation REQUIRED) - FIND_LIBRARY(CORESERVICES_LIBRARY CoreServices REQUIRED) - MARK_AS_ADVANCED(COREAUDIO_LIBRARY AUDIOTOOLBOX_LIBRARY AUDIOUNIT_LIBRARY COREFOUNDATION_LIBRARY CORESERVICES_LIBRARY) - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ${COREAUDIO_LIBRARY} ${AUDIOTOOLBOX_LIBRARY} ${AUDIOUNIT_LIBRARY} ${COREFOUNDATION_LIBRARY} ${CORESERVICES_LIBRARY}) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_USE_COREAUDIO) - SET(PA_PKGCONFIG_LDFLAGS "${PA_PKGCONFIG_LDFLAGS} -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreFoundation -framework CoreServices") - ENDIF() +if(NOT CMAKE_FRAMEWORK) + install(FILES README.md DESTINATION "${CMAKE_INSTALL_DOCDIR}/portaudio") + install(FILES LICENSE.txt DESTINATION "${CMAKE_INSTALL_DOCDIR}/portaudio") - ELSEIF(UNIX) + configure_file(cmake/portaudio-2.0.pc.in "${CMAKE_CURRENT_BINARY_DIR}/portaudio-2.0.pc" @ONLY) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/portaudio-2.0.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") - FIND_PACKAGE(Jack) - IF(JACK_FOUND) - OPTION(PA_USE_JACK "Enable support for Jack" ON) - ELSE() - OPTION(PA_USE_JACK "Enable support for Jack" OFF) - ENDIF() - IF(PA_USE_JACK) - SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${JACK_INCLUDE_DIRS}) - SET(PA_JACK_SOURCES src/hostapi/jack/pa_jack.c) - SOURCE_GROUP("hostapi\\JACK" FILES ${PA_JACK_SOURCES}) - SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_jack.h) - SET(PA_SOURCES ${PA_SOURCES} ${PA_JACK_SOURCES}) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_USE_JACK) - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ${JACK_LIBRARIES}) - SET(PA_PKGCONFIG_LDFLAGS "${PA_PKGCONFIG_LDFLAGS} -ljack") - ENDIF() + configure_package_config_file(cmake/PortAudioConfig.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/cmake/portaudio/PortAudioConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/portaudio" + NO_CHECK_REQUIRED_COMPONENTS_MACRO + ) + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/cmake/portaudio/PortAudioConfigVersion.cmake" + VERSION "${PORTAUDIO_VERSION}" + COMPATIBILITY SameMajorVersion + ) + install(EXPORT PortAudio-targets NAMESPACE "PortAudio::" FILE "PortAudioTargets.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/portaudio") + export(TARGETS PortAudio + FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/portaudio/PortAudioTargets.cmake") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/portaudio/PortAudioConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/cmake/portaudio/PortAudioConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/portaudio") - FIND_PACKAGE(ALSA) - IF(ALSA_FOUND) - OPTION(PA_USE_ALSA "Enable support for ALSA" ON) - OPTION(PA_ALSA_DYNAMIC "Enable loading ALSA through dlopen" OFF) - ELSE() - OPTION(PA_USE_ALSA "Enable support for ALSA" OFF) - ENDIF() - IF(PA_USE_ALSA) - SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${ALSA_INCLUDE_DIRS}) - SET(PA_ALSA_SOURCES src/hostapi/alsa/pa_linux_alsa.c) - SOURCE_GROUP("hostapi\\ALSA" FILES ${PA_ALSA_SOURCES}) - SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_linux_alsa.h) - SET(PA_SOURCES ${PA_SOURCES} ${PA_ALSA_SOURCES}) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_USE_ALSA) - IF(PA_ALSA_DYNAMIC) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_ALSA_DYNAMIC) - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ${CMAKE_DL_LIBS}) - SET(PA_PKGCONFIG_LDFLAGS "${PA_PKGCONFIG_LDFLAGS} -l${CMAKE_DL_LIBS}") - ELSE() - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ${ALSA_LIBRARIES}) - SET(PA_PKGCONFIG_LDFLAGS "${PA_PKGCONFIG_LDFLAGS} -lasound") - ENDIF() - ENDIF() - - ENDIF() - - SET(PA_PKGCONFIG_LDFLAGS "${PA_PKGCONFIG_LDFLAGS} -lm -lpthread") - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} m pthread) - -ENDIF() - -SOURCE_GROUP("include" FILES ${PA_PUBLIC_INCLUDES}) - -SET(PA_INCLUDES ${PA_PRIVATE_INCLUDES} ${PA_PUBLIC_INCLUDES}) - -IF(WIN32) - OPTION(PA_UNICODE_BUILD "Enable Portaudio Unicode build" ON) - IF(PA_UNICODE_BUILD) - SET_SOURCE_FILES_PROPERTIES(${PA_SOURCES} PROPERTIES COMPILE_DEFINITIONS "UNICODE;_UNICODE") - ENDIF() -ENDIF() - -OPTION(PA_ENABLE_DEBUG_OUTPUT "Enable debug output for Portaudio" OFF) -IF(PA_ENABLE_DEBUG_OUTPUT) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_ENABLE_DEBUG_OUTPUT) -ENDIF() - -INCLUDE(TestBigEndian) -TEST_BIG_ENDIAN(IS_BIG_ENDIAN) -IF(IS_BIG_ENDIAN) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_BIG_ENDIAN) -ELSE() - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_LITTLE_ENDIAN) -ENDIF() - -OPTION(PA_BUILD_STATIC "Build static library" ON) -OPTION(PA_BUILD_SHARED "Build shared/dynamic library" ON) - -IF(MSVC) - OPTION(PA_LIBNAME_ADD_SUFFIX "Add suffix _static to static library name" ON) -ELSE() - OPTION(PA_LIBNAME_ADD_SUFFIX "Add suffix _static to static library name" OFF) -ENDIF() - -# MSVC: if PA_LIBNAME_ADD_SUFFIX is not used, and both static and shared libraries are -# built, one, of import- and static libraries, will overwrite the other. In -# embedded builds this is not an issue as they will only build the configuration -# used in the host application. -MARK_AS_ADVANCED(PA_LIBNAME_ADD_SUFFIX) -IF(MSVC AND PA_BUILD_STATIC AND PA_BUILD_SHARED AND NOT PA_LIBNAME_ADD_SUFFIX) - MESSAGE(WARNING "Building both shared and static libraries, and avoiding the suffix _static will lead to a name conflict") - SET(PA_LIBNAME_ADD_SUFFIX ON CACHE BOOL "Forcing use of suffix _static to avoid name conflict between static and import library" FORCE) - MESSAGE(WARNING "PA_LIBNAME_ADD_SUFFIX was set to ON") -ENDIF() - -SET(PA_TARGETS "") - -IF(PA_BUILD_SHARED) - LIST(APPEND PA_TARGETS portaudio) - ADD_LIBRARY(portaudio SHARED ${PA_INCLUDES} ${PA_COMMON_INCLUDES} ${PA_SOURCES} ${PA_NON_UNICODE_SOURCES} ${PA_EXTRA_SHARED_SOURCES}) - SET_PROPERTY(TARGET portaudio APPEND_STRING PROPERTY COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS}) - TARGET_INCLUDE_DIRECTORIES(portaudio PRIVATE ${PA_PRIVATE_INCLUDE_PATHS}) - TARGET_INCLUDE_DIRECTORIES(portaudio PUBLIC "$" "$") - TARGET_LINK_LIBRARIES(portaudio ${PA_LIBRARY_DEPENDENCIES}) -ENDIF() - -IF(PA_BUILD_STATIC) - LIST(APPEND PA_TARGETS portaudio_static) - ADD_LIBRARY(portaudio_static STATIC ${PA_INCLUDES} ${PA_COMMON_INCLUDES} ${PA_SOURCES} ${PA_NON_UNICODE_SOURCES}) - SET_PROPERTY(TARGET portaudio_static APPEND_STRING PROPERTY COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS}) - TARGET_INCLUDE_DIRECTORIES(portaudio_static PRIVATE ${PA_PRIVATE_INCLUDE_PATHS}) - TARGET_INCLUDE_DIRECTORIES(portaudio_static PUBLIC "$" "$") - TARGET_LINK_LIBRARIES(portaudio_static ${PA_LIBRARY_DEPENDENCIES}) - IF(NOT PA_LIBNAME_ADD_SUFFIX) - SET_PROPERTY(TARGET portaudio_static PROPERTY OUTPUT_NAME portaudio) - ENDIF() -ENDIF() - -IF(WIN32 AND MSVC) - OPTION(PA_CONFIG_LIB_OUTPUT_PATH "Make sure that output paths are kept neat" OFF) - IF(CMAKE_CL_64) - SET(TARGET_POSTFIX x64) - IF(PA_CONFIG_LIB_OUTPUT_PATH) - SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin/x64) - ENDIF() - ELSE() - SET(TARGET_POSTFIX x86) - IF(PA_CONFIG_LIB_OUTPUT_PATH) - SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin/Win32) - ENDIF() - ENDIF() - IF(PA_BUILD_SHARED) - IF(PA_LIBNAME_ADD_SUFFIX) - SET_TARGET_PROPERTIES(portaudio PROPERTIES OUTPUT_NAME portaudio_${TARGET_POSTFIX}) - ELSE() - SET_TARGET_PROPERTIES(portaudio PROPERTIES OUTPUT_NAME portaudio) - ENDIF() - ENDIF() - IF(PA_BUILD_STATIC) - IF(PA_LIBNAME_ADD_SUFFIX) - SET_TARGET_PROPERTIES(portaudio_static PROPERTIES OUTPUT_NAME portaudio_static_${TARGET_POSTFIX}) - ELSE() - SET_TARGET_PROPERTIES(portaudio_static PROPERTIES OUTPUT_NAME portaudio) - ENDIF() - ENDIF() -ELSE() - IF(APPLE AND CMAKE_VERSION VERSION_GREATER 3.4.2) - OPTION(PA_OUTPUT_OSX_FRAMEWORK "Generate an OS X framework instead of the simple library" OFF) - IF(PA_OUTPUT_OSX_FRAMEWORK) - SET_TARGET_PROPERTIES(portaudio PROPERTIES - FRAMEWORK TRUE - MACOSX_FRAMEWORK_IDENTIFIER com.portaudio - FRAMEWORK_VERSION A - PUBLIC_HEADER "${PA_PUBLIC_INCLUDES}" - VERSION ${PA_SOVERSION} - SOVERSION ${PA_SOVERSION}) - ENDIF() - ENDIF() -ENDIF() - -# At least on Windows in embedded builds, portaudio's install target should likely -# not be executed, as the library would usually already be installed as part of, and -# by means of the host application. -# The option below offers the option to avoid executing the portaudio install target -# for cases in which the host-application executes install, but no independent install -# of portaudio is wished. -OPTION(PA_DISABLE_INSTALL "Disable targets install and uninstall (for embedded builds)" OFF) - -IF(NOT PA_OUTPUT_OSX_FRAMEWORK AND NOT PA_DISABLE_INSTALL) - INCLUDE(CMakePackageConfigHelpers) - - CONFIGURE_PACKAGE_CONFIG_FILE(cmake_support/portaudioConfig.cmake.in ${CMAKE_BINARY_DIR}/cmake/portaudio/portaudioConfig.cmake - INSTALL_DESTINATION "lib/cmake/portaudio" - NO_CHECK_REQUIRED_COMPONENTS_MACRO) - WRITE_BASIC_PACKAGE_VERSION_FILE(${CMAKE_BINARY_DIR}/cmake/portaudio/portaudioConfigVersion.cmake - VERSION ${PA_VERSION} - COMPATIBILITY SameMajorVersion) - CONFIGURE_FILE(cmake_support/portaudio-2.0.pc.in ${CMAKE_CURRENT_BINARY_DIR}/portaudio-2.0.pc @ONLY) - INSTALL(FILES README.md DESTINATION share/doc/portaudio) - INSTALL(FILES LICENSE.txt DESTINATION share/doc/portaudio) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/portaudio-2.0.pc DESTINATION lib/pkgconfig) - INSTALL(FILES ${PA_PUBLIC_INCLUDES} DESTINATION include) - INSTALL(TARGETS ${PA_TARGETS} - EXPORT portaudio-targets - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib) - INSTALL(EXPORT portaudio-targets FILE "portaudioTargets.cmake" DESTINATION "lib/cmake/portaudio") - EXPORT(TARGETS ${PA_TARGETS} FILE "${PROJECT_BINARY_DIR}/cmake/portaudio/portaudioTargets.cmake") - INSTALL(FILES "${CMAKE_BINARY_DIR}/cmake/portaudio/portaudioConfig.cmake" - "${CMAKE_BINARY_DIR}/cmake/portaudio/portaudioConfigVersion.cmake" - DESTINATION "lib/cmake/portaudio") - - IF (NOT TARGET uninstall) - CONFIGURE_FILE( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake_support/cmake_uninstall.cmake.in" + if(NOT TARGET uninstall) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) - ADD_CUSTOM_TARGET(uninstall - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) - ENDIF() -ENDIF() + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") + endif() +endif() -# Prepared for inclusion of test files -OPTION(PA_BUILD_TESTS "Include test projects" OFF) -IF(PA_BUILD_TESTS) - MACRO(ADD_TEST appl_name) - ADD_EXECUTABLE(${appl_name} "${appl_name}.c") - TARGET_LINK_LIBRARIES(${appl_name} portaudio_static) - TARGET_INCLUDE_DIRECTORIES(${appl_name} PRIVATE "${CMAKE_SOURCE_DIR}/src/common") - SET_TARGET_PROPERTIES(${appl_name} +set_target_properties(PortAudio PROPERTIES + OUTPUT_NAME portaudio + PUBLIC_HEADER "${PORTAUDIO_PUBLIC_HEADERS}" + MACOSX_FRAMEWORK_IDENTIFIER com.portaudio + FRAMEWORK_VERSION A + WINDOWS_EXPORT_ALL_SYMBOLS TRUE + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION} +) +install(TARGETS PortAudio + EXPORT PortAudio-targets + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + FRAMEWORK DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" +) + +# +# Subdirectories +# + +# Some of the tests and examples use private symbols which are not +# exposed by the .def file on Windows. +if(WIN32 AND BUILD_SHARED_LIBS) + set(LINK_PRIVATE_SYMBOLS OFF) +else() + set(LINK_PRIVATE_SYMBOLS ON) +endif() + +if(BUILD_TESTING) + macro(add_test appl_name) + add_executable(${appl_name} "${appl_name}.c") + target_link_libraries(${appl_name} PortAudio Threads::Threads) + if(UNIX) + target_link_libraries(${appl_name} m) + endif() + set_target_properties(${appl_name} PROPERTIES FOLDER "Test" ) - ENDMACRO(ADD_TEST) + endmacro() - SUBDIRS(test) - SUBDIRS(qa) -ENDIF() + subdirs(test) + subdirs(qa) +endif() -# Prepared for inclusion of test files -OPTION(PA_BUILD_EXAMPLES "Include example projects" OFF) -IF(PA_BUILD_EXAMPLES) - SUBDIRS(examples) -ENDIF() +if(BUILD_EXAMPLES) + subdirs(examples) +endif() diff --git a/Makefile.in b/Makefile.in index 8eb7342..527e199 100644 --- a/Makefile.in +++ b/Makefile.in @@ -44,7 +44,7 @@ PALIB = libportaudio.la PAINC = include/portaudio.h PA_LDFLAGS = $(LDFLAGS) $(SHARED_FLAGS) -rpath $(libdir) -no-undefined \ - -export-symbols-regex "(Pa|PaMacCore|PaJack|PaAlsa|PaAsio|PaOSS|PaWasapi|PaWasapiWinrt)_.*" \ + -export-symbols-regex "(Pa|PaMacCore|PaJack|PaAlsa|PaAsio|PaOSS|PaWasapi|PaWasapiWinrt|PaWinMME)_.*" \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) COMMON_OBJS = \ diff --git a/build/msvc/portaudio.def b/build/msvc/portaudio.def index 8de8065..fa34168 100644 --- a/build/msvc/portaudio.def +++ b/build/msvc/portaudio.def @@ -57,3 +57,7 @@ PaWasapi_SetStreamStateHandler @68 PaWasapiWinrt_SetDefaultDeviceId @67 PaWasapiWinrt_PopulateDeviceList @69 PaWasapi_GetIMMDevice @70 +PaWinMME_GetStreamInputHandleCount @71 +PaWinMME_GetStreamInputHandle @72 +PaWinMME_GetStreamOutputHandleCount @73 +PaWinMME_GetStreamOutputHandle @74 diff --git a/cmake/PortAudioConfig.cmake.in b/cmake/PortAudioConfig.cmake.in new file mode 100644 index 0000000..ecc5d16 --- /dev/null +++ b/cmake/PortAudioConfig.cmake.in @@ -0,0 +1,18 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/PortAudioTargets.cmake") + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules") + +include(CMakeFindDependencyMacro) + +find_dependency(Threads) + +if(@JACK@) + find_dependency(Regex) + find_dependency(JACK) +endif() + +if(@ALSA@) + find_dependency(ALSA) +endif() diff --git a/cmake_support/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in similarity index 100% rename from cmake_support/cmake_uninstall.cmake.in rename to cmake/cmake_uninstall.cmake.in diff --git a/cmake/modules/FindASIO.cmake b/cmake/modules/FindASIO.cmake new file mode 100644 index 0000000..d67cf42 --- /dev/null +++ b/cmake/modules/FindASIO.cmake @@ -0,0 +1,79 @@ +#[=======================================================================[.rst: +FindASIO +-------- + +Finds the ASIO SDK by searching for the SDK ZIP in CMAKE_PREFIX_PATH and +CMAKE_CURRENT_BINARY_DIR. Alternatively, you may manually specify the path of +the SDK ZIP with the ASIO_SDK_ZIP_PATH variable, which can be used for caching +in CI scripts. + +If the ZIP is found, this module extracts it. +The ZIP extraction is skipped if the unzipped SDK is found. + +This module provides an `ASIO::host` IMPORT library target for building host +applications which use ASIO drivers. If you want to build an ASIO driver, this +module may serve as a useful start but you will need to modify it. + +#]=======================================================================] + +if(NOT WIN32) + message(FATAL_ERROR "ASIO is only supported on Windows.") +endif() + +file(GLOB HEADER_FILE + "${CMAKE_CURRENT_BINARY_DIR}/asiosdk*/common/asio.h" + "${CMAKE_PREFIX_PATH}/asiosdk*/common/asio.h" + # The old build systems before PortAudio 19.8 used to look for the ASIO SDK + # in the same parent directory as the source code repository. This is no + # longer advised or documented but kept for backwards compatibility. + "${CMAKE_CURRENT_SOURCE_DIR}/../asiosdk*/common/asio.h" +) +if(NOT EXISTS "${HEADER_FILE}") + # The file(ARCHIVE_EXTRACT) command was added in CMake 3.18, so if using an + # older version of CMake, the user needs to extract it themselves. + if(CMAKE_VERSION VERSION_LESS 3.18) + message(STATUS "ASIO SDK NOT found. Download the ASIO SDK ZIP from " + "https://www.steinberg.net/asiosdk and extract it to " + "${CMAKE_PREFIX_PATH} or ${CMAKE_CURRENT_BINARY_DIR}" + ) + return() + endif() + file(GLOB results + "${ASIO_SDK_ZIP_PATH}" + "${CMAKE_CURRENT_BINARY_DIR}/asiosdk*.zip" + "${CMAKE_PREFIX_PATH}/asiosdk*.zip" + "${CMAKE_CURRENT_SOURCE_DIR}/../asiosdk*.zip" + ) + foreach(f ${results}) + if(EXISTS "${f}") + message(STATUS "Extracting ASIO SDK ZIP archive: ${f}") + file(ARCHIVE_EXTRACT INPUT "${f}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") + endif() + endforeach() + file(GLOB HEADER_FILE "${CMAKE_CURRENT_BINARY_DIR}/asiosdk*/common/asio.h") +endif() + +get_filename_component(HEADER_DIR "${HEADER_FILE}" DIRECTORY) +get_filename_component(ASIO_ROOT "${HEADER_DIR}" DIRECTORY) + +if(ASIO_ROOT) + set(ASIO_FOUND TRUE) + message(STATUS "Found ASIO SDK: ${ASIO_ROOT}") + + if(ASIO_FOUND AND NOT TARGET ASIO::host) + add_library(ASIO::host INTERFACE IMPORTED) + target_sources(ASIO::host INTERFACE + "${ASIO_ROOT}/common/asio.cpp" + "${ASIO_ROOT}/host/asiodrivers.cpp" + "${ASIO_ROOT}/host/pc/asiolist.cpp" + ) + target_include_directories(ASIO::host INTERFACE + "${ASIO_ROOT}/common" + "${ASIO_ROOT}/host" + "${ASIO_ROOT}/host/pc" + ) + target_link_libraries(ASIO::host INTERFACE ole32 uuid) + endif() +else() + message(STATUS "ASIO SDK NOT found") +endif() diff --git a/cmake/modules/FindJACK.cmake b/cmake/modules/FindJACK.cmake new file mode 100644 index 0000000..5bf8e42 --- /dev/null +++ b/cmake/modules/FindJACK.cmake @@ -0,0 +1,67 @@ +#[=======================================================================[.rst: +FindJACK +-------- + +Finds the JACK Audio Connection Kit library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module provides the following imported targets, if found: + +``JACK::jack`` + The JACK library + +#]=======================================================================] + +# Prefer finding the libraries from pkgconfig rather than find_library. This is +# required to build with PipeWire's reimplementation of the JACK library. +# +# This also enables using PortAudio with the jack2 port in vcpkg. That only +# builds JackWeakAPI (not the JACK server) which dynamically loads the real +# JACK library and forwards API calls to it. JackWeakAPI requires linking `dl` +# in addition to jack, as specified in the pkgconfig file in vcpkg. +find_package(PkgConfig QUIET) +if(PkgConfig_FOUND) + pkg_check_modules(JACK jack) +else() + find_library(JACK_LINK_LIBRARIES + NAMES jack + DOC "JACK library" + ) + find_path(JACK_INCLUDEDIR + NAMES jack/jack.h + DOC "JACK header" + ) +endif() + +find_package(Regex) +list(APPEND JACK_LINK_LIBRARIES Regex::regex) + +if(NOT CMAKE_USE_PTHREADS_INIT) + # This CMake find module is provided by the pthreads port in vcpkg. + find_package(pthreads) + list(APPEND JACK_LINK_LIBRARIES PThreads4W::PThreads4W) +endif() + +if(CMAKE_USE_PTHREADS_INIT OR TARGET PThreads4W::PThreads4W) + set(PTHREADS_AVAILABLE TRUE) +else() + set(PTHREADS_AVAILABLE FALSE) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + JACK + DEFAULT_MSG + JACK_LINK_LIBRARIES + JACK_INCLUDEDIR + PTHREADS_AVAILABLE + Regex_FOUND +) + +if(JACK_FOUND AND NOT TARGET JACK::jack) + add_library(JACK::jack INTERFACE IMPORTED) + target_link_libraries(JACK::jack INTERFACE "${JACK_LINK_LIBRARIES}" Regex::regex) + target_include_directories(JACK::jack INTERFACE "${JACK_INCLUDEDIR}") +endif() diff --git a/cmake/modules/FindOSS.cmake b/cmake/modules/FindOSS.cmake new file mode 100644 index 0000000..eec7dc3 --- /dev/null +++ b/cmake/modules/FindOSS.cmake @@ -0,0 +1,57 @@ +#[=======================================================================[.rst: +FindOSS +-------- + +Finds the Open Sound System include directory. There is no library to link. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module provides the following imported targets, if found: + +``OSS::oss`` + Target for the OSS header include directory. One of the following + compile definitions is added to the target: + HAVE_SYS_SOUNDCARD_H if the header is sys/soundcard.h + HAVE_LINUX_SOUNDCARD_H if the header is linux/soundcard.h + HAVE_MACHINE_SOUNDCARD_H if the header is machine/soundcard.h + +#]=======================================================================] + +find_path(OSS_INCLUDE_DIR + NAMES sys/soundcard.h + DOC "OSS include directory") +if(OSS_INCLUDE_DIR) + set(OSS_DEFINITIONS HAVE_SYS_SOUNDCARD_H) +else() + find_path(OSS_INCLUDE_DIR + NAMES linux/soundcard.h + DOC "OSS include directory") + if(OSS_INCLUDE_DIR) + set(OSS_DEFINITIONS HAVE_LINUX_SOUNDCARD_H) + else() + find_path(OSS_INCLUDE_DIR + NAMES machine/soundcard.h + DOC "OSS include directory") + if(OSS_INCLUDE_DIR) + set(OSS_DEFINITIONS HAVE_MACHINE_SOUNDCARD_H) + endif() + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + OSS + DEFAULT_MSG + OSS_INCLUDE_DIR + OSS_DEFINITIONS +) + +if(OSS_INCLUDE_DIR AND OSS_DEFINITIONS) + set(OSS_FOUND TRUE) + if(NOT TARGET OSS::oss) + add_library(OSS::oss INTERFACE IMPORTED) + target_include_directories(OSS::oss INTERFACE "${OSS_INCLUDE_DIR}") + target_compile_definitions(OSS::oss INTERFACE "${OSS_DEFINITIONS}") + endif() +endif() diff --git a/cmake/modules/FindRegex.cmake b/cmake/modules/FindRegex.cmake new file mode 100644 index 0000000..8793de6 --- /dev/null +++ b/cmake/modules/FindRegex.cmake @@ -0,0 +1,68 @@ +#[=======================================================================[.rst: +FindRegex +-------- + +Finds an implementation of POSIX regular expressions. It first checks if the +standard regex.h POSIX header is available. If not, it looks for the TRE library. +MinGW does not come with regex.h, so TRE is useful with MinGW. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module provides the following imported targets, if found: + +``Regex::regex`` + The POSIX regular expression implementation + +#]=======================================================================] + +include(FindPackageHandleStandardArgs) +include(CheckIncludeFile) + +set(CMAKE_REQUIRED_QUIET TRUE) +check_include_file(regex.h REGEX_H) +set(CMAKE_REQUIRED_QUIET FALSE) + +if(REGEX_H) + # No need to add any include directories or link any libraries; + # simply provide a dummy target. + if(NOT TARGET Regex::regex) + add_library(Regex::regex INTERFACE IMPORTED) + endif() + + # check_include_file sets the variable to "1" which looks odd in the output + # of find_package_handle_standard_args, so show the user what was actually found. + set(REGEX_H "POSIX regex.h") + find_package_handle_standard_args( + Regex + DEFAULT_MSG + REGEX_H + ) +else() + # MinGW does not include regex.h but this can be supplied by the TRE library. + find_path(TRE_REGEX_H NAMES tre/regex.h) + if(TRE_REGEX_H) + # The POSIX #include is simply but the tre regex.h is at , + # so add the directory containing tre's headers to the include path. + set(TRE_INCLUDE_DIR "${TRE_REGEX_H}/tre") + endif() + find_library(TRE_LIBRARY NAMES tre) + if(TRE_REGEX_H AND TRE_LIBRARY) + message(STATUS "Found regex.h from TRE") + else() + message(STATUS "regex.h POSIX header NOT found and NOT available from TRE") + endif() + + if(NOT TARGET Regex::regex) + add_library(Regex::regex INTERFACE IMPORTED) + target_include_directories(Regex::regex INTERFACE "${TRE_INCLUDE_DIR}") + target_link_libraries(Regex::regex INTERFACE "${TRE_LIBRARY}") + endif() + + find_package_handle_standard_args( + Regex + DEFAULT_MSG + TRE_INCLUDE_DIR + TRE_LIBRARY + ) +endif() diff --git a/cmake/portaudio-2.0.pc.in b/cmake/portaudio-2.0.pc.in new file mode 100644 index 0000000..414be05 --- /dev/null +++ b/cmake/portaudio-2.0.pc.in @@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ + +Name: PortAudio +Description: Portable audio I/O +Version: @CMAKE_PROJECT_VERSION@ + +Libs: -L${libdir} -lportaudio +Libs.private: @PKGCONFIG_LDFLAGS_PRIVATE@ +Cflags: -I${includedir} @PKGCONFIG_CFLAGS@ +Requires.private: @PKGCONFIG_REQUIRES_PRIVATE@ diff --git a/cmake_support/template_portaudio.def b/cmake/portaudio.def.in similarity index 90% rename from cmake_support/template_portaudio.def rename to cmake/portaudio.def.in index b5d56f1..af4d996 100644 --- a/cmake_support/template_portaudio.def +++ b/cmake/portaudio.def.in @@ -6,7 +6,7 @@ EXPORTS ; Pa_GetVersion @1 Pa_GetVersionText @2 -Pa_GetErrorText @3 +Pa_GetErrorText @3 Pa_Initialize @4 Pa_Terminate @5 Pa_GetHostApiCount @6 @@ -60,3 +60,7 @@ PaUtil_SetDebugPrintFunction @55 @DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapiWinrt_SetDefaultDeviceId @67 @DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapiWinrt_PopulateDeviceList @69 @DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetIMMDevice @70 +@DEF_EXCLUDE_WMME_SYMBOLS@PaWinMME_GetStreamInputHandleCount @71 +@DEF_EXCLUDE_WMME_SYMBOLS@PaWinMME_GetStreamInputHandle @72 +@DEF_EXCLUDE_WMME_SYMBOLS@PaWinMME_GetStreamOutputHandleCount @73 +@DEF_EXCLUDE_WMME_SYMBOLS@PaWinMME_GetStreamOutputHandle @74 diff --git a/i686-w64-mingw32.cmake b/cmake/toolchains/i686-w64-mingw32.cmake similarity index 88% rename from i686-w64-mingw32.cmake rename to cmake/toolchains/i686-w64-mingw32.cmake index c3331b6..2a2c7bf 100644 --- a/i686-w64-mingw32.cmake +++ b/cmake/toolchains/i686-w64-mingw32.cmake @@ -1,6 +1,6 @@ # CMake Toolchain file for cross-compiling PortAudio to i686-w64-mingw32 # Inspired from: https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/cross_compiling/Mingw -# Example usage: $ cmake -DCMAKE_TOOLCHAIN_FILE=i686-w64-mingw32.cmake . +# Example usage: $ cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/i686-w64-mingw32.cmake . # i686-w64-mingw32 needs to be installed for this to work. On Debian-based # distributions the package is typically named `mingw-w64`. diff --git a/cmake_support/FindASIOSDK.cmake b/cmake_support/FindASIOSDK.cmake deleted file mode 100644 index 55ad33d..0000000 --- a/cmake_support/FindASIOSDK.cmake +++ /dev/null @@ -1,41 +0,0 @@ -# $Id: $ -# -# - Try to find the ASIO SDK -# Once done this will define -# -# ASIOSDK_FOUND - system has ASIO SDK -# ASIOSDK_ROOT_DIR - path to the ASIO SDK base directory -# ASIOSDK_INCLUDE_DIR - the ASIO SDK include directory - -if(WIN32) -else(WIN32) - message(FATAL_ERROR "FindASIOSDK.cmake: Unsupported platform ${CMAKE_SYSTEM_NAME}" ) -endif(WIN32) - -file(GLOB results "${CMAKE_CURRENT_SOURCE_DIR}/../as*") -foreach(f ${results}) - if(IS_DIRECTORY ${f}) - set(ASIOSDK_PATH_HINT ${ASIOSDK_PATH_HINT} ${f}) - endif() -endforeach() - -find_path(ASIOSDK_ROOT_DIR - common/asio.h - HINTS - ${ASIOSDK_PATH_HINT} -) - -find_path(ASIOSDK_INCLUDE_DIR - asio.h - PATHS - ${ASIOSDK_ROOT_DIR}/common -) - -# handle the QUIETLY and REQUIRED arguments and set ASIOSDK_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(ASIOSDK DEFAULT_MSG ASIOSDK_ROOT_DIR ASIOSDK_INCLUDE_DIR) - -MARK_AS_ADVANCED( - ASIOSDK_ROOT_DIR ASIOSDK_INCLUDE_DIR -) diff --git a/cmake_support/FindJack.cmake b/cmake_support/FindJack.cmake deleted file mode 100644 index 96e0b50..0000000 --- a/cmake_support/FindJack.cmake +++ /dev/null @@ -1,41 +0,0 @@ -# - Try to find jack -# Once done this will define -# JACK_FOUND - System has jack -# JACK_INCLUDE_DIRS - The jack include directories -# JACK_LIBRARIES - The libraries needed to use jack -# JACK_DEFINITIONS - Compiler switches required for using jack - -if (JACK_LIBRARIES AND JACK_INCLUDE_DIRS) - - # in cache already - set(JACK_FOUND TRUE) - -else (JACK_LIBRARIES AND JACK_INCLUDE_DIRS) - - set(JACK_DEFINITIONS "") - - # Look for pkg-config and use it (if available) to find package - find_package(PkgConfig QUIET) - if (PKG_CONFIG_FOUND) - pkg_search_module(JACK QUIET jack) - endif (PKG_CONFIG_FOUND) - - if (NOT JACK_FOUND) - - find_path(JACK_INCLUDE_DIR jack/jack.h HINTS ${JACK_INCLUDEDIR} ${JACK_INCLUDE_DIRS} PATH_SUFFIXES jack) - find_library(JACK_LIBRARY NAMES jack HINTS ${JACK_LIBDIR} ${JACK_LIBRARY_DIRS}) - - set(JACK_LIBRARIES ${JACK_LIBRARY}) - set(JACK_INCLUDE_DIRS ${JACK_INCLUDE_DIR}) - - include(FindPackageHandleStandardArgs) - - # Set JACK_FOUND if the library and include paths were found - find_package_handle_standard_args(jack DEFAULT_MSG JACK_LIBRARY JACK_INCLUDE_DIR) - - # Don't show include/library paths in cmake GUI - mark_as_advanced(JACK_INCLUDE_DIR JACK_LIBRARY) - - endif (NOT JACK_FOUND) - -endif (JACK_LIBRARIES AND JACK_INCLUDE_DIRS) diff --git a/cmake_support/options_cmake.h.in b/cmake_support/options_cmake.h.in deleted file mode 100644 index cd07605..0000000 --- a/cmake_support/options_cmake.h.in +++ /dev/null @@ -1,31 +0,0 @@ -/* $Id: $ - - !!! @GENERATED_MESSAGE@ !!! - - Header file configured by CMake to convert CMake options/vars to macros. It is done this way because if set via - preprocessor options, MSVC f.i. has no way of knowing when an option (or var) changes as there is no dependency chain. - - The generated "options_cmake.h" should be included like so: - - #ifdef PORTAUDIO_CMAKE_GENERATED - #include "options_cmake.h" - #endif - - so that non-CMake build environments are left intact. - - Source template: cmake_support/options_cmake.h.in -*/ - -#ifdef _WIN32 -#if defined(PA_USE_ASIO) || defined(PA_USE_DS) || defined(PA_USE_WMME) || defined(PA_USE_WASAPI) || defined(PA_USE_WDMKS) -#error "This header needs to be included before pa_hostapi.h!!" -#endif - -#cmakedefine01 PA_USE_ASIO -#cmakedefine01 PA_USE_DS -#cmakedefine01 PA_USE_WMME -#cmakedefine01 PA_USE_WASAPI -#cmakedefine01 PA_USE_WDMKS -#else -#error "Platform currently not supported by CMake script" -#endif diff --git a/cmake_support/portaudio-2.0.pc.in b/cmake_support/portaudio-2.0.pc.in deleted file mode 100644 index 738803d..0000000 --- a/cmake_support/portaudio-2.0.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=${prefix} -libdir=${prefix}/lib -includedir=${prefix}/include - -Name: PortAudio -Description: Portable audio I/O -Requires: -Version: @PA_PKGCONFIG_VERSION@ - -Libs: -L${libdir} -lportaudio @PA_PKGCONFIG_LDFLAGS@ -Cflags: -I${includedir} @PA_PKGCONFIG_CFLAGS@ diff --git a/cmake_support/portaudioConfig.cmake.in b/cmake_support/portaudioConfig.cmake.in deleted file mode 100644 index cacc476..0000000 --- a/cmake_support/portaudioConfig.cmake.in +++ /dev/null @@ -1 +0,0 @@ -include("${CMAKE_CURRENT_LIST_DIR}/portaudioTargets.cmake") diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a4a9095..7fb5e7a 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,40 +1,46 @@ # Example projects -MACRO(ADD_EXAMPLE appl_name) - ADD_EXECUTABLE(${appl_name} "${appl_name}.c") - TARGET_LINK_LIBRARIES(${appl_name} portaudio_static) - TARGET_INCLUDE_DIRECTORIES(${appl_name} PRIVATE ../src/common) - SET_TARGET_PROPERTIES(${appl_name} PROPERTIES FOLDER "Examples C") - IF(WIN32) - SET_PROPERTY(TARGET ${appl_name} APPEND_STRING PROPERTY COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS) - ENDIF() -ENDMACRO(ADD_EXAMPLE) +macro(add_example appl_name) + add_executable(${appl_name} "${appl_name}.c") + target_link_libraries(${appl_name} PortAudio) + if(UNIX) + target_link_libraries(${appl_name} m) + endif() + set_target_properties(${appl_name} PROPERTIES FOLDER "Examples C") + if(WIN32) + set_property(TARGET ${appl_name} APPEND_STRING PROPERTY COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS) + endif() +endmacro() -MACRO(ADD_EXAMPLE_CPP appl_name) - ADD_EXECUTABLE(${appl_name} "${appl_name}.cpp") - TARGET_LINK_LIBRARIES(${appl_name} portaudio_static) - SET_TARGET_PROPERTIES(${appl_name} PROPERTIES FOLDER "Examples C++") - IF(WIN32) - SET_PROPERTY(TARGET ${appl_name} APPEND_STRING PROPERTY COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS) - ENDIF() -ENDMACRO(ADD_EXAMPLE_CPP) +macro(add_example_cpp appl_name) + add_executable(${appl_name} "${appl_name}.cpp") + target_link_libraries(${appl_name} PortAudio) + set_target_properties(${appl_name} PROPERTIES FOLDER "Examples C++") + if(WIN32) + set_property(TARGET ${appl_name} APPEND_STRING PROPERTY COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS) + endif() +endmacro() -ADD_EXAMPLE(pa_devs) -ADD_EXAMPLE(pa_fuzz) -IF(PA_USE_ASIO AND WIN32) - ADD_EXAMPLE(paex_mono_asio_channel_select) -ENDIF() -ADD_EXAMPLE(paex_ocean_shore) -ADD_EXAMPLE(paex_pink) -ADD_EXAMPLE(paex_read_write_wire) -ADD_EXAMPLE(paex_record) -ADD_EXAMPLE(paex_record_file) -ADD_EXAMPLE(paex_saw) -ADD_EXAMPLE(paex_sine) -ADD_EXAMPLE_CPP(paex_sine_c++) -IF(PA_USE_WMME AND WIN32) - ADD_EXAMPLE(paex_wmme_ac3) - ADD_EXAMPLE(paex_wmme_surround) -ENDIF() -ADD_EXAMPLE(paex_write_sine) -ADD_EXAMPLE(paex_write_sine_nonint) +add_example(pa_devs) +add_example(pa_fuzz) +if(ASIO AND WIN32) + add_example(paex_mono_asio_channel_select) +endif() +if(LINK_PRIVATE_SYMBOLS) + add_example(paex_ocean_shore) +endif() +add_example(paex_pink) +add_example(paex_read_write_wire) +add_example(paex_record) +if(LINK_PRIVATE_SYMBOLS) + add_example(paex_record_file) +endif() +add_example(paex_saw) +add_example(paex_sine) +add_example_cpp(paex_sine_c++) +if(MME AND WIN32) + add_example(paex_wmme_ac3) + add_example(paex_wmme_surround) +endif() +add_example(paex_write_sine) +add_example(paex_write_sine_nonint) diff --git a/qa/CMakeLists.txt b/qa/CMakeLists.txt index 26c0610..6577c98 100644 --- a/qa/CMakeLists.txt +++ b/qa/CMakeLists.txt @@ -1,5 +1,5 @@ -ADD_TEST(paqa_devs) -ADD_TEST(paqa_errs) -ADD_TEST(paqa_latency) +add_test(paqa_devs) +add_test(paqa_errs) +add_test(paqa_latency) -SUBDIRS(loopback) +subdirs(loopback) diff --git a/qa/loopback/CMakeLists.txt b/qa/loopback/CMakeLists.txt index d58caa3..0c66726 100644 --- a/qa/loopback/CMakeLists.txt +++ b/qa/loopback/CMakeLists.txt @@ -1,4 +1,4 @@ -ADD_EXECUTABLE(paloopback +add_executable(paloopback src/audio_analyzer.c src/biquad_filter.c src/paqa.c @@ -6,5 +6,8 @@ ADD_EXECUTABLE(paloopback src/test_audio_analyzer.c src/write_wav.c ) -TARGET_INCLUDE_DIRECTORIES(paloopback PRIVATE ..) -TARGET_LINK_LIBRARIES(paloopback portaudio) +target_include_directories(paloopback PRIVATE ..) +target_link_libraries(paloopback PortAudio) +if(UNIX) + target_link_libraries(paloopback m) +endif() diff --git a/src/hostapi/wasapi/pa_win_wasapi.c b/src/hostapi/wasapi/pa_win_wasapi.c index cad4b81..1890743 100644 --- a/src/hostapi/wasapi/pa_win_wasapi.c +++ b/src/hostapi/wasapi/pa_win_wasapi.c @@ -1207,6 +1207,8 @@ static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WO } #endif // Get Windows version +// note: We are trying to get Windows version starting from Windows Vista. Earlier OS versions +// will fall into WINDOWS_UNKNOWN case. static EWindowsVersion GetWindowsVersion() { #ifndef PA_WINRT @@ -1229,14 +1231,14 @@ static EWindowsVersion GetWindowsVersion() { OSVERSIONINFOW ver = { sizeof(OSVERSIONINFOW), 0, 0, 0, 0, {0} }; - PRINT(("WASAPI: getting Windows version with RtlGetVersion()\n")); - if (fnRtlGetVersion(&ver) == NTSTATUS_SUCCESS) { dwMajorVersion = ver.dwMajorVersion; dwMinorVersion = ver.dwMinorVersion; dwBuild = ver.dwBuildNumber; } + + PRINT(("WASAPI: getting Windows version with RtlGetVersion(): major=%d, minor=%d, build=%d\n", dwMajorVersion, dwMinorVersion, dwBuild)); } #undef NTSTATUS_SUCCESS @@ -1249,17 +1251,15 @@ static EWindowsVersion GetWindowsVersion() if ((fnGetVersion = (LPFN_GETVERSION)GetProcAddress(GetModuleHandleA("kernel32"), "GetVersion")) != NULL) { - DWORD dwVersion; - - PRINT(("WASAPI: getting Windows version with GetVersion()\n")); - - dwVersion = fnGetVersion(); + DWORD dwVersion = fnGetVersion(); dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); if (dwVersion < 0x80000000) dwBuild = (DWORD)(HIWORD(dwVersion)); + + PRINT(("WASAPI: getting Windows version with GetVersion(): major=%d, minor=%d, build=%d\n", dwMajorVersion, dwMinorVersion, dwBuild)); } } @@ -2319,9 +2319,16 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd PaWasapiHostApiRepresentation *paWasapi; #ifndef PA_WINRT + // Fail safely for any Windows version below Windows Vista + if (GetWindowsVersion() == WINDOWS_UNKNOWN) + { + PRINT(("WASAPI: Unsupported Windows version!\n")); + return paNoError; + } + if (!SetupAVRT()) { - PRINT(("WASAPI: No AVRT! (not VISTA?)\n")); + PRINT(("WASAPI: avrt.dll missing! Windows integrity broken?\n")); return paNoError; } #endif @@ -2349,11 +2356,11 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd // Fill basic interface info *hostApi = &paWasapi->inheritedHostApiRep; - (*hostApi)->info.structVersion = 1; - (*hostApi)->info.type = paWASAPI; - (*hostApi)->info.name = "Windows WASAPI"; + (*hostApi)->info.structVersion = 1; + (*hostApi)->info.type = paWASAPI; + (*hostApi)->info.name = "Windows WASAPI"; (*hostApi)->info.deviceCount = 0; - (*hostApi)->info.defaultInputDevice = paNoDevice; + (*hostApi)->info.defaultInputDevice = paNoDevice; (*hostApi)->info.defaultOutputDevice = paNoDevice; (*hostApi)->Terminate = Terminate; (*hostApi)->OpenStream = OpenStream; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9c8054b..5f0ad96 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,55 +1,59 @@ # Test projects # Use the macro to add test projects -ADD_TEST(pa_minlat) -ADD_TEST(patest1) -ADD_TEST(patest_buffer) -ADD_TEST(patest_callbackstop) -ADD_TEST(patest_clip) -ADD_TEST(patest_converters) -ADD_TEST(patest_dither) -IF(PA_USE_DS) - ADD_TEST(patest_dsound_find_best_latency_params) - ADD_TEST(patest_dsound_low_level_latency_params) - ADD_TEST(patest_dsound_surround) -ENDIF() -ADD_TEST(patest_hang) -ADD_TEST(patest_in_overflow) -IF(PA_USE_WASAPI) - ADD_TEST(patest_jack_wasapi) -ENDIF() -ADD_TEST(patest_latency) -ADD_TEST(patest_leftright) -ADD_TEST(patest_longsine) -ADD_TEST(patest_many) -ADD_TEST(patest_maxsines) -ADD_TEST(patest_mono) -ADD_TEST(patest_multi_sine) -ADD_TEST(patest_out_underflow) -ADD_TEST(patest_prime) -ADD_TEST(patest_read_record) -ADD_TEST(patest_ringmix) -ADD_TEST(patest_sine8) -ADD_TEST(patest_sine_channelmaps) -ADD_TEST(patest_sine_formats) -ADD_TEST(patest_sine_srate) -ADD_TEST(patest_sine_time) -ADD_TEST(patest_start_stop) -ADD_TEST(patest_stop) -ADD_TEST(patest_stop_playout) -ADD_TEST(patest_suggested_vs_streaminfo_latency) -ADD_TEST(patest_sync) -ADD_TEST(patest_timing) -ADD_TEST(patest_toomanysines) -ADD_TEST(patest_two_rates) -ADD_TEST(patest_underflow) -ADD_TEST(patest_unplug) -ADD_TEST(patest_wire) -IF(PA_USE_WMME) - ADD_TEST(patest_wmme_find_best_latency_params) - ADD_TEST(patest_wmme_low_level_latency_params) -ENDIF() -ADD_TEST(patest_write_stop) -IF(UNIX) - ADD_TEST(patest_write_stop_hang_illegal) -ENDIF() +add_test(pa_minlat) +add_test(patest1) +add_test(patest_buffer) +add_test(patest_callbackstop) +add_test(patest_clip) +if(LINK_PRIVATE_SYMBOLS) + add_test(patest_converters) +endif() +add_test(patest_dither) +if(DIRECTSOUND) + add_test(patest_dsound_find_best_latency_params) + add_test(patest_dsound_low_level_latency_params) + add_test(patest_dsound_surround) +endif() +add_test(patest_hang) +add_test(patest_in_overflow) +if(WASAPI) + add_test(patest_jack_wasapi) +endif() +add_test(patest_latency) +add_test(patest_leftright) +add_test(patest_longsine) +add_test(patest_many) +add_test(patest_maxsines) +add_test(patest_mono) +add_test(patest_multi_sine) +add_test(patest_out_underflow) +add_test(patest_prime) +add_test(patest_read_record) +add_test(patest_ringmix) +add_test(patest_sine8) +add_test(patest_sine_channelmaps) +add_test(patest_sine_formats) +add_test(patest_sine_srate) +add_test(patest_sine_time) +add_test(patest_start_stop) +add_test(patest_stop) +add_test(patest_stop_playout) +add_test(patest_suggested_vs_streaminfo_latency) +if(LINK_PRIVATE_SYMBOLS) + add_test(patest_sync) +endif() +add_test(patest_timing) +add_test(patest_toomanysines) +add_test(patest_two_rates) +add_test(patest_underflow) +add_test(patest_unplug) +add_test(patest_wire) +if(WMME) + add_test(patest_wmme_find_best_latency_params) + add_test(patest_wmme_low_level_latency_params) +endif() +add_test(patest_write_stop) +if(UNIX) + add_test(patest_write_stop_hang_illegal) +endif()