diff options
Diffstat (limited to '3rdparty/portmidi')
136 files changed, 8956 insertions, 17248 deletions
diff --git a/3rdparty/portmidi/.github/workflows/build.yml b/3rdparty/portmidi/.github/workflows/build.yml new file mode 100644 index 00000000000..351b5cbf00c --- /dev/null +++ b/3rdparty/portmidi/.github/workflows/build.yml @@ -0,0 +1,47 @@ +name: build + +on: + push: + pull_request: + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - name: Ubuntu + os: ubuntu-latest + install_dir: ~/portmidi + cmake_extras: -DCMAKE_BUILD_TYPE=RelWithDebInfo + - name: macOS + os: macos-latest + install_dir: ~/portmidi + cmake_extras: -DCMAKE_BUILD_TYPE=RelWithDebInfo + - name: Windows + os: windows-latest + install_dir: C:\portmidi + cmake_config: --config RelWithDebInfo + + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + steps: + - name: Check out Git repository + uses: actions/checkout@v2 + - name: "[Ubuntu] Install dependencies" + run: sudo apt install -y libasound2-dev + if: runner.os == 'Linux' + - name: Configure + run: cmake -D CMAKE_INSTALL_PREFIX=${{ matrix.install_dir }} ${{ matrix.cmake_extras }} -S . -B build + - name: Build + run: cmake --build build ${{ matrix.cmake_config }} + env: + CMAKE_BUILD_PARALLEL_LEVEL: 2 + - name: Install + run: cmake --install . ${{ matrix.cmake_config }} + working-directory: build + - name: Upload Build Artifact + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.name }} portmidi build + path: ${{ matrix.install_dir }} diff --git a/3rdparty/portmidi/.github/workflows/docs.yml b/3rdparty/portmidi/.github/workflows/docs.yml new file mode 100644 index 00000000000..d0e251b77da --- /dev/null +++ b/3rdparty/portmidi/.github/workflows/docs.yml @@ -0,0 +1,28 @@ +name: Generate Docs + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + doxygen: + name: Doxygen + runs-on: ubuntu-latest + steps: + - name: "Check out repository" + uses: actions/checkout@v2 + + - name: Install Doxygen + run: sudo apt-get update && sudo apt-get install -y --no-install-recommends doxygen + + - name: Generate Documentation + run: doxygen + working-directory: . + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: docs/html diff --git a/3rdparty/portmidi/.gitignore b/3rdparty/portmidi/.gitignore new file mode 100644 index 00000000000..19d66501fee --- /dev/null +++ b/3rdparty/portmidi/.gitignore @@ -0,0 +1,62 @@ +.DS_Store +build*/ +*~ +CMakeCache.txt +CMakeFiles/ +CMakeScripts/ +/portmidi.pc +/x64/ +/Debug/ +/Release/ +/pm_java/pmdefaults/pmdefaults.jar +/pm_java/pmdefaults.sln +/pm_java/pmjni.dir/ +/pm_java/x64/ +portmidi.build/ +cmake_install.cmake +*.xcodeproj/ +/.vs/ +/portmidi.sln +*.vcxproj +*.vcxproj.filters +*.vcxproj.user +/Makefile +/libportmidi.so* +/libportmidi.a +/libportmidi_static.a +/libpmjni.so* +/packaging/PortMidiConfig.cmake +/packaging/PortMidiConfigVersion.cmake +/packaging/portmidi.pc +/pm_common/Makefile +/pm_common/portmidi.dir/ +/pm_java/Makefile +/pm_test/Debug/ +/pm_test/Release/ +/pm_test/Makefile +/pm_test/fastrcv +/pm_test/fastrcv.dir/ +/pm_test/latency +/pm_test/latency.dir/ +/pm_test/midiclock +/pm_test/midiclock.dir/ +/pm_test/midithread +/pm_test/midithread.dir/ +/pm_test/midithru +/pm_test/midithru.dir/ +/pm_test/mm +/pm_test/mm.dir/ +/pm_test/multivirtual +/pm_test/qtest +/pm_test/qtest.dir/ +/pm_test/recvvirtual +/pm_test/sendvirtual +/pm_test/sysex +/pm_test/sysex.dir/ +/pm_test/testio +/pm_test/testio.dir/ +/pm_test/virttest +/pm_test/fast +/pm_test/fast.dir/ +/pm_test/pmlist +/pm_test/pmlist.dir/ diff --git a/3rdparty/portmidi/ALL_BUILD.vcproj b/3rdparty/portmidi/ALL_BUILD.vcproj deleted file mode 100644 index b99ce00bb18..00000000000 --- a/3rdparty/portmidi/ALL_BUILD.vcproj +++ /dev/null @@ -1,128 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="ALL_BUILD" - ProjectGUID="{E1C2664B-91BB-4D4F-868C-433164F81101}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="ALL_BUILD.dir\Debug" - ConfigurationType="10" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=".\pm_common;.\porttime;" - ExceptionHandling="0" - PreprocessorDefinitions="CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories=".\pm_common;.\porttime;" - PreprocessorDefinitions="CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="ALL_BUILD.dir\Release" - ConfigurationType="10" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=".\pm_common;.\porttime;" - ExceptionHandling="0" - PreprocessorDefinitions="CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories=".\pm_common;.\porttime;" - PreprocessorDefinitions="CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - </Configuration> - </Configurations> - <Files> - <File - RelativePath=".\CMakeFiles\ALL_BUILD"> - </File> - <Filter - Name="CMake Rules" - Filter=""> - <File - RelativePath=".\CMakeFiles\ALL_BUILD.rule"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCustomBuildTool" - Description="Build all projects" - CommandLine="" - AdditionalDependencies=".\CMakeFiles\ALL_BUILD.rule" - Outputs=".\CMakeFiles\ALL_BUILD"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCustomBuildTool" - Description="Build all projects" - CommandLine="" - AdditionalDependencies=".\CMakeFiles\ALL_BUILD.rule" - Outputs=".\CMakeFiles\ALL_BUILD"/> - </FileConfiguration> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/CHANGELOG.txt b/3rdparty/portmidi/CHANGELOG.txt index c2a083a5685..fee43309cd0 100644 --- a/3rdparty/portmidi/CHANGELOG.txt +++ b/3rdparty/portmidi/CHANGELOG.txt @@ -1,5 +1,26 @@ /* CHANGELOG FOR PORTMIDI * + * 21Feb22 v2.0.3 Roger Dannenberg + * - this version allows multiple hardware devices to have the same name. + * + * 03Jan22 v2.0.2 Roger Dannenberg + * - many changes for CMake including install support + * - bare-bones Java and PmDefaults support. It runs, but no + * installation. + * + * 16Sep21 Roger Dannenberg + * - Added CreateVirtualInput and CreateVirtualOutput functions (macOS + * & Linux) only. + * - Fix for unicode endpoints on macOS CoreMIDI. + * - Parsing in macOS of realtime message embedded in short messages + * (can this actually happen?) + * - renamed pm_test/test.c to pm_test/testio.c + * - with this release, pm_java, pm_csharp, pm_cl, pm_python, pm_qt + * are marked as "legacy code" and README.txt's refer to other + * projects. I had hoped for "one-stop shopping" for language + * bindings, but developers decided to move work to independent + * repositories. Maybe that's better. + * * 19Oct09 Roger Dannenberg * - Changes dynamic library names from portmidi_d to portmidi to * be backward-compatible with programs expecting a library by diff --git a/3rdparty/portmidi/CMakeLists.txt b/3rdparty/portmidi/CMakeLists.txt index 4919b78df62..650fd943510 100644 --- a/3rdparty/portmidi/CMakeLists.txt +++ b/3rdparty/portmidi/CMakeLists.txt @@ -1,77 +1,183 @@ # portmidi -# Roger B. Dannenberg -# 20 Sep 2009 - -cmake_minimum_required(VERSION 2.6) - -if(UNIX) - # allow user to set Release or Debug - set(CMAKE_BUILD_TYPE Release CACHE STRING - "Semicolon-separate list of supported configuration types") - # set default directories but don't override cached values... - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CACHEFILE_DIR}/${CMAKE_BUILD_TYPE} - CACHE STRING "libraries go here") - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CACHEFILE_DIR}/${CMAKE_BUILD_TYPE} - CACHE STRING "libraries go here") - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY - ${CMAKE_CACHEFILE_DIR}/${CMAKE_BUILD_TYPE} - CACHE STRING "executables go here") - -else(UNIX) - # this does not seem to work for xcode: - set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING - "Semicolon-separate list of supported configuration types") -endif(UNIX) - -#set(CMAKE_RELATIVE_PATHS ON CACHE STRING "avoid absolute paths" FORCE) - -# Clear out the built-in C++ compiler and link flags for each of the -# unused configurations. -set(CMAKE_CXX_FLAGS_MINSIZEREL "" CACHE INTERNAL "Unused") -set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "" CACHE INTERNAL "Unused") -set(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "" CACHE INTERNAL "Unused") -set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "" CACHE INTERNAL "Unused") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "Unused") -set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "Unused") -set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "Unused") -set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "Unused") - -set(CMAKE_OSX_ARCHITECTURES i386 ppc x86_64 CACHE STRING "change to needed architecture for a smaller library" FORCE) - -PROJECT(portmidi) - -if(UNIX) - # Problem: if there was an old Debug build and you change - # CMAKE_BUILD_TYPE to Release, then the OUTPUT_DIRECTORY's will - # still be Debug. Try to fix this by checking if the DIRECTORY's - # look wrong, and if so, force them to the defaults: - if(CMAKE_BUILD_TYPE MATCHES "Debug") - set(BAD_DIR "Release") - else(CMAKE_BUILD_TYPE MATCHES "Debug") - set(BAD_DIR "Debug") - endif(CMAKE_BUILD_TYPE MATCHES "Debug") - # use library as reference -- if you give it a non-BAD_DIR location - # then every other path is left alone - if(CMAKE_LIBRARY_OUTPUT_DIRECTORY MATCHES ${BAD_DIR}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY - ${CMAKE_CACHEFILE_DIR}/${CMAKE_BUILD_TYPE} - CACHE STRING "executables go here" FORCE) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY - ${CMAKE_CACHEFILE_DIR}/${CMAKE_BUILD_TYPE} - CACHE STRING "libraries go here" FORCE) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY - ${CMAKE_CACHEFILE_DIR}/${CMAKE_BUILD_TYPE} - CACHE STRING "libraries go here" FORCE) - endif(CMAKE_LIBRARY_OUTPUT_DIRECTORY MATCHES ${BAD_DIR}) -endif(UNIX) +# Roger B. Dannenberg (and others) +# Sep 2009 - 2021 + +cmake_minimum_required(VERSION 3.21) +# (ALSA::ALSA new in 3.12 and used in pm_common/CMakeLists.txt) +# Some Java stuff failed on 3.17 but works with 3.20+ + +cmake_policy(SET CMP0091 NEW) # enables MSVC_RUNTIME_LIBRARY target property + +# Previously, PortMidi versions were simply SVN commit version numbers. +# Versions are now in the form x.y.z +# Changed 1.0 to 2.0 because API is extended with virtual ports: +set(SOVERSION "2") +set(VERSION "2.0.3") + +project(portmidi VERSION "${VERSION}" + DESCRIPTION "Cross-Platform MIDI IO") + +set(LIBRARY_SOVERSION "${SOVERSION}") +set(LIBRARY_VERSION "${VERSION}") + +option(BUILD_SHARED_LIBS "Build shared libraries" ON) + +option(PM_USE_STATIC_RUNTIME + "Use MSVC static runtime. Only applies when BUILD_SHARED_LIBS is OFF" + ON) + +# MSVCRT_DLL is used to construct the MSVC_RUNTIME_LIBRARY property +# (see pm_common/CMakeLists.txt and pm_test/CMakeLists.txt) +if(PM_USE_STATIC_RUNTIME AND NOT BUILD_SHARED_LIBS) + set(MSVCRT_DLL "") +else() + set(MSVCRT_DLL "DLL") +endif() + +# Always build with position-independent code (-fPIC) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9 CACHE STRING + "make for this OS version or higher") + +# PM_ACTUAL_LIB_NAME is in this scope -- see pm_common/CMakeLists.txt +# PM_NEEDED_LIBS is in this scope -- see pm_common/CMakeLists.txt + +include(GNUInstallDirs) + +# Build Types +# credit: http://cliutils.gitlab.io/modern-cmake/chapters/features.html +set(DEFAULT_BUILD_TYPE "Release") +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS + "Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified.") + set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE + STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Release" "MinSizeRel" "RelWithDebInfo") +endif() + +# where to put libraries? Everything goes here in this directory +# (or Debug or Release, depending on the OS) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +option(BUILD_PMDEFAULTS + "build the legacy Java application PmDefaults" OFF) +option(BUILD_JAVA_NATIVE_INTERFACE + "build the Java PortMidi interface library" OFF) + +# Defines are used in both portmidi (in pm_common/) and pmjni (in pm_java), +# so define them here to be inherited by both libraries. +# +# PortMidi software architecture supports multiple system API's to lower- +# level MIDI drivers, e.g. PMNULL (no drivers), Jack (but not supported yet), +# and sndio (BSD, not supported yet). Interfaces are selected by defining, +# e.g., PMALSA. (In principle, we should require PMCOREMIDI (for macOS) +# and PMWINMM (for windows), but these are assumed. +# +if(APPLE OR WIN32) +else(APPLE_OR_WIN32) + set(LINUX_DEFINES "PMALSA" CACHE STRING "must define either PMALSA or PMNULL") + add_compile_definitions(${LINUX_DEFINES}) +endif(APPLE OR WIN32) + +if(BUILD_JAVA_NATIVE_INTERFACE) + message(WARNING + "Java API and PmDefaults program updated 2021, but support has " + "been discontinued. If you need/use this, let developers know.") + set(PMJNI_IF_EXISTS "pmjni") # used by INSTALL below +else(BUILD_JAVA_NATIVE_INTERFACE) + set(PMJNI_IF_EXISTS "") # used by INSTALL below + if(BUILD_PMDEFAULTS) + message(FATAL_ERROR + "Cannot build PM_Defaults program (BUILD_PM_DEFAULTS) without option " + "BUILD_JAVA_NATIVE_INTERFACE") + endif(BUILD_PMDEFAULTS) +endif(BUILD_JAVA_NATIVE_INTERFACE) + + +# Something like this might help if you need to build for a specific cpu type: +# set(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING +# "change to support other architectures" FORCE) include_directories(pm_common porttime) add_subdirectory(pm_common) -add_subdirectory(pm_test) +option(BUILD_PORTMIDI_TESTS + "Build test programs, including midi monitor (mm)" OFF) +if(BUILD_PORTMIDI_TESTS) + add_subdirectory(pm_test) +endif(BUILD_PORTMIDI_TESTS) + +# See note above about Java support (probably) discontinued +if(BUILD_JAVA_NATIVE_INTERFACE) + add_subdirectory(pm_java) +endif(BUILD_JAVA_NATIVE_INTERFACE) + +# Install the libraries and headers (Linux and Mac OS X command line) +INSTALL(TARGETS portmidi ${PMJNI_IF_EXISTS} + EXPORT PortMidiTargets + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + +INSTALL(FILES + pm_common/portmidi.h + pm_common/pmutil.h + porttime/porttime.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# pkgconfig - generate pc file +# See https://cmake.org/cmake/help/latest/command/configure_file.html +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packaging/portmidi.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/packaging/portmidi.pc @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/packaging/portmidi.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + +# CMake config +set(PORTMIDI_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/PortMidi") +install( + EXPORT PortMidiTargets + FILE PortMidiTargets.cmake + NAMESPACE PortMidi:: + DESTINATION "${PORTMIDI_INSTALL_CMAKEDIR}" +) +include(CMakePackageConfigHelpers) +configure_package_config_file(packaging/PortMidiConfig.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/packaging/PortMidiConfig.cmake" + INSTALL_DESTINATION "${PORTMIDI_INSTALL_CMAKEDIR}" +) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/packaging/PortMidiConfigVersion.cmake" + VERSION "${CMAKE_PROJECT_VERSION}" + COMPATIBILITY SameMajorVersion +) +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/packaging/PortMidiConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/packaging/PortMidiConfigVersion.cmake" + DESTINATION "${PORTMIDI_INSTALL_CMAKEDIR}" +) + + -add_subdirectory(pm_dylib) -# Cannot figure out how to make an xcode Java application with CMake -add_subdirectory(pm_java) +# Finding out what CMake is doing is really hard, e.g. COMPILE_FLAGS +# does not include COMPILE_OPTIONS or COMPILE_DEFINTIONS. Thus, the +# following report is probably not complete... +MESSAGE(STATUS "PortMidi Library name: " ${PM_ACTUAL_LIB_NAME}) +MESSAGE(STATUS "Build type: " ${CMAKE_BUILD_TYPE}) +MESSAGE(STATUS "Library Type: " ${LIB_TYPE}) +MESSAGE(STATUS "Compiler flags: " ${CMAKE_CXX_COMPILE_FLAGS}) +get_directory_property(prop COMPILE_DEFINITIONS) +MESSAGE(STATUS "Compile definitions: " ${prop}) +get_directory_property(prop COMPILE_OPTIONS) +MESSAGE(STATUS "Compile options: " ${prop}) +MESSAGE(STATUS "Compiler cxx debug flags: " ${CMAKE_CXX_FLAGS_DEBUG}) +MESSAGE(STATUS "Compiler cxx release flags: " ${CMAKE_CXX_FLAGS_RELEASE}) +MESSAGE(STATUS "Compiler cxx min size flags: " ${CMAKE_CXX_FLAGS_MINSIZEREL}) +MESSAGE(STATUS "Compiler cxx flags: " ${CMAKE_CXX_FLAGS}) diff --git a/3rdparty/portmidi/Doxyfile b/3rdparty/portmidi/Doxyfile index 0adb6829325..95e37080b97 100644 --- a/3rdparty/portmidi/Doxyfile +++ b/3rdparty/portmidi/Doxyfile @@ -1,1472 +1,2682 @@ -# Doxyfile 1.5.5 +# Doxyfile 1.9.2 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project +# doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. PROJECT_NAME = PortMidi -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. -PROJECT_NUMBER = 2.2.x +PROJECT_BRIEF = "Cross-platform MIDI IO library" -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. -OUTPUT_DIRECTORY = . +PROJECT_LOGO = portmusic_logo.png -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../github-portmidi-portmidi_docs + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. CREATE_SUBDIRS = NO -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, -# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, -# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, -# Spanish, Swedish, and Ukrainian. +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. +# The default value is: YES. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief # description. +# The default value is: NO. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. +# The default value is: NO. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. -FULL_PATH_NAMES = NO +FULL_PATH_NAMES = YES -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. JAVADOC_AUTOBRIEF = YES -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. +JAVADOC_BANNER = NO -MULTILINE_CPP_IS_BRIEF = NO +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES +QT_AUTOBRIEF = NO -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. -SEPARATE_MEMBER_PAGES = NO +MULTILINE_CPP_IS_BRIEF = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. -TAB_SIZE = 8 +PYTHON_DOCSTRING = YES -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. -ALIASES = +INHERIT_DOCS = YES -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. -OPTIMIZE_OUTPUT_FOR_C = YES +SEPARATE_MEMBER_PAGES = NO -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:^^" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. +# The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. +# The default value is: NO. CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. -# 1.5.7 -#IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. +# The default value is: NO. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. SUBGROUPING = YES -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols -# 1.5.7 -# SYMBOL_CACHE_SIZE = 0 +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = YES + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. EXTRACT_ALL = NO -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. EXTRACT_PRIVATE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. EXTRACT_STATIC = NO -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. -EXTRACT_LOCAL_CLASSES = NO +EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. EXTRACT_LOCAL_METHODS = NO -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the # documentation. +# The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# The default value is: system dependent. -CASE_SENSE_NAMES = YES +CASE_SENSE_NAMES = NO -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. -HIDE_SCOPE_NAMES = NO +HIDE_SCOPE_NAMES = YES -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. SHOW_INCLUDE_FILES = YES -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. SORT_BRIEF_DOCS = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. SORT_GROUP_NAMES = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. SORT_BY_SCOPE_NAME = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. GENERATE_DEPRECATEDLIST= YES -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if <section_label> ... \endif and \cond <section_label> +# ... \endcond blocks. -ENABLED_SECTIONS = +ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. +# The default value is: YES. SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. -# 1.5.7 -# SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. -# 1.5.7 -# SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command <command> <input-file>, where <command> is the value of -# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. -# 1.5.7 -# LAYOUT_FILE = +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. -QUIET = YES +QUIET = NO -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. -WARN_IF_UNDOCUMENTED = NO +WARN_IF_UNDOCUMENTED = YES -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. +# The default value is: YES. WARN_IF_DOC_ERROR = YES -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC +# The default value is: NO. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. -INPUT = \ - pm_common/portmidi.h \ - pm_common/portmidi.c \ +INPUT =pm_common porttime/porttime.h pm_common/pmutil.h -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# The default value is: UTF-8. INPUT_ENCODING = UTF-8 -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = *.h \ - *.c - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, +# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C +# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.l \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f18 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. EXCLUDE = -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded # from the input. +# The default value is: NO. EXCLUDE_SYMLINKS = NO -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = TRUE, FALSE, PMEXPORT -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). -EXAMPLE_PATH = ./pm_test +EXAMPLE_PATH = -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. -EXAMPLE_PATTERNS = *.cxx \ - *.h \ - *.H \ - *.fl +EXAMPLE_PATTERNS = * -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). -IMAGE_PATH = +IMAGE_PATH = -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command <filter> <input-file>, where <filter> -# is the value of the INPUT_FILTER tag, and <input-file> is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# <filter> <input-file> +# +# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = -INPUT_FILTER = +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. +FILTER_SOURCE_FILES = NO -FILTER_PATTERNS = +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). +FILTER_SOURCE_PATTERNS = -FILTER_SOURCE_FILES = NO +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. -SOURCE_BROWSER = YES +SOURCE_BROWSER = NO -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. -REFERENCED_BY_RELATION = YES +REFERENCED_BY_RELATION = NO -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. -REFERENCES_RELATION = YES +REFERENCES_RELATION = NO -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentstion. +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. VERBATIM_HEADERS = YES +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS +# tag is set to YES then doxygen will add the directory of each input to the +# include path. +# The default value is: YES. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. -COLS_IN_ALPHA_INDEX = 5 +ALPHABETICAL_INDEX = YES -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. -IGNORE_PREFIX = Pm_ +IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = html +HTML_OUTPUT = docs -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a # standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a color-wheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use gray-scales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. - -GENERATE_DOCSET = YES - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be # written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -CHM_FILE = +CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -HHC_LOCATION = +HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. -# 1.5.7 -# CHM_INDEX_ENCODING = +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. -# 1.5.7 -# GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. -# 1.5.7 -# QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# <a href="http://doc.trolltech.com/qthelpproject.html#namespace">Qt Help Project / Namespace</a>. -# 1.5.7 -# QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# <a href="http://doc.trolltech.com/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>. -# 1.5.7 -# QHP_VIRTUAL_FOLDER = doc - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file . -# 1.5.7 -# QHG_LOCATION = - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATOR_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to FRAME, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. Other possible values -# for this tag are: HIERARCHIES, which will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list; -# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which -# disables this behavior completely. For backwards compatibility with previous -# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE -# respectively. +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = YES +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see https://docs.mathjax.org/en/v2.7-latest/tex.html +# #tex-and-latex-extensions): +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use <access key> + S +# (what the <access key> is depends on the OS and browser, but it is typically +# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down +# key> to jump into the search results window, the results can be navigated +# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel +# the search. The filter options can be selected when the cursor is inside the +# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys> +# to select a filter and <Enter> or <escape> to activate or cancel the filter +# option. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using JavaScript. There +# are two flavors of web server based searching depending on the EXTERNAL_SEARCH +# setting. When disabled, doxygen will generate a PHP script for searching and +# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing +# and searching needs to be provided by external tools. See the section +# "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain the +# search results. +# +# Doxygen ships with an example indexer (doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: +# https://xapian.org/). +# +# See the section "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. +EXTERNAL_SEARCH = NO -TREEVIEW_WIDTH = 200 +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will return the search results when EXTERNAL_SEARCH is enabled. +# +# Doxygen ships with an example indexer (doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: +# https://xapian.org/). See the section "External Indexing and Searching" for +# details. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. +# The default file is: searchdata.xml. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH_ID = -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. -# 1.5.7 -# FORMULA_FONTSIZE = 10 +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of +# to a relative location where the documentation can be found. The format is: +# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- -# configuration options related to the LaTeX output +# Configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. +# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. +# The default value is: YES. -GENERATE_LATEX = YES +GENERATE_LATEX = NO -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_OUTPUT = latex -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. +# +# Note that when not enabling USE_PDFLATEX the default is latex when enabling +# USE_PDFLATEX the default is pdflatex and when in the later case latex is +# chosen this is overwritten by pdflatex. For specific output languages the +# default can have been set differently, this depends on the implementation of +# the output language. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_CMD_NAME = + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate +# index for LaTeX. +# Note: This tag is used in the Makefile / make.bat. +# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file +# (.tex). +# The default file is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. -MAKEINDEX_CMD_NAME = makeindex +LATEX_MAKEINDEX_CMD = makeindex -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. +# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. COMPACT_LATEX = NO -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. +# The PAPER_TYPE tag can be used to set the paper type that is used by the +# printer. +# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x +# 14 inches) and executive (7.25 x 10.5 inches). +# The default value is: a4. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names +# that should be included in the LaTeX output. The package can be specified just +# by its name or with the correct syntax as to be used with the LaTeX +# \usepackage command. To get the times font for instance you can specify : +# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times} +# To use the option intlimits with the amsmath package you can specify: +# EXTRA_PACKAGES=[intlimits]{amsmath} +# If left blank no extra packages will be included. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for +# the generated LaTeX document. The header should contain everything until the +# first chapter. If it is left blank doxygen will generate a standard header. It +# is highly recommended to start with a default header using +# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty +# and then modify the file new_header.tex. See also section "Doxygen usage" for +# information on how to generate the default header that doxygen normally uses. +# +# Note: Only use a user-defined header if you know what you are doing! +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. The following +# commands have a special meaning inside the header (and footer): For a +# description of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for +# the generated LaTeX document. The footer should contain everything after the +# last chapter. If it is left blank doxygen will generate a standard footer. See +# LATEX_HEADER for more information on how to generate a default footer and what +# special commands can be used inside the footer. See also section "Doxygen +# usage" for information on how to generate the default footer that doxygen +# normally uses. Note: Only use a user-defined footer if you know what you are +# doing! +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_FOOTER = + +# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# LaTeX style sheets that are included after the standard style sheets created +# by doxygen. Using this option one can overrule certain style aspects. Doxygen +# will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_STYLESHEET = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the LATEX_OUTPUT output +# directory. Note that the files will be copied as-is; there are no commands or +# markers available. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is +# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will +# contain links (just like the HTML output) instead of page references. This +# makes the output suitable for online browsing using a PDF viewer. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. -PAPER_TYPE = a4wide +PDF_HYPERLINKS = YES -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. +# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX +# files. Set this option to YES, to get a higher quality PDF documentation. +# +# See also section LATEX_CMD_NAME for selecting the engine. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. -EXTRA_PACKAGES = +USE_PDFLATEX = YES -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode +# command to the generated LaTeX files. This will instruct LaTeX to keep running +# if errors occur, instead of asking the user for help. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_HEADER = +LATEX_BATCHMODE = NO -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. +# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# index chapters (such as File Index, Compound Index, etc.) in the output. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. -PDF_HYPERLINKS = YES +LATEX_HIDE_INDICES = NO -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. See +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# The default value is: plain. +# This tag requires that the tag GENERATE_LATEX is set to YES. -USE_PDFLATEX = YES +LATEX_BIB_STYLE = plain -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. +# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_BATCHMODE = YES +LATEX_TIMESTAMP = NO -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. +# This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_HIDE_INDICES = NO +LATEX_EMOJI_DIRECTORY = #--------------------------------------------------------------------------- -# configuration options related to the RTF output +# Configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. +# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The +# RTF output is optimized for Word 97 and may not look too pretty with other RTF +# readers/editors. +# The default value is: NO. GENERATE_RTF = NO -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: rtf. +# This tag requires that the tag GENERATE_RTF is set to YES. RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. +# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. COMPACT_RTF = NO -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will +# contain hyperlink fields. The RTF file will contain links (just like the HTML +# output) instead of page references. This makes the output suitable for online +# browsing using Word or some other Word compatible readers that support those +# fields. +# +# Note: WordPad (write) and others do not support links. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# configuration file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. +# +# See also section "Doxygen usage" for information on how to generate the +# default style sheet that doxygen normally uses. +# This tag requires that the tag GENERATE_RTF is set to YES. -RTF_STYLESHEET_FILE = +RTF_STYLESHEET_FILE = -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. +# Set optional variables used in the generation of an RTF document. Syntax is +# similar to doxygen's configuration file. A template extensions file can be +# generated using doxygen -e rtf extensionFile. +# This tag requires that the tag GENERATE_RTF is set to YES. -RTF_EXTENSIONS_FILE = +RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- -# configuration options related to the man page output +# Configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages +# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for +# classes and files. +# The default value is: NO. GENERATE_MAN = NO -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. +# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. A directory man3 will be created inside the directory specified by +# MAN_OUTPUT. +# The default directory is: man. +# This tag requires that the tag GENERATE_MAN is set to YES. MAN_OUTPUT = man -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) +# The MAN_EXTENSION tag determines the extension that is added to the generated +# man pages. In case the manual section does not start with a number, the number +# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is +# optional. +# The default value is: .3. +# This tag requires that the tag GENERATE_MAN is set to YES. MAN_EXTENSION = .3 -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. +# The MAN_SUBDIR tag determines the name of the directory created within +# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by +# MAN_EXTENSION with the initial . removed. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_SUBDIR = + +# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# will generate one additional man file for each entity documented in the real +# man page(s). These additional files only source the real man page, but without +# them the man command would be unable to find the correct page. +# The default value is: NO. +# This tag requires that the tag GENERATE_MAN is set to YES. MAN_LINKS = NO #--------------------------------------------------------------------------- -# configuration options related to the XML output +# Configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. +# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that +# captures the structure of the code including all documentation. +# The default value is: NO. GENERATE_XML = NO -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. +# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: xml. +# This tag requires that the tag GENERATE_XML is set to YES. XML_OUTPUT = xml -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. +# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program +# listings (including syntax highlighting and cross-referencing information) to +# the XML output. Note that enabling this will significantly increase the size +# of the XML output. +# The default value is: YES. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_PROGRAMLISTING = YES + +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO -XML_SCHEMA = +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. +# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files +# that can be used to generate PDF. +# The default value is: NO. -XML_DTD = +GENERATE_DOCBOOK = NO -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. +# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. +# The default directory is: docbook. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. -XML_PROGRAMLISTING = YES +DOCBOOK_OUTPUT = docbook #--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output +# Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. +# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an +# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# the structure of the code including all documentation. Note that this feature +# is still experimental and incomplete at the moment. +# The default value is: NO. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- -# configuration options related to the Perl module output +# Configuration options related to Sqlite3 output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module +# file that captures the structure of the code including all documentation. +# +# Note that this feature is still experimental and incomplete at the moment. +# The default value is: NO. GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. +# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary +# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI +# output from the Perl module output. +# The default value is: NO. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. PERLMOD_LATEX = NO -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. +# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely +# formatted so it can be parsed by a human reader. This is useful if you want to +# understand what is going on. On the other hand, if this tag is set to NO, the +# size of the Perl module output will be much smaller and Perl will parse it +# just the same. +# The default value is: YES. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. PERLMOD_PRETTY = YES -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. +# The names of the make variables in the generated doxyrules.make file are +# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful +# so different doxyrules.make files included by the same Makefile don't +# overwrite each other's variables. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. -PERLMOD_MAKEVAR_PREFIX = +PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- -# Configuration options related to the preprocessor +# Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. +# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all +# C-preprocessor directives found in the sources and include files. +# The default value is: YES. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. +# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# in the source code. If set to NO, only conditional compilation will be +# performed. Macro expansion can be done in a controlled way by setting +# EXPAND_ONLY_PREDEF to YES. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. MACRO_EXPANSION = NO -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then +# the macro expansion is limited to the macros specified with the PREDEFINED and +# EXPAND_AS_DEFINED tags. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. EXPAND_ONLY_PREDEF = NO -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. +# If the SEARCH_INCLUDES tag is set to YES, the include files in the +# INCLUDE_PATH will be searched if a #include is found. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. SEARCH_INCLUDES = YES -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by the +# preprocessor. +# This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = +INCLUDE_PATH = -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will be +# used. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -INCLUDE_FILE_PATTERNS = +INCLUDE_FILE_PATTERNS = -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. +# The PREDEFINED tag can be used to specify one or more macro names that are +# defined before the preprocessor is started (similar to the -D option of e.g. +# gcc). The argument of the tag is a list of macros of the form: name or +# name=definition (no spaces). If the definition and the "=" are omitted, "=1" +# is assumed. To prevent a macro definition from being undefined via #undef or +# recursively expanded use the := operator instead of the = operator. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = FL_DOXYGEN \ - HAVE_CAIRO \ - HAVE_GL \ - HAVE_GL_OVERLAY \ - FL_EXPORT:= +PREDEFINED = -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this +# tag can be used to specify a list of macro names that should be expanded. The +# macro definition that is found in the sources will be used. Use the PREDEFINED +# tag if you want to use a different macro definition that overrules the +# definition found in the source code. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_AS_DEFINED = +EXPAND_AS_DEFINED = -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. +# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# remove all references to function-like macros that are alone on a line, have +# an all uppercase name, and do not end with a semicolon. Such function macros +# are typically used for boiler-plate code, and will confuse the parser if not +# removed. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- -# Configuration::additions related to external references +# Configuration options related to external references #--------------------------------------------------------------------------- -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. +# The TAGFILES tag can be used to specify one or more tag files. For each tag +# file the location of the external documentation should be added. The format of +# a tag file without this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where loc1 and loc2 can be relative or absolute paths or URLs. See the +# section "Linking to external documentation" for more information about the use +# of tag files. +# Note: Each tag file must have a unique name (where the name does NOT include +# the path). If a tag file is not located in the directory in which doxygen is +# run, you must also specify the path to the tagfile here. -TAGFILES = +TAGFILES = -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. +# When a file name is specified after GENERATE_TAGFILE, doxygen will create a +# tag file that is based on the input files it reads. See section "Linking to +# external documentation" for more information about the usage of tag files. -GENERATE_TAGFILE = +GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. +# If the ALLEXTERNALS tag is set to YES, all external class will be listed in +# the class index. If set to NO, only the inherited external classes will be +# listed. +# The default value is: NO. ALLEXTERNALS = NO -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. +# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will be +# listed. +# The default value is: YES. EXTERNAL_GROUPS = YES -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). +# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in +# the related pages index. If set to NO, only the current project's pages will +# be listed. +# The default value is: YES. -PERL_PATH = /usr/bin/perl +EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more +# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram +# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to +# NO turns the diagrams off. Note that this option also works with HAVE_DOT +# disabled, but it is recommended to install and use dot, since it yields more # powerful graphs. +# The default value is: YES. -CLASS_DIAGRAMS = YES +CLASS_DIAGRAMS = NO -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. -MSCGEN_PATH = +DIA_PATH = -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. +# If set to YES the inheritance and collaboration graphs will hide inheritance +# and usage relations if the target is undocumented or is not a class. +# The default value is: YES. HIDE_UNDOC_RELATIONS = YES -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz (see: +# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# Bell Labs. The other options in this section have no effect if this option is +# set to NO +# The default value is: NO. HAVE_DOT = NO -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. -# 1.5.7 -# DOT_FONTNAME = FreeSans - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. -# 1.5.7 -# DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed +# to run in parallel. When set to 0 doxygen will base this on the number of +# processors available in the system. You can set it explicitly to a value +# larger than 0 to get control over the balance between CPU load and processing +# speed. +# Minimum value: 0, maximum value: 32, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NUM_THREADS = 0 + +# When you want a differently looking font in the dot files that doxygen +# generates you can specify the font name using DOT_FONTNAME. You need to make +# sure dot is able to find the font, which can be done by putting it in a +# standard location or by setting the DOTFONTPATH environment variable or by +# setting DOT_FONTPATH to the directory containing the font. +# The default value is: Helvetica. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of +# dot graphs. +# Minimum value: 4, maximum value: 24, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the default font as specified with +# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set +# the path where dot can find it using this tag. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTPATH = + +# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for +# each documented class showing the direct and indirect inheritance relations. +# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. CLASS_GRAPH = YES -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. +# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# graph for each documented class showing the direct and indirect implementation +# dependencies (inheritance, containment, and class references variables) of the +# class with other documented classes. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. COLLABORATION_GRAPH = YES -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies +# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for +# groups, showing the direct groups dependencies. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. GROUP_GRAPHS = YES -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling +# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. UML_LOOK = NO -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. +# If the UML_LOOK tag is enabled, the fields and methods are shown inside the +# class node. If there are many fields or methods and many nodes the graph may +# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the +# number of items for each type to make the size more manageable. Set this to 0 +# for no limit. Note that the threshold may be exceeded by 50% before the limit +# is enforced. So when you set the threshold to 10, up to 15 fields may appear, +# but if the number exceeds 15, the total amount of fields shown is limited to +# 10. +# Minimum value: 0, maximum value: 100, default value: 10. +# This tag requires that the tag UML_LOOK is set to YES. + +UML_LIMIT_NUM_FIELDS = 10 + +# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS +# tag is set to YES, doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# will not generate fields with class member information in the UML graphs. The +# class diagrams will look similar to the default class diagrams but using UML +# notation for the relationships. +# Possible values are: NO, YES and NONE. +# The default value is: NO. +# This tag requires that the tag UML_LOOK is set to YES. + +DOT_UML_DETAILS = NO + +# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters +# to display on a single line. If the actual line length exceeds this threshold +# significantly it will wrapped across multiple lines. Some heuristics are apply +# to avoid ugly line breaks. +# Minimum value: 0, maximum value: 1000, default value: 17. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_WRAP_THRESHOLD = 17 + +# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and +# collaboration graphs will show the relations between templates and their +# instances. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. TEMPLATE_RELATIONS = NO -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. +# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to +# YES then doxygen will generate a graph for each documented file showing the +# direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. INCLUDE_GRAPH = YES -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. +# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are +# set to YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. INCLUDED_BY_GRAPH = YES -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. +# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. Disabling a call graph can be +# accomplished by means of the command \hidecallgraph. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. CALL_GRAPH = NO -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. +# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. Disabling a caller graph can be +# accomplished by means of the command \hidecallergraph. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. CALLER_GRAPH = NO -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. +# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# hierarchy of all classes instead of a textual one. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. GRAPHICAL_HIERARCHY = YES -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. +# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# dependencies a directory has on other directories in a graphical way. The +# dependency relations are determined by the #include relations between the +# files in the directories. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. DIRECTORY_GRAPH = YES -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. For an explanation of the image formats see the section +# output formats in the documentation of the dot tool (Graphviz (see: +# http://www.graphviz.org/)). +# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order +# to make the SVG files visible in IE 9+ (other browsers do not have this +# requirement). +# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and +# png:gdiplus:gdiplus. +# The default value is: png. +# This tag requires that the tag HAVE_DOT is set to YES. DOT_IMAGE_FORMAT = png -# The tag DOT_PATH can be used to specify the path where the dot tool can be +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# +# Note that this requires a modern browser other than Internet Explorer. Tested +# and working are Firefox, Chrome, Safari, and Opera. +# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make +# the SVG files visible. Older versions of IE do not have SVG support. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +INTERACTIVE_SVG = NO + +# The DOT_PATH tag can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the \dotfile +# command). +# This tag requires that the tag HAVE_DOT is set to YES. + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = + +# The DIAFILE_DIRS tag can be used to specify one or more directories that +# contain dia files that are included in the documentation (see the \diafile +# command). + +DIAFILE_DIRS = -DOT_PATH = +# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file. If left blank, it is assumed +# PlantUML is not used or called during a preprocessing step. Doxygen will +# generate a warning when it encounters a \startuml command in this case and +# will not generate output for the diagram. -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). +PLANTUML_JAR_PATH = -DOTFILE_DIRS = +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +PLANTUML_CFG_FILE = + +# When using plantuml, the specified paths are searched for files specified by +# the !include statement in a plantuml block. + +PLANTUML_INCLUDE_PATH = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes +# that will be shown in the graph. If the number of nodes in a graph becomes +# larger than this value, doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that doxygen if the number of direct +# children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that +# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +# Minimum value: 0, maximum value: 10000, default value: 50. +# This tag requires that the tag HAVE_DOT is set to YES. DOT_GRAPH_MAX_NODES = 50 -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs +# generated by dot. A depth value of 3 means that only nodes reachable from the +# root by following a path via at most 3 edges will be shown. Nodes that lay +# further from the root node will be omitted. Note that setting this option to 1 +# or 2 may greatly reduce the computation time needed for large code bases. Also +# note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. +# Minimum value: 0, maximum value: 1000, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. MAX_DOT_GRAPH_DEPTH = 0 -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not seem +# to support this out of the box. +# +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. DOT_TRANSPARENT = NO -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. +# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) support +# this, this feature is disabled by default. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. DOT_MULTI_TARGETS = NO -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. +# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# explaining the meaning of the various boxes and arrows in the dot generated +# graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate +# files that are used to generate the various graphs. +# +# Note: This setting is not only used for dot files but also for msc temporary +# files. +# The default value is: YES. DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/3rdparty/portmidi/README.md b/3rdparty/portmidi/README.md new file mode 100644 index 00000000000..f8cb9106a81 --- /dev/null +++ b/3rdparty/portmidi/README.md @@ -0,0 +1,104 @@ +# PortMidi - Cross-Platform MIDI IO + +This is the canonical release of PortMidi. + +See other repositories within [PortMidi](https://github.com/PortMidi) +for related code and bindings (although currently, not much is here). + +## [Full C API documentation is here.](https://portmidi.github.io/portmidi_docs/) + +## Compiling and Using PortMidi + +Use CMake (or ccmake) to create a Makefile for Linux/BSD or a +project file for Xcode or MS Visual Studio. Use make or an IDE to compile: +``` +cd portmidi # start in the top-level portmidi directory +ccmake . # set any options interactively, type c to configure + # type g to generate a Makefile or IDE project + # type q to quit + # (alternatively, run the CMake GUI and use + # Configure and Generate buttons to build IDE project) +make # compile sources and build PortMidi library + # (alternatively, open project file with your IDE) +sudo make install # if you want to install to your system +``` + +**PmDefaults** is a Java-based program for setting default MIDI +devices. It is necessary if you use `Pm_DefaultInputDeviceID()` or +`Pm_DefaultOutputDeviceID()` to avoid implementing your own device +browsing, selection and preferences in your applications. Enable +`BUILD_PMDEFAULTS` and `BUILD_JAVA_NATIVE_INTERFACE` in ccmake, and +see `pm_java/README.txt` for more information. + +See also notes in `pm_mac/README_MAC.txt`, `pm_win/README_WIN.txt` and +`pm_linux/README_LINUX.txt`. + +## What's New? + +PortMidi has some fixes for Apple M1 cpus as of May 23, 2022. This has not yet +been formally released to allow for further testing, but please use the latest +code if you want to run on an M1. + +PortMidi has some changes in 2021: + + - added Pm_CreateVirtualInput() and Pm_CreateVirtualOutput() functions that allow + applications to create named ports analogous to devices. + + - improvements for macOS CoreMIDI include higher data rates for devices, better + handling of Unicode interface names in addition to virtual device creation. + + - the notion of default devices, Pm_GetDefaultInputDeviceID(), + Pm_GetDefaultOutputDeviceID and the PmDefaults program have fallen into disuse + and are now deprecated. + + - Native Interfaces for Python, Java, Go, Rust, Lua and more seem best left + to individual repos, so support within this repo has been dropped. A Java + interface is still here and probably usable -- let me know if you need it + and/or would like to help bring it up to date. I am happy to help with, + link to, or collaborate in supporting PortMidi for other languages. + +For up-to-date PortMidi for languages other than C/C++, check with +developers. As of 27 Sep 2021, this (and SourceForge) is the only repo with +the features described above. + +# Other Repositories + +PortMidi used to be part of the PortMedia suite, but this repo has been reduced to +mostly just C/C++ code for PortMidi. You will find some other repositories in this PortMidi project +set up for language bindings (volunteers and contributors are invited!). Other code removed from +previous releases of PortMedia include: + +## PortSMF + +A Standard MIDI File (SMF) (and more) library is in the [portsmf repository](https://github.com/PortMidi/portsmf). + +PortSMF is a library for reading/writing/editing Standard MIDI Files. It is +actually much more, with a general representation of events and updates with +properties consisting of attributes and typed values. Familiar properties of +pitch, time, duration, and channel are built into events and updates to make +them faster to access and more compact. + +To my knowledge, PortSMF has the most complete and useful handling of MIDI +tempo tracks. E.g., you can edit notes according to either beat or time, and +you can edit tempo tracks, for example, flattening the tempo while preserving +the beat alignment, preserving the real time while changing the tempo or +stretching the tempo over some interval. + +In addition to Standard MIDI Files, PortSMF supports an ASCII representation +called Allegro. PortSMF and Allegro are used for Audacity Note Tracks. + +## scorealign + +Scorealign used to be part of the PortMedia suite. It is now at the [scorealign repository](https://github.com/rbdannenberg/scorealign). + +Scorealign aligns +audio-to-audio, audio-to-MIDI or MIDI-to-MIDI using dynamic time warping (DTW) +of a computed chromagram representation. There are some added smoothing tricks +to improve performance. This library is written in C and runs substantially +faster than most other implementations, especially those written in MATLAB, +due to the core DTW algorithm. Users should be warned that while chromagrams +are robust features for alignment, they achieve robustness by operating at +fairly high granularity, e.g., durations of around 100ms, which limits +time precision. Other more recent algorithms can doubtless do better, but +be cautious of claims, since it all depends on what assumptions you can +make about the music. diff --git a/3rdparty/portmidi/README.txt b/3rdparty/portmidi/README.txt index 18d951e5f19..aa18b19f8d5 100644 --- a/3rdparty/portmidi/README.txt +++ b/3rdparty/portmidi/README.txt @@ -2,19 +2,16 @@ README for PortMidi Roger B. Dannenberg -VERSION: please use "svn info" to get info. - Documentation for PortMidi is found in pm_common/portmidi.h. +Documentation in HTML is available at portmidi.github.io/portmidi_docs/ Additional documentation: + - README.md (overview, how to build, what's new) - Windows: see pm_win/README_WIN.txt and pm_win/debugging_dlls.txt - Linux: see pm_linux/README_LINUX.txt - Mac OSX: see pm_mac/README_MAC.txt - - Common Lisp: see pm_cl/README_CL.txt - - Eclipse: see portmidi_cdt.zip (this was contributed as is; the dlls here - are now -- Sep 09 -- out of date. What is really needed is a script - to generate this release automatically so we can maintain it.) - - C-Sharp: see pm_csharp.zip (also contributed as is) + - Other Languages: look for other repos at github.com/PortMidi, + and search README.md for pointers to other projects. ---------- some notes on the design of PortMidi ---------- @@ -82,3 +79,10 @@ abruptly terminate the program. The Windows version (and perhaps others) also offers a DEBUG compile-time option. See README_WIN.txt. + +RELEASE + +To make a new release, update VERSION variable in CMakeLists.txt. + +Update CHANGELOG.txt. What's new? + diff --git a/3rdparty/portmidi/ZERO_CHECK.vcproj b/3rdparty/portmidi/ZERO_CHECK.vcproj deleted file mode 100644 index fb17304e882..00000000000 --- a/3rdparty/portmidi/ZERO_CHECK.vcproj +++ /dev/null @@ -1,128 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="ZERO_CHECK" - ProjectGUID="{28779535-7541-4FF5-AC12-FAFD66E894EC}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="ZERO_CHECK.dir\Debug" - ConfigurationType="10" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=".\pm_common;.\porttime;" - ExceptionHandling="0" - PreprocessorDefinitions="CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories=".\pm_common;.\porttime;" - PreprocessorDefinitions="CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="ZERO_CHECK.dir\Release" - ConfigurationType="10" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=".\pm_common;.\porttime;" - ExceptionHandling="0" - PreprocessorDefinitions="CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories=".\pm_common;.\porttime;" - PreprocessorDefinitions="CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - </Configuration> - </Configurations> - <Files> - <File - RelativePath=".\CMakeFiles\ZERO_CHECK"> - </File> - <Filter - Name="CMake Rules" - Filter=""> - <File - RelativePath=".\CMakeFiles\ZERO_CHECK.rule"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCustomBuildTool" - Description="" - CommandLine="" - AdditionalDependencies=".\CMakeFiles\ZERO_CHECK.rule" - Outputs=".\CMakeFiles\ZERO_CHECK"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCustomBuildTool" - Description="" - CommandLine="" - AdditionalDependencies=".\CMakeFiles\ZERO_CHECK.rule" - Outputs=".\CMakeFiles\ZERO_CHECK"/> - </FileConfiguration> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/packaging/PortMidiConfig.cmake.in b/3rdparty/portmidi/packaging/PortMidiConfig.cmake.in new file mode 100644 index 00000000000..a04928a835d --- /dev/null +++ b/3rdparty/portmidi/packaging/PortMidiConfig.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) +if(UNIX AND NOT APPLE AND NOT HAIKU AND (@LINUX_DEFINES@ MATCHES ".*PMALSA.*")) + find_dependency(ALSA) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/PortMidiTargets.cmake") + +check_required_components(PortMidi) diff --git a/3rdparty/portmidi/packaging/portmidi.pc.in b/3rdparty/portmidi/packaging/portmidi.pc.in new file mode 100644 index 00000000000..bc608284b76 --- /dev/null +++ b/3rdparty/portmidi/packaging/portmidi.pc.in @@ -0,0 +1,11 @@ +prefix="@CMAKE_INSTALL_PREFIX@" +exec_prefix="${prefix}" +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ + +Name: @CMAKE_PROJECT_NAME@ +Description: @CMAKE_PROJECT_DESCRIPTION@ +Version: @CMAKE_PROJECT_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -l@CMAKE_PROJECT_NAME@ +Requires.private: @PKGCONFIG_REQUIRES_PRIVATE@ diff --git a/3rdparty/portmidi/pm_cl/README_CL.txt b/3rdparty/portmidi/pm_cl/README_CL.txt deleted file mode 100644 index be4c63591f6..00000000000 --- a/3rdparty/portmidi/pm_cl/README_CL.txt +++ /dev/null @@ -1,104 +0,0 @@ -README_CL.txt for PortMidi -Roger B. Dannenberg -17 Jan 2007 - -This is a Common Lisp interface to PortMidi. - -On Mac OSX, you need to build PortMidi as a dynamic link library -before you can use PortMidi from Common Lisp. - -You can build PortMidi as a dynamic link library by running this: - -cd portmidi -make -F pm_mac/Makefile.osx install-with-xcode - -This is just a shortcut for: - -cd portmidi/pm_mac -sudo xcodebuild -project pm_mac.xcodeproj -configuration Deployment install DSTROOT=/ - -You can check the file and the architecture for which it is built using: - file /usr/local/lib/libportmidi.dylib - -If you've done this install of portmidi, then you should also have - /usr/local/include/portmidi.h -This will be necessary to successfully build the cffi interface below. - -To test PortMidi with Common Lisp, I (RBD) am using SBCL, which I -downloaded from http://prdownloads.sourceforge.net/sbcl. Currently, I use - sbcl-0.9.17-x86-darwin-binary.tar.bz2 -To install this, I unpacked it by just double-clicking in the finder. Then, -from a command window, I became root using "sudo sh", and then typed: -# INSTALL_ROOT=/usr/local -# sh install.sh -# exit - -I also downloaded cffi-061012.tar.gz from - http://common-lisp.net/project/cffi/tarballs/?M=D - -To compile cffi, use the following, where "/Lisp/cffi/" is replaced by -the actual directory of cffi, e.g. - "/Users/rbd/sbcl-0.9.17-x86-darwin/cffi-061012": - -% sbcl -* (require 'asdf) -* (push "/Lisp/cffi/" asdf:*central-registry*) -* (asdf:oos 'asdf:load-op :cffi) -* (quit) - -Download Common Music's portmidi module from cvs and build the c side: -(Replace "/Lisp" with your lisp directory, e.g. -"/Users/rbd/sbcl-0.9.17-x86-darwin". These cvs commands will create -a new directory, portmidi.) - -% cd /Lisp -% export CVSROOT=:pserver:anonymous@commonmusic.cvs.sourceforge.net:/cvsroot/commonmusic -% cvs login # press Return at password prompt -% cvs checkout portmidi -% cd portmidi -% ./configure -% make -% cd .. - -Now compile/load the portmidi module just like cffi. Again, change -"/Lisp/cffi/" and "/Lisp/portmidi" to correspond to your local file system. -(Note that /Lisp becomes your lisp directory, and "cffi" becomes your -cffi folder name, e.g. "cffi-061012". - -% sbcl -* (require 'asdf) -* (push "/Lisp/cffi/" asdf:*central-registry*) -* (asdf:oos 'asdf:load-op :cffi) -* (push "/Lisp/portmidi/" asdf:*central-registry*) -* (asdf:oos 'asdf:load-op :portmidi) - -Look in the file /Lisp/portmidi/test.lisp for a test of the lisp interface to -portmidi. For example, while still running sbcl: - -* (pm:portmidi) ; initialize portmidi -* (pt:start) ; start time -* (pt:time) ; get time -* (pprint (pm:GetDeviceInfo)) ; get list of devices -((:ID 0 :NAME "IAC Driver Bus 1" :TYPE :INPUT :OPEN NIL) - (:ID 1 :NAME "IAC Driver Bus 1" :TYPE :OUTPUT :OPEN NIL)) - -Notice that test.lisp assumes MIDI input devices are connected -and uses some hard-wired device numbers, so it may not run -as is without error. - -Since test.lisp uses some Common Music calls, I (RBD) wrote a -simpler test, test-no-cm.lisp, which is in the same folder as -this (README_CL.txt) file. To use it, first check that the -values for outid (4) and inid (1) actually match PortMidi device -id's for output and input devices, and make sure the input -device is a keyboard that can generate a middle-C -- otherwise -the program will hang waiting for input. Run sbcl from this -pm_cl folder, and type: - -(load "test-no-cm.lisp") - -The program pauses frequently by calling (READ), so you -should type t or something, then <RETURN> to continue. - - -(Thanks to Leigh Smith and Rick Taube) diff --git a/3rdparty/portmidi/pm_cl/cffi-portmidi.lisp b/3rdparty/portmidi/pm_cl/cffi-portmidi.lisp deleted file mode 100644 index 4b3ad9c3e00..00000000000 --- a/3rdparty/portmidi/pm_cl/cffi-portmidi.lisp +++ /dev/null @@ -1,384 +0,0 @@ -;;; ********************************************************************** -;;; Copyright (C) 2005 Heinrich Taube, <taube (at) uiuc (dot) edu> -;;; -;;; This program is free software; you can redistribute it and/or -;;; modify it under the terms of the Lisp Lesser Gnu Public License. -;;; See http://www.cliki.net/LLGPL for the text of this agreement. -;;; ********************************************************************** - - -;;; A CFFI interface to Portmidi. Should run in most Common Lisp -;;; implementations on Linux, OS X and Windows. For information about -;;; CFFI see http://common-lisp.net/project/cffi/ - -(in-package :cl-user) - -(defvar *libportmidi* - (let ((type #+(or darwin macos macosx) "dylib" - #+(or linux linux-target (and unix pc386) freebsd) "so" - #+(or win32 microsoft-32 cygwin) "dll") - (paths (list "/usr/lib/" "/usr/local/lib/" *load-pathname*))) - (loop for d in paths - for p = (make-pathname :name "libportmidi" :type type - :defaults d) - when (probe-file p) do (return p) - finally - (error "Library \"portmidi.~A\" not found. Fix *libportmidi*." - type)))) - -;;; linux: guess i need to load porttime.so first (?) osx doesnt seem -;;; to need this lib at all... - -#+(or linux (and clisp unix (not macos))) -(let ((lpt (merge-pathnames "libporttime" *libportmidi*))) - (if (probe-file lpt) - (cffi:load-foreign-library lpt) - (error "Porttime: ~a not found. Fix *libportmidi* path." lpt))) - -;;; load portmidi lib - -(cffi:load-foreign-library *libportmidi*) - -(defpackage :portmidi - (:use :common-lisp) - (:nicknames :pm :pt) - (:shadow :initialize :terminate :time :start :stop :abort - :close :read :write :poll) - (:export :Initialize :Terminate - :HasHostError :GetErrorText :GetHostErrorText - :CountDevices :GetDefaultInputDeviceID - :GetDefaultOutputDeviceID :GetDeviceInfo - :Message :Message.status :Message.data1 :Message.data2 - :Event.message :Event.timestamp - ;; event buffers added to api - :EventBufferNew :EventBufferFree :EventBufferElt - :EventBufferMap - :OpenInput :OpenOutput :SetFilter :SetChannelMask - :Abort :Close :Read :Write :Poll :WriteShort :WriteSysex - ;; filtering constants - :filt-active :filt-sysex :filt-clock :filt-play :filt-f9 - :filt-fd :filt-reset :filt-note :filt-channel-aftertouch - :filt-poly-aftertouch :filt-program :filt-control - :filt-pitchbend :filt-mtc :filt-song-position - :filt-song-select :filt-tune :filt-tick :filt-undefined - :filt-realtime :filt-aftertouch :filt-systemcommon - ;; porttime. - :Start :Stop :Started :Time - ;; initialization insurers added to api - :portmidi :*portmidi* )) - -(in-package :portmidi) - -(cffi:defcstruct pm-device-info - (struct-version :int) - (interf :pointer) - (name :pointer) - (input :int) - (output :int) - (opened :int)) - -(cffi:define-foreign-type pm-message () ':long) -(cffi:define-foreign-type pm-timestamp () ':long) -(cffi:defcstruct pm-event - (message pm-message) - (timestamp pm-timestamp)) -(cffi:define-foreign-type pm-error () ':int) - -(cffi:define-foreign-type port-midi-stream () ':void) -(cffi:define-foreign-type pm-device-id () ':int) -(cffi:define-foreign-type pm-time-proc-ptr () ':pointer) -(cffi:defcfun ("Pm_WriteSysEx" pm-write-sys-ex) pm-error (stream :pointer) (when pm-timestamp) (msg :pointer)) -(cffi:defcfun ("Pm_WriteShort" pm-write-short) pm-error (stream :pointer) (when pm-timestamp) (msg :long)) -(cffi:defcfun ("Pm_Write" pm-write) pm-error (stream :pointer) (buffer :pointer) (length :long)) -(cffi:defcfun ("Pm_Poll" pm-poll) pm-error (stream :pointer)) -(cffi:defcfun ("Pm_Read" pm-read) pm-error (stream :pointer) (buffer :pointer) (length :long)) -(cffi:defcfun ("Pm_Close" pm-close) pm-error (stream :pointer)) -(cffi:defcfun ("Pm_Abort" pm-abort) pm-error (stream :pointer)) -;(cffi:defcfun ("Pm_SetChannelMask" pm-set-channel-mask) pm-error (stream :pointer) (mask :int)) -(cffi:defcfun ("Pm_SetFilter" pm-set-filter) pm-error (stream :pointer) (filters :long)) -(cffi:defcfun ("Pm_OpenOutput" pm-open-output) pm-error (stream :pointer) (output-device pm-device-id) (output-driver-info :pointer) (buffer-size :long) (time-proc pm-time-proc-ptr) (time-info :pointer) (latency :long)) -(cffi:defcfun ("Pm_OpenInput" pm-open-input) pm-error (stream :pointer) (input-device pm-device-id) (input-driver-info :pointer) (buffer-size :long) (time-proc pm-time-proc-ptr) (time-info :pointer)) -(cffi:defcfun ("Pm_GetDeviceInfo" pm-get-device-info) :pointer (id pm-device-id)) -(cffi:defcfun ("Pm_GetDefaultOutputDeviceID" pm-get-default-output-device-id) pm-device-id) -(cffi:defcfun ("Pm_GetDefaultInputDeviceID" pm-get-default-input-device-id) pm-device-id) -(cffi:defcfun ("Pm_CountDevices" pm-count-devices) :int) -(cffi:defcfun ("Pm_GetHostErrorText" pm-get-host-error-text) :void (msg :pointer) (len :unsigned-int)) -(cffi:defcfun ("Pm_GetErrorText" pm-get-error-text) :pointer (errnum pm-error)) -(cffi:defcfun ("Pm_HasHostError" pm-has-host-error) :int (stream :pointer)) -(cffi:defcfun ("Pm_Terminate" pm-terminate) pm-error) -(cffi:defcfun ("Pm_Initialize" pm-initialize) pm-error) - -;;; porttime.h - -(cffi:define-foreign-type pt-error () ':int) -(cffi:define-foreign-type pt-timestamp () ':long) -(cffi:defcfun ("Pt_Start" pt-start) pt-error (a :int) (b :pointer) (c :pointer)) -(cffi:defcfun ("Pt_Stop" pt-stop) pt-error ) -(cffi:defcfun ("Pt_Started" pt-started) :int) -(cffi:defcfun ("Pt_Time" pt-time) pt-timestamp) - -(defconstant true 1) -(defconstant false 0) -(defconstant pmNoError 0) -(defconstant pmHostError -10000) -(defconstant pm-no-device -1) -(defconstant pm-default-sysex-buffer-size 1024) -(defconstant filt-active 1) -(defconstant filt-sysex 2) -(defconstant filt-clock 4) -(defconstant filt-play 8) -(defconstant filt-f9 16) -(defconstant filt-fd 32) -(defconstant filt-reset 64) -(defconstant filt-note 128) -(defconstant filt-channel-aftertouch 256) -(defconstant filt-poly-aftertouch 512) -(defconstant filt-program 1024) -(defconstant filt-control 2048) -(defconstant filt-pitchbend 4096) -(defconstant filt-mtc 8192) -(defconstant filt-song-position 16384) -(defconstant filt-song-select 32768) -(defconstant filt-tune 65536) -(defconstant filt-tick filt-f9) -(defconstant filt-undefined (logior filt-f9 filt-fd)) -(defconstant filt-realtime (logior filt-active filt-sysex - filt-clock filt-play - filt-undefined filt-reset)) -(defconstant filt-aftertouch (logior filt-channel-aftertouch - filt-poly-aftertouch )) -(defconstant filt-systemcommon (logior filt-mtc filt-song-position - filt-song-select filt-tune)) -(defvar *portmidi* nil) ; t if loaded - -;;; -;;; utils -;;; - -(defvar host-error-text (make-string 256 :initial-element #\*)) - -(defmacro with-pm-error (form) - (let ((v (gensym))) - `(let ((,v ,form)) - (if (not (= ,v pmNoError)) - (if (= ,v pmHostError) - (cffi:with-foreign-string (host-error host-error-text) - (pm-get-host-error-text host-error - (length host-error-text)) - (error "Host error is: ~a" - (cffi:foreign-string-to-lisp host-error))) - (error (cffi:foreign-string-to-lisp - (pm-get-error-text ,v)))) - ,v)))) - -(defun portmidi () - ;; initializer, call before using lib - (or *portmidi* - (progn (pm-initialize) - (setq *portmidi* t)))) - -(defun Message (status data1 data2) - ;; portmidi messages are just unsigneds - (logior (logand (ash data2 16) #xFF0000) - (logand (ash data1 08) #xFF00) - (logand status #xFF))) - -(defun Message.status (m) - (logand m #xFF)) - -(defun Message.data1 (m) - (logand (ash m -08) #xFF)) - -(defun Message.data2 (m) - (logand (ash m -16) #xFF)) - -;;; accessors - -(defun DeviceInfo.interf (ptr) - (cffi:foreign-string-to-lisp - (cffi:foreign-slot-value ptr 'pm-device-info 'interf))) - -(defun DeviceInfo.name (ptr) - (cffi:foreign-string-to-lisp - (cffi:foreign-slot-value ptr 'pm-device-info 'name))) - -(defun DeviceInfo.input (ptr) - (if (= (cffi:foreign-slot-value ptr 'pm-device-info 'input) 0) - nil - t)) - -(defun DeviceInfo.output (ptr) - (if (= (cffi:foreign-slot-value ptr 'pm-device-info 'output) 0) - nil - t)) - -(defun DeviceInfo.opened (ptr) - (if (= (cffi:foreign-slot-value ptr 'pm-device-info 'opened) 0) - nil - t)) - -(defun Event.message (e &optional (v nil vp)) - (if vp - (progn - (setf (cffi:foreign-slot-value e 'pm-event 'message) v) - v) - (cffi:foreign-slot-value e 'pm-event 'message))) - -(defun Event.timestamp (e &optional (v nil vp)) - (if vp - (progn - (setf (cffi:foreign-slot-value e 'pm-event 'timestamp) v) - v) - (cffi:foreign-slot-value e 'pm-event 'timestamp))) - -;;; functions - -(defun Initialize () - (with-pm-error (pm-initialize))) - -(defun terminate () - (with-pm-error (pm-terminate))) - - -(defun HasHostError (pms) - (pm-has-host-error pms)) - -(defun GetErrorText (err) - (pm-get-error-text err)) - -; how do i do this? -;(progn -; (defalien "pm-GetHostErrorText" void (a c-string) (b unsigned-int)) -; (defun GetHostErrorText () -; (pm-GetHostErrorText 256))) - -(defun CountDevices () - (portmidi) - (pm-count-devices )) - -(defun GetDefaultInputDeviceID () - (let ((id (pm-get-default-input-device-id ))) - (if (= id pm-no-device) nil id))) - -(defun GetDefaultOutputDeviceID () - (let ((id (pm-get-default-output-device-id ))) - (if (= id pm-no-device) nil id))) - -;replaced by lispy version end of file. -;(defun GetDeviceInfo (id) (pm-get-device-info id)) - -(defun OpenInput (device bufsiz) - ;; portmidi: timer must be running before opening - (unless (Started) (Start)) - (cffi:with-foreign-object (p1 :pointer) - (let ((err (pm-open-input p1 device (cffi:null-pointer) - bufsiz (cffi:null-pointer) (cffi:null-pointer)))) - (if (= err pmNoError) - (cffi:mem-ref p1 :pointer) - (error (pm-get-error-text err)))))) - -(defun OpenOutput (device bufsiz latency) - (unless (Started) (Start)) - (cffi:with-foreign-object (p1 :pointer) ;(p (* PortMidi)) - (let ((err (pm-open-output p1 device (cffi:null-pointer) - bufsiz (cffi:null-pointer) (cffi:null-pointer) - latency))) - (if (= err pmNoError) - (cffi:mem-ref p1 :pointer) - (error (pm-get-error-text err)))))) - -(defun SetFilter (a filts) - (with-pm-error - (pm-set-filter a filts))) - -;(defun SetChannelMask (pms mask) -; (with-pm-error (pm-set-channel-mask pms mask))) - -(defun Abort (pms) - (with-pm-error (pm-abort pms))) - -(defun Close (pms) - (with-pm-error (pm-close pms))) - -(defun EventBufferFree (buf) - (cffi:foreign-free buf)) - -(defun EventBufferNew (len) - (cffi:foreign-alloc 'pm-event :count len)) - -(defun EventBufferElt (buf i) - ;; buf is POINTER to buf - (cffi:mem-aref buf 'pm-event i)) - -(defun EventBufferSet (buffer index timestamp message) - (setf (cffi:foreign-slot-value - (cffi:mem-aref buffer 'pm-event index) 'pm-event 'timestamp) - timestamp) - (setf (cffi:foreign-slot-value - (cffi:mem-aref buffer 'pm-event index) 'pm-event 'message) - message) - (values)) - -(defun EventBufferMap (fn buf end) - (loop for i below end - for e = (EventBufferElt buf i) - do (funcall fn (Event.message e) (Event.timestamp e))) - (values)) - -(defun Read (pms *evbuf len) - (let ((res (pm-read pms *evbuf len))) - (if (< res 0) - (error (pm-get-error-text res)) - res))) - -(defun Poll (pms) - (let ((res (pm-poll pms))) - (cond ((= res 0) nil) - ((= res 1) t) - (t (error (pm-get-error-text res)))))) - -(defun Write (pms *evbuf len) - (with-pm-error (pm-write pms *evbuf len))) - -(defun WriteShort (pms when msg) - (with-pm-error (pm-write-short pms when msg))) - -(defun WriteSysex (pms when string) - (cffi:with-foreign-string (ptr string) - (with-pm-error (pm-write-sys-ex pms when ptr)))) - -;;; porttime.h - -(defun Started () - (let ((res (pt-started))) - (if (= res false) nil t))) - -(defun Start () - ;; NB: This has to be called before opening output or input. - ;; it seems that if its called 2x we get an error. - (unless (Started) - (with-pm-error (pt-start 1 (cffi:null-pointer) (cffi:null-pointer)))) - (values)) - -(defun Stop () - (when (Started) - (with-pm-error (pt-stop))) - (values)) - -(defun Time () - (pt-time)) - -(defun GetDeviceInfo (&optional id) - (flet ((getone (id) - (let ((d (pm-get-device-info id))) - (list :id id - :name (DeviceInfo.name d) - :type (if (DeviceInfo.input d) ':input ':output) - :open (DeviceInfo.opened d))))) - ;; make sure lib is initialized before checking devices - (portmidi) - (if id (getone id) - (loop for i below (CountDevices) - collect (getone i))))) - -(pushnew ':portmidi *features*) diff --git a/3rdparty/portmidi/pm_cl/test-no-cm.lisp b/3rdparty/portmidi/pm_cl/test-no-cm.lisp deleted file mode 100644 index fd8527e6298..00000000000 --- a/3rdparty/portmidi/pm_cl/test-no-cm.lisp +++ /dev/null @@ -1,112 +0,0 @@ -;; this is a half-baked sequence of PortMidi calls to test the interface -;; No calls to Common Music are made, hence test-no-cm.lisp - -; setup cffi if it has not been done already -(if (not (boundp '*clpath*)) - (load "setup-pm.lisp")) - -(defun println (s) (print s) (terpri)) - -;; initialize portmidi lib -(pm:portmidi) -;; timer testing -(pt:Start ) -(pt:Started) -(format t "time is ~A, type something~%" (pt:Time)) -(read) -(format t "time is ~A, type something~%" (pt:Time)) -(read) -(pt:Time) -(format t "time is ~A, type something~%" (pt:Time)) - -;; device testing -(pm:CountDevices) -(pprint (pm:GetDeviceInfo )) -(defparameter inid (pm:GetDefaultInputDeviceID )) -(pm:GetDeviceInfo inid) -(defparameter outid (pm:GetDefaultOutputDeviceID )) -(pm:GetDeviceInfo outid) -;; output testing -(defparameter outid 4) ; 4 = my SimpleSynth -(defparameter outdev (pm:OpenOutput outid 100 1000)) -(pm:getDeviceInfo outid) ; :OPEN should be T -;; message tests -(defun pm (m &optional (s t)) - (format s "#<message :op ~2,'0x :ch ~2,'0d :data1 ~3,'0d :data2 ~3,'0d>" - (ash (logand (pm:Message.status m) #xf0) -4) - (logand (pm:Message.status m) #x0f) - (pm:Message.data1 m) - (pm:Message.data2 m))) -(defparameter on (pm:message #b10010000 60 64)) -(terpri) -(pm on) -(pm:Message.status on) -(logand (ash (pm:Message.status on) -4) #x0f) -(pm:Message.data1 on) -(pm:Message.data2 on) -(pm:WriteShort outdev (+ (pm:time) 100) on) -(defparameter off (pm:message #b10000000 60 64)) -(terpri) -(pm off) -(terpri) -(println "type something for note off") -(read) -(pm:WriteShort outdev (+ (pm:time) 100) off) -(println "type something to close output device") -(read) -(pm:Close outdev) -;; event buffer testing -(defparameter buff (pm:EventBufferNew 8)) -(loop for i below 8 for x = (pm:EventBufferElt buff i) - ;; set buffer events - do - (pm:Event.message x (pm:message #b1001000 (+ 60 i) (+ 100 i))) - (pm:Event.timestamp x (* 1000 i))) -(loop for i below 8 for x = (pm:EventBufferElt buff i) - ;; check buffer contents - collect (list (pm:Event.timestamp x) - (pm:Message.data1 (pm:Event.message x)) - (pm:Message.data2 (pm:Event.message x)))) -(pm:EventBufferFree buff) -;; input testing -- requires external midi keyboard -(println (pm:GetDeviceInfo )) -(defparameter inid 1) ; 1 = my external keyboard -(defparameter indev (pm:OpenInput inid 256)) -(pm:GetDeviceInfo inid) ; :OPEN should be T -(pm:SetFilter indev pm:filt-realtime) ; ignore active sensing etc. -(println "poll says:") -(println (pm:Poll indev)) -(println "play midi keyboard and type something") -(read) -;; -;; ...play midi keyboard, then ... -;; -(println "poll says") -(println (pm:Poll indev)) -(defparameter buff (pm:EventBufferNew 32)) -(defparameter num (pm:Read indev buff 32)) -(println "pm:Read gets") -(println num) -(println "input messages:") -(pm:EventBufferMap (lambda (a b) b (terpri) (pm a)) - buff num) -(pm:Poll indev) - -(println "play keyboard, to stop, play middle-C") - -;;; recv testing - -(defparameter pitch 0) -(loop while (/= pitch 60) do - (let ((n (pm:Read indev buff 1))) - (cond ((= n 1) - (pm:EventBufferMap - (lambda (a b) - b (pm a) (terpri) - (setf pitch (pm:Message.data1 a))) - buff n))))) - -(pm:EventBufferFree buff) -(pm:Close indev) - - diff --git a/3rdparty/portmidi/pm_common/CMakeLists.txt b/3rdparty/portmidi/pm_common/CMakeLists.txt index e1710474ae3..062887bc111 100644 --- a/3rdparty/portmidi/pm_common/CMakeLists.txt +++ b/3rdparty/portmidi/pm_common/CMakeLists.txt @@ -1,32 +1,69 @@ -# pm_common +# pm_common/CMakeLists.txt -- how to build portmidi library + +# creates the portmidi library +# exports PM_NEEDED_LIBS to parent. It seems that PM_NEEDED_LIBS for +# Linux should include Thread::Thread and ALSA::ALSA, but these +# are not visible in other CMake files, even though the portmidi +# target is. Therefore, Thread::Thread is replaced by +# CMAKE_THREAD_LIBS_INIT and ALSA::ALSA is replaced by ALSA_LIBRARIES. +# Is there a better way to do this? Maybe this whole file should be +# at the parent level. + +# Support alternative name for static libraries to avoid confusion. +# (In particular, Xcode has automatically converted portmidi.a to +# portmidi.dylib without warning, so using portmidi-static.a eliminates +# this possibility, but default for all libs is "portmidi"): +set(PM_STATIC_LIB_NAME "portmidi" CACHE STRING + "For static builds, the PortMidi library name, e.g. portmidi-static. + Default is portmidi") +set(PM_ACTUAL_LIB_NAME "portmidi") +if(NOT BUILD_SHARED_LIBS) + set(PM_ACTUAL_LIB_NAME ${PM_STATIC_LIB_NAME}) +endif() # set the build directory for libportmidi.a to be in portmidi, not in -# portmidi/pm_common +# portmidi/pm_common. Must be done here BEFORE add_library below. if(APPLE OR WIN32) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) # set the build directory for .dylib libraries set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) - - # the first time CMake configures, save off CMake's built-in flags - if(NOT DEFAULT_DEBUG_FLAGS) - set(DEFAULT_DEBUG_FLAGS ${CMAKE_C_FLAGS_DEBUG} CACHE - STRING "CMake's default debug flags" FORCE) - set(DEFAULT_RELEASE_FLAGS ${CMAKE_C_FLAGS_RELEASE} CACHE - STRING "CMake's default release flags" FORCE) - else(NOT DEFAULT_DEBUG_FLAGS) - message(STATUS "DEFAULT_DEBUG_FLAGS not nil: " ${DEFAULT_DEBUG_FLAGS}) - endif(NOT DEFAULT_DEBUG_FLAGS) -else(APPLE OR WIN32) - set(LINUX_FLAGS "-DPMALSA") endif(APPLE OR WIN32) -if(APPLE) - set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk CACHE - PATH "-isysroot parameter for compiler" FORCE) - set(CMAKE_C_FLAGS "-mmacosx-version-min=10.5" CACHE - STRING "needed in conjunction with CMAKE_OSX_SYSROOT" FORCE) -endif(APPLE) +# we need full paths to sources because they are shared with other targets +# (in particular pmjni). Set PMDIR to the top-level portmidi directory: +get_filename_component(PMDIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) +set(PM_LIB_PUBLIC_SRC ${PMDIR}/pm_common/portmidi.c + ${PMDIR}/pm_common/pmutil.c + ${PMDIR}/porttime/porttime.c) +add_library(portmidi ${PM_LIB_PUBLIC_SRC}) + +# MSVCRT_DLL is "DLL" for shared runtime library, and "" for static: +set_target_properties(portmidi PROPERTIES + VERSION ${LIBRARY_VERSION} + SOVERSION ${LIBRARY_SOVERSION} + OUTPUT_NAME "${PM_ACTUAL_LIB_NAME}" + MSVC_RUNTIME_LIBRARY + "MultiThreaded$<$<CONFIG:Debug>:Debug>${MSVCRT_DLL}" + WINDOWS_EXPORT_ALL_SYMBOLS TRUE) +target_include_directories(portmidi PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>) + + +option(PM_CHECK_ERRORS +"Insert a check for error return values at the end of each PortMidi function. +If an error is encountered, a text message is printed using printf(), the user +is asked to type ENTER, and then exit(-1) is called to clean up and terminate +the program. + +You should not use PM_CHECK_ERRORS if printf() does not work (e.g. this is not +a console application under Windows, or there is no visible console on some +other OS), and you should not use PM_CHECK_ERRORS if you intend to recover +from errors rather than abruptly terminate the program." OFF) +if(PM_CHECK_ERRORS) + target_compile_definitions(portmidi PRIVATE PM_CHECK_ERRORS) +endif(PM_CHECK_ERRORS) macro(prepend_path RESULT PATH) set(${RESULT}) @@ -35,94 +72,79 @@ macro(prepend_path RESULT PATH) endforeach(FILE) endmacro(prepend_path) -set(CMAKE_C_FLAGS_DEBUG - "${DEFAULT_DEBUG_FLAGS} -DPM_CHECK_ERRORS=1 -DDEBUG ${LINUX_FLAGS}" - CACHE STRING "enable extra checks for debugging" FORCE) - -set(CMAKE_C_FLAGS_RELEASE "${DEFAULT_RELEASE_FLAGS} ${LINUX_FLAGS}" - CACHE STRING "flags for release version" FORCE) +# UNIX needs pthread library +if(NOT WIN32) + set(THREADS_PREFER_PTHREAD_FLAG ON) + find_package(Threads REQUIRED) +endif() # first include the appropriate system-dependent file: -if(UNIX) - # add the -g switch for Linux and Mac OS X (not used in Win32) - set (CMAKE_C_FLAGS_DEBUG "-g ${CMAKE_C_FLAGS_DEBUG}" - CACHE STRING "enable extra checks for debugging" FORCE) - if(APPLE) - set(MACSRC pmmacosxcm pmmac readbinaryplist finddefault) - prepend_path(LIBSRC ../pm_mac/ ${MACSRC}) - list(APPEND LIBSRC ../porttime/ptmacosx_mach) - - include_directories(${CMAKE_OSX_SYSROOT}/Developer/Headers/FlatCarbon) - set(FRAMEWORK_PATH ${CMAKE_OSX_SYSROOT}/System/Library/Frameworks) - set(COREAUDIO_LIB "${FRAMEWORK_PATH}/CoreAudio.framework") - set(COREFOUNDATION_LIB "${FRAMEWORK_PATH}/CoreFoundation.framework") - set(COREMIDI_LIB "${FRAMEWORK_PATH}/CoreMIDI.framework") - set(CORESERVICES_LIB "${FRAMEWORK_PATH}/CoreServices.framework") - set(PM_NEEDED_LIBS ${COREAUDIO_LIB} ${COREFOUNDATION_LIB} - ${COREMIDI_LIB} ${CORESERVICES_LIB} - CACHE INTERNAL "") - - set(JAVAVM_LIB "${FRAMEWORK_PATH}/JavaVM.framework") - set(JAVA_INCLUDE_PATHS ${JAVAVM_LIB}/Headers) - message(STATUS "SYSROOT: " ${CMAKE_OSX_SYSROOT}) - else(APPLE) - # LINUX settings... - include(FindJNI) - message(STATUS "JAVA_JVM_LIB_PATH is " ${JAVA_JVM_LIB_PATH}) - message(STATUS "JAVA_INCLUDE_PATH is " ${JAVA_INCLUDE_PATH}) - message(STATUS "JAVA_INCLUDE_PATH2 is " ${JAVA_INCLUDE_PATH2}) - message(STATUS "JAVA_JVM_LIBRARY is " ${JAVA_JVM_LIBRARY}) - set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2}) - # libjvm.so is found relative to JAVA_INCLUDE_PATH: - set(JAVAVM_LIB ${JAVA_JVM_LIBRARY}/libjvm.so) - - set(LINUXSRC pmlinuxalsa pmlinux finddefault) - prepend_path(LIBSRC ../pm_linux/ ${LINUXSRC}) - list(APPEND LIBSRC ../porttime/ptlinux) - - set(PM_NEEDED_LIBS pthread asound) - endif(APPLE) -else(UNIX) - if(WIN32) +if(UNIX AND APPLE) + set(Threads::Threads "" PARENT_SCOPE) + find_library(COREAUDIO_LIBRARY CoreAudio REQUIRED) + find_library(COREFOUNDATION_LIBRARY CoreFoundation REQUIRED) + find_library(COREMIDI_LIBRARY CoreMIDI REQUIRED) + find_library(CORESERVICES_LIBRARY CoreServices REQUIRED) + set(PM_LIB_PRIVATE_SRC + ${PMDIR}/porttime/ptmacosx_mach.c + ${PMDIR}/pm_mac/pmmac.c + ${PMDIR}/pm_mac/pmmacosxcm.c + ${PMDIR}/pm_mac/finddefault.c + ${PMDIR}/pm_mac/readbinaryplist.c) + set(PM_NEEDED_LIBS ${CMAKE_THREAD_LIBS_INIT} ${COREAUDIO_LIBRARY} + ${COREFOUNDATION_LIBRARY} ${COREMIDI_LIBRARY} ${CORESERVICES_LIBRARY} + PARENT_SCOPE) + target_link_libraries(portmidi PRIVATE Threads::Threads ${COREAUDIO_LIBRARY} + ${COREFOUNDATION_LIBRARY} ${COREMIDI_LIBRARY} ${CORESERVICES_LIBRARY}) + # set to CMake default; is this right?: + set_target_properties(portmidi PROPERTIES MACOSX_RPATH ON) +elseif(HAIKU) + set(PM_LIB_PRIVATE_SRC + ${PMDIR}/porttime/pthaiku.cpp + ${PMDIR}/pm_haiku/pmhaiku.cpp + ${PMDIR}/pm_linux/finddefault.c) + set(PM_NEEDED_LIBS be midi midi2 PARENT_SCOPE) + target_link_libraries(portmidi PRIVATE be midi midi2) +elseif(UNIX) + target_compile_definitions(portmidi PRIVATE ${LINUX_FLAGS}) + set(PM_LIB_PRIVATE_SRC + ${PMDIR}/porttime/ptlinux.c + ${PMDIR}/pm_linux/pmlinux.c + ${PMDIR}/pm_linux/pmlinuxnull.c + ${PMDIR}/pm_linux/finddefault.c) + if(${LINUX_DEFINES} MATCHES ".*PMALSA.*") + # Note that ALSA is not required if PMNULL is defined -- PortMidi will then + # compile without ALSA and report no MIDI devices. Later, PMSNDIO or PMJACK + # might be additional options. + find_package(ALSA REQUIRED) + list(APPEND PM_LIB_PRIVATE_SRC ${PMDIR}/pm_linux/pmlinuxalsa.c) + set(PM_NEEDED_LIBS ${CMAKE_THREAD_LIBS_INIT} ${ALSA_LIBRARIES} PARENT_SCOPE) + target_link_libraries(portmidi PRIVATE Threads::Threads ALSA::ALSA) + set(PKGCONFIG_REQUIRES_PRIVATE "alsa" PARENT_SCOPE) + else() + message(WARNING "No PMALSA, so PortMidi will not use ALSA, " + "and will not find or open MIDI devices.") + set(PM_NEEDED_LIBS ${CMAKE_THREAD_LIBS_INIT} PARENT_SCOPE) + target_link_libraries(portmidi PRIVATE Threads::Threads) + endif() +elseif(WIN32) + set(PM_LIB_PRIVATE_SRC + ${PMDIR}/porttime/ptwinmm.c + ${PMDIR}/pm_win/pmwin.c + ${PMDIR}/pm_win/pmwinmm.c) + set(PM_NEEDED_LIBS winmm PARENT_SCOPE) + target_link_libraries(portmidi PRIVATE winmm) +# if(NOT BUILD_SHARED_LIBS AND PM_USE_STATIC_RUNTIME) # /MDd is multithread debug DLL, /MTd is multithread debug # /MD is multithread DLL, /MT is multithread. Change to static: - include(../pm_win/static.cmake) - - include(FindJNI) - - set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2}) - # message(STATUS "JAVA_INCLUDE_PATHS: " ${JAVA_INCLUDE_PATHS}) - - set(WINSRC pmwin pmwinmm) - prepend_path(LIBSRC ../pm_win/ ${WINSRC}) - list(APPEND LIBSRC ../porttime/ptwinmm) - set(PM_NEEDED_LIBS winmm.lib) - endif(WIN32) -endif(UNIX) -set(JNI_EXTRA_LIBS ${PM_NEEDED_LIBS} ${JAVA_JVM_LIBRARY}) - -# this completes the list of library sources by adding shared code -list(APPEND LIBSRC pmutil portmidi) - -# now add the shared files to make the complete list of library sources -add_library(portmidi-static ${LIBSRC}) -set_target_properties(portmidi-static PROPERTIES OUTPUT_NAME "portmidi_s") -target_link_libraries(portmidi-static ${PM_NEEDED_LIBS}) +# include(../pm_win/static.cmake) +# endif() +else() + message(FATAL_ERROR "Operating system not supported.") +endif() -# define the jni library -include_directories(${JAVA_INCLUDE_PATHS}) +set(PM_LIB_PUBLIC_SRC ${PM_LIB_PUBLIC_SRC} PARENT_SCOPE) # export to parent +set(PM_LIB_PRIVATE_SRC ${PM_LIB_PRIVATE_SRC} PARENT_SCOPE) # export to parent -set(JNISRC ${LIBSRC} ../pm_java/pmjni/pmjni.c) -add_library(pmjni SHARED ${JNISRC}) -target_link_libraries(pmjni ${JNI_EXTRA_LIBS}) -set_target_properties(pmjni PROPERTIES EXECUTABLE_EXTENSION "jnilib") +target_sources(portmidi PRIVATE ${PM_LIB_PRIVATE_SRC}) -# install the libraries (Linux and Mac OS X command line) -if(UNIX) - INSTALL(TARGETS portmidi-static pmjni - LIBRARY DESTINATION /usr/local/lib - ARCHIVE DESTINATION /usr/local/lib) -# .h files installed by pm_dylib/CMakeLists.txt, so don't need them here -# INSTALL(FILES portmidi.h ../porttime/porttime.h -# DESTINATION /usr/local/include) -endif(UNIX) diff --git a/3rdparty/portmidi/pm_common/pminternal.h b/3rdparty/portmidi/pm_common/pminternal.h index 6b6242026dd..80efbb07f64 100644 --- a/3rdparty/portmidi/pm_common/pminternal.h +++ b/3rdparty/portmidi/pm_common/pminternal.h @@ -1,4 +1,4 @@ -/* pminternal.h -- header for interface implementations */ +/** @file pminternal.h header for PortMidi implementations */ /* this file is included by files that implement library internals */ /* Here is a guide to implementers: @@ -17,6 +17,8 @@ assumptions about pm_fns_type functions are given below. */ +/** @cond INTERNAL - add INTERNAL to Doxygen ENABLED_SECTIONS to include */ + #ifdef __cplusplus extern "C" { #endif @@ -27,8 +29,10 @@ extern int pm_initialized; /* see note in portmidi.c */ void *pm_alloc(size_t s); void pm_free(void *ptr); -/* if an error occurs while opening or closing a midi stream, set these: */ -extern int pm_hosterror; +/* if a host error (an error reported by the host MIDI API that is not + * mapped to a PortMidi error code) occurs in a synchronous operation + * (i.e., not in a callback from another thread) set these: */ +extern int pm_hosterror; /* boolean */ extern char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN]; struct pm_internal_struct; @@ -51,31 +55,30 @@ typedef PmTimestamp (*pm_synchronize_fn)(struct pm_internal_struct *midi); of the open fails */ typedef PmError (*pm_open_fn)(struct pm_internal_struct *midi, void *driverInfo); +typedef PmError (*pm_create_fn)(int is_input, const char *name, + void *driverInfo); +typedef PmError (*pm_delete_fn)(PmDeviceID id); typedef PmError (*pm_abort_fn)(struct pm_internal_struct *midi); /* pm_close_fn should clean up all memory and close the device if any part of the close fails. */ typedef PmError (*pm_close_fn)(struct pm_internal_struct *midi); typedef PmError (*pm_poll_fn)(struct pm_internal_struct *midi); -typedef void (*pm_host_error_fn)(struct pm_internal_struct *midi, char * msg, - unsigned int len); -typedef unsigned int (*pm_has_host_error_fn)(struct pm_internal_struct *midi); +typedef unsigned int (*pm_check_host_error_fn)(struct pm_internal_struct *midi); typedef struct { pm_write_short_fn write_short; /* output short MIDI msg */ pm_begin_sysex_fn begin_sysex; /* prepare to send a sysex message */ pm_end_sysex_fn end_sysex; /* marks end of sysex message */ pm_write_byte_fn write_byte; /* accumulate one more sysex byte */ - pm_write_realtime_fn write_realtime; /* send real-time message within sysex */ + pm_write_realtime_fn write_realtime; /* send real-time msg within sysex */ pm_write_flush_fn write_flush; /* send any accumulated but unsent data */ - pm_synchronize_fn synchronize; /* synchronize portmidi time to stream time */ + pm_synchronize_fn synchronize; /* synchronize PM time to stream time */ pm_open_fn open; /* open MIDI device */ pm_abort_fn abort; /* abort */ pm_close_fn close; /* close device */ pm_poll_fn poll; /* read pending midi events into portmidi buffer */ - pm_has_host_error_fn has_host_error; /* true when device has had host - error message */ - pm_host_error_fn host_error; /* provide text readable host error message - for device (clears and resets) */ + pm_check_host_error_fn check_host_error; /* true when device has had host */ + /* error; sets pm_hosterror and writes message to pm_hosterror_text */ } pm_fns_node, *pm_fns_type; @@ -83,23 +86,25 @@ typedef struct { extern pm_fns_node pm_none_dictionary; typedef struct { - PmDeviceInfo pub; /* some portmidi state also saved in here (for autmatic - device closing (see PmDeviceInfo struct) */ - void *descriptor; /* ID number passed to win32 multimedia API open */ - void *internalDescriptor; /* points to PmInternal device, allows automatic - device closing */ + PmDeviceInfo pub; /* some portmidi state also saved in here (for automatic + device closing -- see PmDeviceInfo struct) */ + int deleted; /* is this is a deleted virtual device? */ + void *descriptor; /* ID number passed to win32 multimedia API open, + * coreMIDI endpoint, etc., representing the device */ + struct pm_internal_struct *pm_internal; /* points to PmInternal device */ + /* when the device is open, allows automatic device closing */ pm_fns_type dictionary; } descriptor_node, *descriptor_type; extern int pm_descriptor_max; -extern descriptor_type descriptors; -extern int pm_descriptor_index; +extern descriptor_type pm_descriptors; +extern int pm_descriptor_len; typedef uint32_t (*time_get_proc_type)(void *time_info); typedef struct pm_internal_struct { - int device_id; /* which device is open (index to descriptors) */ - short write_flag; /* MIDI_IN, or MIDI_OUT */ + int device_id; /* which device is open (index to pm_descriptors) */ + short is_input; /* MIDI IN (true) or MIDI OUT (false) */ PmTimeProcPtr time_proc; /* where to get the time */ void *time_info; /* pass this to get_time() */ @@ -129,7 +134,7 @@ typedef struct pm_internal_struct { PmTimestamp now; /* set by PmWrite to current time */ int first_message; /* initially true, used to run first synchronization */ pm_fns_type dictionary; /* implementation functions */ - void *descriptor; /* system-dependent state */ + void *api_info; /* system-dependent state */ /* the following are used to expedite sysex data */ /* on windows, in debug mode, based on some profiling, these optimizations * cut the time to process sysex bytes from about 7.5 to 0.26 usec/byte, @@ -138,7 +143,7 @@ typedef struct pm_internal_struct { */ unsigned char *fill_base; /* addr of ptr to sysex data */ uint32_t *fill_offset_ptr; /* offset of next sysex byte */ - int32_t fill_length; /* how many sysex bytes to write */ + uint32_t fill_length; /* how many sysex bytes to write */ } PmInternal; @@ -155,8 +160,11 @@ PmTimestamp none_synchronize(PmInternal *midi); PmError pm_fail_fn(PmInternal *midi); PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp); PmError pm_success_fn(PmInternal *midi); -PmError pm_add_device(char *interf, char *name, int input, void *descriptor, - pm_fns_type dictionary); +PmError pm_add_interf(const char *interf, pm_create_fn create_fn, + pm_delete_fn delete_fn); +PmError pm_add_device(const char *interf, const char *name, int is_input, + int is_virtual, void *descriptor, pm_fns_type dictionary); +void pm_undo_add_device(int id); uint32_t pm_read_bytes(PmInternal *midi, const unsigned char *data, int len, PmTimestamp timestamp); void pm_read_short(PmInternal *midi, PmEvent *event); @@ -176,3 +184,4 @@ int pm_find_default_device(char *pattern, int is_input); } #endif +/** @endcond */ diff --git a/3rdparty/portmidi/pm_common/pmjni.vcproj b/3rdparty/portmidi/pm_common/pmjni.vcproj deleted file mode 100644 index b783f3e0c54..00000000000 --- a/3rdparty/portmidi/pm_common/pmjni.vcproj +++ /dev/null @@ -1,161 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="pmjni" - ProjectGUID="{87B548BD-F5CE-4D1F-9181-390966AC5855}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="pmjni.dir\Debug" - ConfigurationType="2" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="1" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\",pmjni_EXPORTS" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../Debug/pmjni.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\",pmjni_EXPORTS"/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\",pmjni_EXPORTS" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib winmm.lib "C:\Program Files\Java\jdk1.6.0_16\include\..\lib\jvm.lib" " - OutputFile="..\Debug\pmjni.dll" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="..\Debug\pmjni.pdb" - GenerateDebugInformation="TRUE" - ImportLibrary="..\Debug\pmjni.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="pmjni.dir\Release" - ConfigurationType="2" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="0" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\",pmjni_EXPORTS" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../Release/pmjni.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\",pmjni_EXPORTS"/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\",pmjni_EXPORTS" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib winmm.lib "C:\Program Files\Java\jdk1.6.0_16\include\..\lib\jvm.lib" " - OutputFile="..\Release\pmjni.dll" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="..\Release\pmjni.pdb" - ImportLibrary="..\Release\pmjni.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_win\pmwin.c"> - </File> - <File - RelativePath="..\pm_win\pmwinmm.c"> - </File> - <File - RelativePath="..\porttime\ptwinmm.c"> - </File> - <File - RelativePath="..\pm_common\pmutil.c"> - </File> - <File - RelativePath="..\pm_common\portmidi.c"> - </File> - <File - RelativePath="..\pm_java\pmjni\pmjni.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_common/pmutil.c b/3rdparty/portmidi/pm_common/pmutil.c index 7d0abe35337..a70fe2fa1f8 100644 --- a/3rdparty/portmidi/pm_common/pmutil.c +++ b/3rdparty/portmidi/pm_common/pmutil.c @@ -8,7 +8,7 @@ #include "pmutil.h" #include "pminternal.h" -#if defined(WIN32) || defined(_MSC_VER) +#ifdef WIN32 #define bzero(addr, siz) memset(addr, 0, siz) #endif diff --git a/3rdparty/portmidi/pm_common/pmutil.h b/3rdparty/portmidi/pm_common/pmutil.h index ef5ee4bf84a..17f6984a0d7 100644 --- a/3rdparty/portmidi/pm_common/pmutil.h +++ b/3rdparty/portmidi/pm_common/pmutil.h @@ -1,31 +1,48 @@ -/* pmutil.h -- some helpful utilities for building midi - applications that use PortMidi +/** @file pmutil.h lock-free queue for building MIDI + applications with PortMidi. + + PortMidi is not reentrant, and locks can suffer from priority + inversion. To support coordination between system callbacks, a + high-priority thread created with PortTime, and the main + application thread, PortMidi uses a lock-free, non-blocking + queue. The queue implementation is not particular to MIDI and is + available for other uses. */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ +/** @defgroup grp_pmutil Lock-free Queue + @{ +*/ + +/** The queue representation is opaque. Declare a queue as PmQueue * */ typedef void PmQueue; -/* - A single-reader, single-writer queue is created by - Pm_QueueCreate(), which takes the number of messages and - the message size as parameters. The queue only accepts - fixed sized messages. Returns NULL if memory cannot be allocated. +/** create a single-reader, single-writer queue. + + @param num_msgs the number of messages the queue can hold + + @param the fixed message size + + @return the allocated and initialized queue, or NULL if memory + cannot be allocated. Allocation uses #pm_malloc(). + + The queue only accepts fixed sized messages. This queue implementation uses the "light pipe" algorithm which operates correctly even with multi-processors and out-of-order memory writes. (see Alexander Dokumentov, "Lock-free Interprocess - Communication," Dr. Dobbs Portal, http://www.ddj.com/, - articleID=189401457, June 15, 2006. This algorithm requires - that messages be translated to a form where no words contain - zeros. Each word becomes its own "data valid" tag. Because of - this translation, we cannot return a pointer to data still in - the queue when the "peek" method is called. Instead, a buffer - is preallocated so that data can be copied there. Pm_QueuePeek() - dequeues a message into this buffer and returns a pointer to - it. A subsequent Pm_Dequeue() will copy from this buffer. + Communication," Dr. Dobbs Portal, http://www.ddj.com/, + articleID=189401457, June 15, 2006. This algorithm requires that + messages be translated to a form where no words contain + zeros. Each word becomes its own "data valid" tag. Because of this + translation, we cannot return a pointer to data still in the queue + when the "peek" method is called. Instead, a buffer is + preallocated so that data can be copied there. Pm_QueuePeek() + dequeues a message into this buffer and returns a pointer to it. A + subsequent Pm_Dequeue() will copy from this buffer. This implementation does not try to keep reader/writer data in separate cache lines or prevent thrashing on cache lines. @@ -36,92 +53,127 @@ typedef void PmQueue; of the cache line, especially if messages are smaller than cache lines. See the Dokumentov article for explanation. - The algorithm is extended to handle "overflow" reporting. To report - an overflow, the sender writes the current tail position to a field. - The receiver must acknowlege receipt by zeroing the field. The sender - will not send more until the field is zeroed. - - Pm_QueueDestroy() destroys the queue and frees its storage. + The algorithm is extended to handle "overflow" reporting. To + report an overflow, the sender writes the current tail position to + a field. The receiver must acknowlege receipt by zeroing the + field. The sender will not send more until the field is zeroed. */ - PMEXPORT PmQueue *Pm_QueueCreate(long num_msgs, int32_t bytes_per_msg); + +/** destroy a queue and free its storage. + + @param queue a queue created by #Pm_QueueCreate(). + + @return pmNoError or an error code. + + Uses #pm_free(). + + */ PMEXPORT PmError Pm_QueueDestroy(PmQueue *queue); -/* - Pm_Dequeue() removes one item from the queue, copying it into msg. - Returns 1 if successful, and 0 if the queue is empty. - Returns pmBufferOverflow if what would have been the next thing - in the queue was dropped due to overflow. (So when overflow occurs, - the receiver can receive a queue full of messages before getting the - overflow report. This protocol ensures that the reader will be +/** remove one message from the queue, copying it into \p msg. + + @param queue a queue created by #Pm_QueueCreate(). + + @param msg address to which the message, if any, is copied. + + @return 1 if successful, and 0 if the queue is empty. Returns + #pmBufferOverflow if what would have been the next thing in the + queue was dropped due to overflow. (So when overflow occurs, the + receiver can receive a queue full of messages before getting the + overflow report. This protocol ensures that the reader will be notified when data is lost due to overflow. */ PMEXPORT PmError Pm_Dequeue(PmQueue *queue, void *msg); +/** insert one message into the queue, copying it from \p msg. -/* - Pm_Enqueue() inserts one item into the queue, copying it from msg. - Returns pmNoError if successful and pmBufferOverflow if the queue was - already full. If pmBufferOverflow is returned, the overflow flag is set. + @param queue a queue created by #Pm_QueueCreate(). + + @param msg address of the message to be enqueued. + + @return #pmNoError if successful and #pmBufferOverflow if the + queue was already full. If #pmBufferOverflow is returned, the + overflow flag is set. */ PMEXPORT PmError Pm_Enqueue(PmQueue *queue, void *msg); +/** test if the queue is full. -/* - Pm_QueueFull() returns non-zero if the queue is full - Pm_QueueEmpty() returns non-zero if the queue is empty + @param queue a queue created by #Pm_QueueCreate(). - Either condition may change immediately because a parallel - enqueue or dequeue operation could be in progress. Furthermore, - Pm_QueueEmpty() is optimistic: it may say false, when due to - out-of-order writes, the full message has not arrived. Therefore, - Pm_Dequeue() could still return 0 after Pm_QueueEmpty() returns - false. On the other hand, Pm_QueueFull() is pessimistic: if it - returns false, then Pm_Enqueue() is guaranteed to succeed. + @return non-zero iff the queue is empty, and @pmBadPtr if \p queue + is NULL. - Error conditions: Pm_QueueFull() returns pmBadPtr if queue is NULL. - Pm_QueueEmpty() returns FALSE if queue is NULL. + The full condition may change immediately because a parallel + dequeue operation could be in progress. The result is + pessimistic: if it returns false (zero) to the single writer, then + #Pm_Enqueue() is guaranteed to succeed. */ PMEXPORT int Pm_QueueFull(PmQueue *queue); + +/** test if the queue is empty. + + @param queue a queue created by #Pm_QueueCreate(). + + @return zero iff the queue is either empty or NULL. + + The empty condition may change immediately because a parallel + enqueue operation could be in progress. Furthermore, the + result is optimistic: it may say false, when due to + out-of-order writes, the full message has not arrived. Therefore, + #Pm_Dequeue() could still return 0 after #Pm_QueueEmpty() returns + false. +*/ PMEXPORT int Pm_QueueEmpty(PmQueue *queue); +/** get a pointer to the item at the head of the queue. -/* - Pm_QueuePeek() returns a pointer to the item at the head of the queue, - or NULL if the queue is empty. The item is not removed from the queue. - Pm_QueuePeek() will not indicate when an overflow occurs. If you want - to get and check pmBufferOverflow messages, use the return value of - Pm_QueuePeek() *only* as an indication that you should call - Pm_Dequeue(). At the point where a direct call to Pm_Dequeue() would - return pmBufferOverflow, Pm_QueuePeek() will return NULL but internally - clear the pmBufferOverflow flag, enabling Pm_Enqueue() to resume - enqueuing messages. A subsequent call to Pm_QueuePeek() - will return a pointer to the first message *after* the overflow. - Using this as an indication to call Pm_Dequeue(), the first call - to Pm_Dequeue() will return pmBufferOverflow. The second call will - return success, copying the same message pointed to by the previous - Pm_QueuePeek(). - - When to use Pm_QueuePeek(): (1) when you need to look at the message + @param queue a queue created by #Pm_QueueCreate(). + + @result a pointer to the head message or NULL if the queue is empty. + + The message is not removed from the queue. #Pm_QueuePeek() will + not indicate when an overflow occurs. If you want to get and check + #pmBufferOverflow messages, use the return value of + #Pm_QueuePeek() *only* as an indication that you should call + #Pm_Dequeue(). At the point where a direct call to #Pm_Dequeue() + would return #pmBufferOverflow, #Pm_QueuePeek() will return NULL, + but internally clear the #pmBufferOverflow flag, enabling + #Pm_Enqueue() to resume enqueuing messages. A subsequent call to + #Pm_QueuePeek() will return a pointer to the first message *after* + the overflow. Using this as an indication to call #Pm_Dequeue(), + the first call to #Pm_Dequeue() will return #pmBufferOverflow. The + second call will return success, copying the same message pointed + to by the previous #Pm_QueuePeek(). + + When to use #Pm_QueuePeek(): (1) when you need to look at the message data to decide who should be called to receive it. (2) when you need to know a message is ready but cannot accept the message. - Note that Pm_QueuePeek() is not a fast check, so if possible, you - might as well just call Pm_Dequeue() and accept the data if it is there. + Note that #Pm_QueuePeek() is not a fast check, so if possible, you + might as well just call #Pm_Dequeue() and accept the data if it is there. */ PMEXPORT void *Pm_QueuePeek(PmQueue *queue); -/* - Pm_SetOverflow() allows the writer (enqueuer) to signal an overflow - condition to the reader (dequeuer). E.g. when transfering data from - the OS to an application, if the OS indicates a buffer overrun, - Pm_SetOverflow() can be used to insure that the reader receives a - pmBufferOverflow result from Pm_Dequeue(). Returns pmBadPtr if queue - is NULL, returns pmBufferOverflow if buffer is already in an overflow - state, returns pmNoError if successfully set overflow state. +/** allows the writer (enqueuer) to signal an overflow + condition to the reader (dequeuer). + + @param queue a queue created by #Pm_QueueCreate(). + + @return #pmNoError if overflow is set, or #pmBadPtr if queue is + NULL, or #pmBufferOverflow if buffer is already in an overflow + state. + + E.g., when transfering data from the OS to an application, if the + OS indicates a buffer overrun, #Pm_SetOverflow() can be used to + insure that the reader receives a #pmBufferOverflow result from + #Pm_Dequeue(). */ PMEXPORT PmError Pm_SetOverflow(PmQueue *queue); +/** @} */ + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/3rdparty/portmidi/pm_common/portmidi-dynamic.vcproj b/3rdparty/portmidi/pm_common/portmidi-dynamic.vcproj deleted file mode 100644 index 42b4a271a20..00000000000 --- a/3rdparty/portmidi/pm_common/portmidi-dynamic.vcproj +++ /dev/null @@ -1,179 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="portmidi-dynamic" - ProjectGUID="{7283FAD1-7415-4061-A19A-FF5C7BCE9306}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="portmidi-dynamic.dir\Debug" - ConfigurationType="2" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="C:\Users\rbd\portmedia\portmidi\pm_common;C:\Users\rbd\portmedia\portmidi\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="3" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\",portmidi_dynamic_EXPORTS" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="C:/Users/rbd/portmedia/portmidi/Debug/portmidi.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="C:\Users\rbd\portmedia\portmidi\pm_common;C:\Users\rbd\portmedia\portmidi\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\",portmidi_dynamic_EXPORTS"/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\",portmidi_dynamic_EXPORTS" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib winmm.lib " - OutputFile="C:\Users\rbd\portmedia\portmidi\Debug\portmidi.dll" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="C:\Users\rbd\portmedia\portmidi\Debug\portmidi.pdb" - GenerateDebugInformation="TRUE" - ImportLibrary="C:\Users\rbd\portmedia\portmidi\Debug\portmidi.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="portmidi-dynamic.dir\Release" - ConfigurationType="2" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="C:\Users\rbd\portmedia\portmidi\pm_common;C:\Users\rbd\portmedia\portmidi\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="2" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\",portmidi_dynamic_EXPORTS" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="C:/Users/rbd/portmedia/portmidi/Release/portmidi.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="C:\Users\rbd\portmedia\portmidi\pm_common;C:\Users\rbd\portmedia\portmidi\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\",portmidi_dynamic_EXPORTS"/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\",portmidi_dynamic_EXPORTS" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib winmm.lib " - OutputFile="C:\Users\rbd\portmedia\portmidi\Release\portmidi.dll" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="C:\Users\rbd\portmedia\portmidi\Release\portmidi.pdb" - ImportLibrary="C:\Users\rbd\portmedia\portmidi\Release\portmidi.lib"/> - </Configuration> - </Configurations> - <Files> - <File - RelativePath="C:\Users\rbd\portmedia\portmidi\pm_common\CMakeLists.txt"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCustomBuildTool" - Description="Building Custom Rule C:/Users/rbd/portmedia/portmidi/pm_common/CMakeLists.txt" - CommandLine=""C:\Program Files\CMake 2.6\bin\cmake.exe" -HC:/Users/rbd/portmedia/portmidi -BC:/Users/rbd/portmedia/portmidi --check-stamp-file CMakeFiles/generate.stamp" - AdditionalDependencies="C:\Users\rbd\portmedia\portmidi\pm_common\CMakeLists.txt;"C:\Program Files\CMake 2.6\share\cmake-2.6\Modules\FindJNI.cmake";C:\Users\rbd\portmedia\portmidi\pm_common\CMakeLists.txt;" - Outputs="CMakeFiles\generate.stamp"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCustomBuildTool" - Description="Building Custom Rule C:/Users/rbd/portmedia/portmidi/pm_common/CMakeLists.txt" - CommandLine=""C:\Program Files\CMake 2.6\bin\cmake.exe" -HC:/Users/rbd/portmedia/portmidi -BC:/Users/rbd/portmedia/portmidi --check-stamp-file CMakeFiles/generate.stamp" - AdditionalDependencies="C:\Users\rbd\portmedia\portmidi\pm_common\CMakeLists.txt;"C:\Program Files\CMake 2.6\share\cmake-2.6\Modules\FindJNI.cmake";C:\Users\rbd\portmedia\portmidi\pm_common\CMakeLists.txt;" - Outputs="CMakeFiles\generate.stamp"/> - </FileConfiguration> - </File> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="C:\Users\rbd\portmedia\portmidi\pm_win\pmwin.c"> - </File> - <File - RelativePath="C:\Users\rbd\portmedia\portmidi\pm_win\pmwinmm.c"> - </File> - <File - RelativePath="C:\Users\rbd\portmedia\portmidi\porttime\ptwinmm.c"> - </File> - <File - RelativePath="C:\Users\rbd\portmedia\portmidi\pm_common\pmutil.c"> - </File> - <File - RelativePath="C:\Users\rbd\portmedia\portmidi\pm_common\portmidi.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_common/portmidi-static.vcproj b/3rdparty/portmidi/pm_common/portmidi-static.vcproj deleted file mode 100644 index 4702b2d1e31..00000000000 --- a/3rdparty/portmidi/pm_common/portmidi-static.vcproj +++ /dev/null @@ -1,141 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="portmidi-static" - ProjectGUID="{2985D5DA-D91E-44E0-924B-E612B6AA33F6}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="portmidi-static.dir\Debug" - ConfigurationType="4" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="1" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../Debug/portmidi_s.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLibrarianTool" - OutputFile="..\Debug\portmidi_s.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="portmidi-static.dir\Release" - ConfigurationType="4" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="0" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../Release/portmidi_s.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;"C:\Program Files\Java\jdk1.6.0_16\include";"C:\Program Files\Java\jdk1.6.0_16\include\win32";" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLibrarianTool" - OutputFile="..\Release\portmidi_s.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_win\pmwin.c"> - </File> - <File - RelativePath="..\pm_win\pmwinmm.c"> - </File> - <File - RelativePath="..\porttime\ptwinmm.c"> - </File> - <File - RelativePath="..\pm_common\pmutil.c"> - </File> - <File - RelativePath="..\pm_common\portmidi.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_common/portmidi.c b/3rdparty/portmidi/pm_common/portmidi.c index 2ed9171e781..7c906dcae42 100644 --- a/3rdparty/portmidi/pm_common/portmidi.c +++ b/3rdparty/portmidi/pm_common/portmidi.c @@ -1,7 +1,5 @@ -#ifdef _MSC_VER - #pragma warning(disable: 4244) // stop warnings about downsize typecasts - #pragma warning(disable: 4018) // stop warnings about signed/unsigned -#endif +/* portmidi.c -- cross-platform MIDI I/O library */ +/* see license.txt for license */ #include "stdlib.h" #include "string.h" @@ -36,12 +34,21 @@ #define is_empty(midi) ((midi)->tail == (midi)->head) -/* this is not static so that pm_init can set it directly if +/* this is not static so that pm_init can set it directly * (see pmmac.c:pm_init()) */ int pm_initialized = FALSE; -int pm_hosterror; +int pm_hosterror; /* boolean */ + +/* if PM_CHECK_ERRORS is enabled, but the caller wants to + * handle an error condition, declare this as extern and + * set to FALSE (this override is provided specifically + * for the test program virttest.c, where pmNameConflict + * is expected in a call to Pm_CreateVirtualInput()): + */ +int pm_check_errors = TRUE; + char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN]; #ifdef PM_CHECK_ERRORS @@ -54,15 +61,16 @@ static void prompt_and_exit(void) { char line[STRING_MAX]; printf("type ENTER..."); - fgets(line, STRING_MAX, stdin); + char *rslt = fgets(line, STRING_MAX, stdin); /* this will clean up open ports: */ exit(-1); } - static PmError pm_errmsg(PmError err) { - if (err == pmHostError) { + if (!pm_check_errors) { /* see pm_check_errors declaration above */ + ; + } else if (err == pmHostError) { /* it seems pointless to allocate memory and copy the string, * so I will do the work of Pm_GetHostErrorText directly */ @@ -87,52 +95,193 @@ system implementation of portmidi interface */ int pm_descriptor_max = 0; -int pm_descriptor_index = 0; -descriptor_type descriptors = NULL; +int pm_descriptor_len = 0; +descriptor_type pm_descriptors = NULL; + +/* interface pm_descriptors are simple: an array of string/fnptr pairs: */ +#define MAX_INTERF 4 +static struct { + const char *interf; + pm_create_fn create_fn; + pm_delete_fn delete_fn; +} pm_interf_list[MAX_INTERF]; + +static int pm_interf_list_len = 0; + + +/* pm_add_interf -- describe an interface to library + * + * This is called at initialization time, once for each + * supported interface (e.g., CoreMIDI). The strings + * are retained but NOT COPIED, so do not destroy them! + * + * The purpose is to register functions that create/delete + * a virtual input or output device. + * + * returns pmInsufficientMemor if interface memory is + * exceeded, otherwise returns pmNoError. + */ +PmError pm_add_interf(const char *interf, pm_create_fn create_fn, + pm_delete_fn delete_fn) +{ + if (pm_interf_list_len >= MAX_INTERF) { + return pmInsufficientMemory; + } + pm_interf_list[pm_interf_list_len].interf = interf; + pm_interf_list[pm_interf_list_len].create_fn = create_fn; + pm_interf_list[pm_interf_list_len].delete_fn = delete_fn; + pm_interf_list_len++; + return pmNoError; +} + + +PmError pm_create_virtual(PmInternal *midi, int is_input, const char *interf, + const char *name, void *device_info) +{ + int i; + if (pm_interf_list_len == 0) { + return pmNotImplemented; + } + if (!interf) { + /* default interface is the first one */ + interf = pm_interf_list[0].interf; + } + for (i = 0; i < pm_interf_list_len; i++) { + if (strcmp(pm_interf_list[i].interf, + interf) == 0) { + int id = (*pm_interf_list[i].create_fn)(is_input, name, + device_info); + pm_descriptors[id].pub.is_virtual = TRUE; + return id; + } + } + return pmInterfaceNotSupported; +} + /* pm_add_device -- describe interface/device pair to library * * This is called at intialization time, once for each - * interface (e.g. DirectSound) and device (e.g. SoundBlaster 1) - * The strings are retained but NOT COPIED, so do not destroy them! + * interface (e.g. DirectSound) and device (e.g. SoundBlaster 1). + * This is also called when user creates a virtual device. + * + * Normally, increasing integer indices are returned. If the device + * is virtual, a linear search is performed to ensure that the name + * is unique. If the name is already taken, the call will fail and + * no device is added. + * + * interf is assumed to be static memory, so it is NOT COPIED and + * NOT FREED. + * name is owned by caller, COPIED if needed, and FREED by PortMidi. + * Caller is resposible for freeing name when pm_add_device returns. * - * returns pmInvalidDeviceId if device memory is exceeded - * otherwise returns pmNoError + * returns pmInvalidDeviceId if device memory is exceeded or a virtual + * device would take the name of an existing device. + * otherwise returns index (portmidi device_id) of the added device */ -PmError pm_add_device(char *interf, char *name, int input, - void *descriptor, pm_fns_type dictionary) { - if (pm_descriptor_index >= pm_descriptor_max) { - // expand descriptors +PmError pm_add_device(const char *interf, const char *name, int is_input, + int is_virtual, void *descriptor, pm_fns_type dictionary) { + /* printf("pm_add_device: %s %s %d %p %p\n", + interf, name, is_input, descriptor, dictionary); */ + int device_id; + PmDeviceInfo *d; + /* if virtual, search for duplicate name or unused ID; otherwise, + * just add a new device at the next integer available: + */ + for (device_id = (is_virtual ? 0 : pm_descriptor_len); + device_id < pm_descriptor_len; device_id++) { + d = &pm_descriptors[device_id].pub; + d->structVersion = 200; + if (strcmp(d->interf, interf) == 0 && strcmp(d->name, name) == 0) { + /* only reuse a name if it is a deleted virtual device with + * a matching direction (input or output) */ + if (pm_descriptors[device_id].deleted && is_input == d->input) { + /* here, we know d->is_virtual because only virtual devices + * can be deleted, and we know is_virtual because we are + * in this loop. + */ + pm_free((void *) d->name); /* reuse this device entry */ + d->name = NULL; + break; + /* name conflict exists if the new device appears to others as + * the same direction (input or output) as the existing device. + * Note that virtual inputs appear to others as outputs and + * vice versa. + * The direction of the new virtual device to others is "output" + * if is_input, i.e., virtual inputs appear to others as outputs. + * The existing device appears to others as "output" if + * (d->is_virtual == d->input) by the same logic. + * The compare will detect if device directions are the same: + */ + } else if (is_input == (d->is_virtual == d->input)) { + return pmNameConflict; + } + } + } + if (device_id >= pm_descriptor_max) { + // expand pm_descriptors descriptor_type new_descriptors = (descriptor_type) pm_alloc(sizeof(descriptor_node) * (pm_descriptor_max + 32)); if (!new_descriptors) return pmInsufficientMemory; - if (descriptors) { - memcpy(new_descriptors, descriptors, + if (pm_descriptors) { + memcpy(new_descriptors, pm_descriptors, sizeof(descriptor_node) * pm_descriptor_max); - free(descriptors); + pm_free(pm_descriptors); } pm_descriptor_max += 32; - descriptors = new_descriptors; + pm_descriptors = new_descriptors; + } + if (device_id == pm_descriptor_len) { + pm_descriptor_len++; /* extending array of pm_descriptors */ } - descriptors[pm_descriptor_index].pub.interf = interf; - descriptors[pm_descriptor_index].pub.name = name; - descriptors[pm_descriptor_index].pub.input = input; - descriptors[pm_descriptor_index].pub.output = !input; + d = &pm_descriptors[device_id].pub; + d->interf = interf; + d->name = pm_alloc(strlen(name) + 1); + if (!d->name) { + return pmInsufficientMemory; + } +#pragma warning(suppress: 4996) // don't use suggested strncpy_s + strcpy(d->name, name); + d->input = is_input; + d->output = !is_input; + d->is_virtual = FALSE; /* caller should set to TRUE if this is virtual */ /* default state: nothing to close (for automatic device closing) */ - descriptors[pm_descriptor_index].pub.opened = FALSE; + d->opened = FALSE; + + pm_descriptors[device_id].deleted = FALSE; /* ID number passed to win32 multimedia API open */ - descriptors[pm_descriptor_index].descriptor = descriptor; + pm_descriptors[device_id].descriptor = descriptor; /* points to PmInternal, allows automatic device closing */ - descriptors[pm_descriptor_index].internalDescriptor = NULL; + pm_descriptors[device_id].pm_internal = NULL; - descriptors[pm_descriptor_index].dictionary = dictionary; - - pm_descriptor_index++; + pm_descriptors[device_id].dictionary = dictionary; - return pmNoError; + return device_id; +} + + +/* Undo a successful call to pm_add_device(). If a new device was + * allocated, it must be the last device in pm_descriptors, so it is + * easy to delete by decrementing the length of pm_descriptors, but + * first free the name (which was copied to the heap). Otherwise, + * the device must be a virtual device that was created previously + * and is in the interior of the array of pm_descriptors. Leave it, + * but mark it as deleted. + */ +void pm_undo_add_device(int id) +{ + /* Clear some fields (not all are strictly necessary) */ + pm_descriptors[id].deleted = TRUE; + pm_descriptors[id].descriptor = NULL; + pm_descriptors[id].pm_internal = NULL; + + if (id == pm_descriptor_len - 1) { + pm_free(pm_descriptors[id].pub.name); + pm_descriptor_len--; + } } @@ -144,7 +293,7 @@ int pm_find_default_device(char *pattern, int is_input) int id = pmNoDevice; int i; /* first parse pattern into name, interf parts */ - char *interf_pref = (char *)""; /* initially assume it is not there */ + char const *interf_pref = ""; /* initially assume it is not there */ char *name_pref = strstr(pattern, ", "); if (name_pref) { /* found separator, adjust the pointer */ @@ -154,7 +303,7 @@ int pm_find_default_device(char *pattern, int is_input) } else { name_pref = pattern; /* whole string is the name pattern */ } - for (i = 0; i < pm_descriptor_index; i++) { + for (i = 0; i < pm_descriptor_len; i++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(i); if (info->input == is_input && strstr(info->name, name_pref) && @@ -173,56 +322,71 @@ portmidi implementation ==================================================================== */ -PMEXPORT int Pm_CountDevices( void ) { +PMEXPORT int Pm_CountDevices(void) +{ Pm_Initialize(); /* no error checking -- Pm_Initialize() does not fail */ - return pm_descriptor_index; + return pm_descriptor_len; } -PMEXPORT const PmDeviceInfo* Pm_GetDeviceInfo( PmDeviceID id ) { +PMEXPORT const PmDeviceInfo* Pm_GetDeviceInfo(PmDeviceID id) +{ Pm_Initialize(); /* no error check needed */ - if (id >= 0 && id < pm_descriptor_index) { - return &descriptors[id].pub; + if (id >= 0 && id < pm_descriptor_len && !pm_descriptors[id].deleted) { + return &pm_descriptors[id].pub; } return NULL; } /* pm_success_fn -- "noop" function pointer */ -PmError pm_success_fn(PmInternal *midi) { +PmError pm_success_fn(PmInternal *midi) +{ return pmNoError; } /* none_write -- returns an error if called */ -PmError none_write_short(PmInternal *midi, PmEvent *buffer) { +PmError none_write_short(PmInternal *midi, PmEvent *buffer) +{ return pmBadPtr; } /* pm_fail_timestamp_fn -- placeholder for begin_sysex and flush */ -PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp) { +PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp) +{ return pmBadPtr; } PmError none_write_byte(PmInternal *midi, unsigned char byte, - PmTimestamp timestamp) { + PmTimestamp timestamp) +{ return pmBadPtr; } /* pm_fail_fn -- generic function, returns error if called */ -PmError pm_fail_fn(PmInternal *midi) { +PmError pm_fail_fn(PmInternal *midi) +{ return pmBadPtr; } -static PmError none_open(PmInternal *midi, void *driverInfo) { +static PmError none_open(PmInternal *midi, void *driverInfo) +{ return pmBadPtr; } -static void none_get_host_error(PmInternal * midi, char * msg, unsigned int len) { + +static void none_get_host_error(PmInternal * midi, char * msg, + unsigned int len) +{ *msg = 0; // empty string } -static unsigned int none_has_host_error(PmInternal * midi) { + +static unsigned int none_check_host_error(PmInternal * midi) +{ return FALSE; } -PmTimestamp none_synchronize(PmInternal *midi) { + +PmTimestamp none_synchronize(PmInternal *midi) +{ return 0; } @@ -238,15 +402,15 @@ pm_fns_node pm_none_dictionary = { none_write_flush, none_synchronize, none_open, - none_abort, + none_abort, none_close, none_poll, - none_has_host_error, - none_get_host_error + none_check_host_error, }; -PMEXPORT const char *Pm_GetErrorText( PmError errnum ) { +PMEXPORT const char *Pm_GetErrorText(PmError errnum) +{ const char *msg; switch(errnum) @@ -255,47 +419,59 @@ PMEXPORT const char *Pm_GetErrorText( PmError errnum ) { msg = ""; break; case pmHostError: - msg = "PortMidi: `Host error'"; + msg = "PortMidi: Host error"; break; case pmInvalidDeviceId: - msg = "PortMidi: `Invalid device ID'"; + msg = "PortMidi: Invalid device ID"; break; case pmInsufficientMemory: - msg = "PortMidi: `Insufficient memory'"; + msg = "PortMidi: Insufficient memory"; break; case pmBufferTooSmall: - msg = "PortMidi: `Buffer too small'"; + msg = "PortMidi: Buffer too small"; break; case pmBadPtr: - msg = "PortMidi: `Bad pointer'"; + msg = "PortMidi: Bad pointer"; break; case pmInternalError: - msg = "PortMidi: `Internal PortMidi Error'"; + msg = "PortMidi: Internal PortMidi Error"; break; case pmBufferOverflow: - msg = "PortMidi: `Buffer overflow'"; + msg = "PortMidi: Buffer overflow"; break; case pmBadData: - msg = "PortMidi: `Invalid MIDI message Data'"; + msg = "PortMidi: Invalid MIDI message Data"; break; case pmBufferMaxSize: - msg = "PortMidi: `Buffer cannot be made larger'"; + msg = "PortMidi: Buffer cannot be made larger"; + break; + case pmNotImplemented: + msg = "PortMidi: Function is not implemented"; + break; + case pmInterfaceNotSupported: + msg = "PortMidi: Interface not supported"; break; - default: - msg = "PortMidi: `Illegal error number'"; + case pmNameConflict: + msg = "PortMidi: Cannot create virtual device: name is taken"; + break; + default: + msg = "PortMidi: Illegal error number"; break; } return msg; } -/* This can be called whenever you get a pmHostError return value. +/* This can be called whenever you get a pmHostError return value + * or TRUE from Pm_HasHostError(). * The error will always be in the global pm_hosterror_text. */ -PMEXPORT void Pm_GetHostErrorText(char * msg, unsigned int len) { +PMEXPORT void Pm_GetHostErrorText(char * msg, unsigned int len) +{ assert(msg); assert(len > 0); if (pm_hosterror) { +#pragma warning(suppress: 4996) // don't use suggested strncpy_s strncpy(msg, (char *) pm_hosterror_text, len); pm_hosterror = FALSE; pm_hosterror_text[0] = 0; /* clear the message; not necessary, but it @@ -307,24 +483,22 @@ PMEXPORT void Pm_GetHostErrorText(char * msg, unsigned int len) { } -PMEXPORT int Pm_HasHostError(PortMidiStream * stream) { +PMEXPORT int Pm_HasHostError(PortMidiStream * stream) +{ if (pm_hosterror) return TRUE; if (stream) { PmInternal * midi = (PmInternal *) stream; - pm_hosterror = (*midi->dictionary->has_host_error)(midi); - if (pm_hosterror) { - midi->dictionary->host_error(midi, pm_hosterror_text, - PM_HOST_ERROR_MSG_LEN); - /* now error message is global */ - return TRUE; - } + return (*midi->dictionary->check_host_error)(midi); } return FALSE; } -PMEXPORT PmError Pm_Initialize( void ) { +PMEXPORT PmError Pm_Initialize(void) +{ if (!pm_initialized) { + pm_descriptor_len = 0; + pm_interf_list_len = 0; pm_hosterror = FALSE; pm_hosterror_text[0] = 0; /* the null string */ pm_init(); @@ -334,16 +508,24 @@ PMEXPORT PmError Pm_Initialize( void ) { } -PMEXPORT PmError Pm_Terminate( void ) { +PMEXPORT PmError Pm_Terminate(void) +{ if (pm_initialized) { pm_term(); - // if there are no devices, descriptors might still be NULL - if (descriptors != NULL) { - free(descriptors); - descriptors = NULL; + /* if there are no devices, pm_descriptors might still be NULL */ + if (pm_descriptors != NULL) { + int i; /* free names copied into pm_descriptors */ + for (i = 0; i < pm_descriptor_len; i++) { + if (pm_descriptors[i].pub.name) { + pm_free(pm_descriptors[i].pub.name); + } + } + pm_free(pm_descriptors); + pm_descriptors = NULL; } - pm_descriptor_index = 0; + pm_descriptor_len = 0; pm_descriptor_max = 0; + pm_interf_list_len = 0; pm_initialized = FALSE; } return pmNoError; @@ -354,7 +536,8 @@ PMEXPORT PmError Pm_Terminate( void ) { /* * returns number of messages actually read, or error code */ -PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length) { +PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length) +{ PmInternal *midi = (PmInternal *) stream; int n = 0; PmError err = pmNoError; @@ -362,9 +545,9 @@ PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length) { /* arg checking */ if(midi == NULL) err = pmBadPtr; - else if(!descriptors[midi->device_id].pub.opened) + else if(!pm_descriptors[midi->device_id].pub.opened) err = pmBadPtr; - else if(!descriptors[midi->device_id].pub.input) + else if(!pm_descriptors[midi->device_id].pub.input) err = pmBadPtr; /* First poll for data in the buffer... * This either simply checks for data, or attempts first to fill the buffer @@ -375,9 +558,7 @@ PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length) { if (err != pmNoError) { if (err == pmHostError) { - midi->dictionary->host_error(midi, pm_hosterror_text, - PM_HOST_ERROR_MSG_LEN); - pm_hosterror = TRUE; + midi->dictionary->check_host_error(midi); } return pm_errmsg(err); } @@ -395,7 +576,7 @@ PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length) { return n; } -PMEXPORT PmError Pm_Poll( PortMidiStream *stream ) +PMEXPORT PmError Pm_Poll(PortMidiStream *stream) { PmInternal *midi = (PmInternal *) stream; PmError err; @@ -404,23 +585,18 @@ PMEXPORT PmError Pm_Poll( PortMidiStream *stream ) /* arg checking */ if(midi == NULL) err = pmBadPtr; - else if (!descriptors[midi->device_id].pub.opened) + else if (!pm_descriptors[midi->device_id].pub.opened) err = pmBadPtr; - else if (!descriptors[midi->device_id].pub.input) + else if (!pm_descriptors[midi->device_id].pub.input) err = pmBadPtr; else err = (*(midi->dictionary->poll))(midi); if (err != pmNoError) { - if (err == pmHostError) { - midi->dictionary->host_error(midi, pm_hosterror_text, - PM_HOST_ERROR_MSG_LEN); - pm_hosterror = TRUE; - } return pm_errmsg(err); } - return !Pm_QueueEmpty(midi->queue); + return (PmError) !Pm_QueueEmpty(midi->queue); } @@ -432,11 +608,6 @@ static PmError pm_end_sysex(PmInternal *midi) { PmError err = (*midi->dictionary->end_sysex)(midi, 0); midi->sysex_in_progress = FALSE; - if (err == pmHostError) { - midi->dictionary->host_error(midi, pm_hosterror_text, - PM_HOST_ERROR_MSG_LEN); - pm_hosterror = TRUE; - } return err; } @@ -445,7 +616,8 @@ static PmError pm_end_sysex(PmInternal *midi) Pm_WriteSysEx all operate a state machine that "outputs" calls to write_short, begin_sysex, write_byte, end_sysex, and write_realtime */ -PMEXPORT PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, int32_t length) +PMEXPORT PmError Pm_Write(PortMidiStream *stream, PmEvent *buffer, + int32_t length) { PmInternal *midi = (PmInternal *) stream; PmError err = pmNoError; @@ -456,9 +628,9 @@ PMEXPORT PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, int32_t leng /* arg checking */ if(midi == NULL) err = pmBadPtr; - else if(!descriptors[midi->device_id].pub.opened) + else if(!pm_descriptors[midi->device_id].pub.opened) err = pmBadPtr; - else if(!descriptors[midi->device_id].pub.output) + else if(!pm_descriptors[midi->device_id].pub.output) err = pmBadPtr; else err = pmNoError; @@ -569,16 +741,15 @@ PMEXPORT PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, int32_t leng err = (*midi->dictionary->write_flush)(midi, 0); pm_write_error: if (err == pmHostError) { - midi->dictionary->host_error(midi, pm_hosterror_text, - PM_HOST_ERROR_MSG_LEN); - pm_hosterror = TRUE; + midi->dictionary->check_host_error(midi); } error_exit: return pm_errmsg(err); } -PMEXPORT PmError Pm_WriteShort(PortMidiStream *stream, PmTimestamp when, PmMessage msg) +PMEXPORT PmError Pm_WriteShort(PortMidiStream *stream, PmTimestamp when, + PmMessage msg) { PmEvent event; @@ -666,79 +837,110 @@ end_of_sysex: -PMEXPORT PmError Pm_OpenInput(PortMidiStream** stream, - PmDeviceID inputDevice, - void *inputDriverInfo, - int32_t bufferSize, - PmTimeProcPtr time_proc, - void *time_info) +PmError pm_create_internal(PmInternal **stream, PmDeviceID device_id, + int is_input, int latency, PmTimeProcPtr time_proc, + void *time_info, int buffer_size) { PmInternal *midi; - PmError err = pmNoError; - pm_hosterror = FALSE; - *stream = NULL; - - /* arg checking */ - if (inputDevice < 0 || inputDevice >= pm_descriptor_index) - err = pmInvalidDeviceId; - else if (!descriptors[inputDevice].pub.input) - err = pmInvalidDeviceId; - else if(descriptors[inputDevice].pub.opened) - err = pmInvalidDeviceId; - - if (err != pmNoError) - goto error_return; - + if (device_id < 0 || device_id >= pm_descriptor_len) { + return pmInvalidDeviceId; + } + if (latency < 0) { /* force a legal value */ + latency = 0; + } /* create portMidi internal data */ midi = (PmInternal *) pm_alloc(sizeof(PmInternal)); *stream = midi; if (!midi) { - err = pmInsufficientMemory; - goto error_return; + return pmInsufficientMemory; } - midi->device_id = inputDevice; - midi->write_flag = FALSE; + midi->device_id = device_id; + midi->is_input = is_input; midi->time_proc = time_proc; + /* if latency != 0, we need a time reference for output. + we always need a time reference for input. + If none is provided, use PortTime library */ + if (time_proc == NULL && (latency != 0 || is_input)) { + if (!Pt_Started()) + Pt_Start(1, 0, 0); + /* time_get does not take a parameter, so coerce */ + midi->time_proc = (PmTimeProcPtr) Pt_Time; + } midi->time_info = time_info; - /* windows adds timestamps in the driver and these are more accurate than - using a time_proc, so do not automatically provide a time proc. Non-win - implementations may want to provide a default time_proc in their - system-specific midi_out_open() method. - */ - if (bufferSize <= 0) bufferSize = 256; /* default buffer size */ - midi->queue = Pm_QueueCreate(bufferSize, (int32_t) sizeof(PmEvent)); - if (!midi->queue) { - /* free portMidi data */ - *stream = NULL; - pm_free(midi); - err = pmInsufficientMemory; - goto error_return; + if (is_input) { + midi->latency = 0; /* unused by input */ + if (buffer_size <= 0) buffer_size = 256; /* default buffer size */ + midi->queue = Pm_QueueCreate(buffer_size, (int32_t) sizeof(PmEvent)); + if (!midi->queue) { + /* free portMidi data */ + *stream = NULL; + pm_free(midi); + return pmInsufficientMemory; + } + } else { + /* if latency zero, output immediate (timestamps ignored) */ + /* if latency < 0, use 0 but don't return an error */ + if (latency < 0) latency = 0; + midi->latency = latency; + midi->queue = NULL; /* unused by output; input needs to allocate: */ } - midi->buffer_len = bufferSize; /* portMidi input storage */ - midi->latency = 0; /* not used */ + midi->buffer_len = buffer_size; /* portMidi input storage */ midi->sysex_in_progress = FALSE; midi->sysex_message = 0; midi->sysex_message_count = 0; - midi->filters = PM_FILT_ACTIVE; + midi->filters = (is_input ? PM_FILT_ACTIVE : 0); midi->channel_mask = 0xFFFF; midi->sync_time = 0; midi->first_message = TRUE; - midi->dictionary = descriptors[inputDevice].dictionary; + midi->api_info = NULL; midi->fill_base = NULL; midi->fill_offset_ptr = NULL; midi->fill_length = 0; - descriptors[inputDevice].internalDescriptor = midi; + midi->dictionary = pm_descriptors[device_id].dictionary; + pm_descriptors[device_id].pm_internal = midi; + return pmNoError; +} + + +PMEXPORT PmError Pm_OpenInput(PortMidiStream** stream, + PmDeviceID inputDevice, + void *inputDriverInfo, + int32_t bufferSize, + PmTimeProcPtr time_proc, + void *time_info) +{ + PmInternal *midi = NULL; + PmError err = pmNoError; + pm_hosterror = FALSE; + *stream = NULL; /* invariant: *stream == midi */ + + /* arg checking */ + if (!pm_descriptors[inputDevice].pub.input) + err = pmInvalidDeviceId; + else if (pm_descriptors[inputDevice].pub.opened) + err = pmInvalidDeviceId; + if (err != pmNoError) + goto error_return; + + /* common initialization of PmInternal structure (midi): */ + err = pm_create_internal(&midi, inputDevice, TRUE, 0, time_proc, + time_info, bufferSize); + *stream = midi; + if (err) { + goto error_return; + } + /* open system dependent input device */ err = (*midi->dictionary->open)(midi, inputDriverInfo); if (err) { *stream = NULL; - descriptors[inputDevice].internalDescriptor = NULL; + pm_descriptors[inputDevice].pm_internal = NULL; /* free portMidi data */ Pm_QueueDestroy(midi->queue); pm_free(midi); } else { /* portMidi input open successful */ - descriptors[inputDevice].pub.opened = TRUE; + pm_descriptors[inputDevice].pub.opened = TRUE; } error_return: /* note: if there is a pmHostError, it is the responsibility @@ -750,12 +952,12 @@ error_return: PMEXPORT PmError Pm_OpenOutput(PortMidiStream** stream, - PmDeviceID outputDevice, - void *outputDriverInfo, - int32_t bufferSize, - PmTimeProcPtr time_proc, - void *time_info, - int32_t latency ) + PmDeviceID outputDevice, + void *outputDriverInfo, + int32_t bufferSize, + PmTimeProcPtr time_proc, + void *time_info, + int32_t latency) { PmInternal *midi; PmError err = pmNoError; @@ -763,62 +965,33 @@ PMEXPORT PmError Pm_OpenOutput(PortMidiStream** stream, *stream = NULL; /* arg checking */ - if (outputDevice < 0 || outputDevice >= pm_descriptor_index) + if (outputDevice < 0 || outputDevice >= pm_descriptor_len) err = pmInvalidDeviceId; - else if (!descriptors[outputDevice].pub.output) + else if (!pm_descriptors[outputDevice].pub.output) err = pmInvalidDeviceId; - else if (descriptors[outputDevice].pub.opened) + else if (pm_descriptors[outputDevice].pub.opened) err = pmInvalidDeviceId; if (err != pmNoError) goto error_return; - /* create portMidi internal data */ - midi = (PmInternal *) pm_alloc(sizeof(PmInternal)); - *stream = midi; - if (!midi) { - err = pmInsufficientMemory; + /* common initialization of PmInternal structure (midi): */ + err = pm_create_internal(&midi, outputDevice, FALSE, latency, time_proc, + time_info, bufferSize); + *stream = midi; + if (err) { goto error_return; } - midi->device_id = outputDevice; - midi->write_flag = TRUE; - midi->time_proc = time_proc; - /* if latency > 0, we need a time reference. If none is provided, - use PortTime library */ - if (time_proc == NULL && latency != 0) { - if (!Pt_Started()) - Pt_Start(1, 0, 0); - /* time_get does not take a parameter, so coerce */ - midi->time_proc = (PmTimeProcPtr) Pt_Time; - } - midi->time_info = time_info; - midi->buffer_len = bufferSize; - midi->queue = NULL; /* unused by output */ - /* if latency zero, output immediate (timestamps ignored) */ - /* if latency < 0, use 0 but don't return an error */ - if (latency < 0) latency = 0; - midi->latency = latency; - midi->sysex_in_progress = FALSE; - midi->sysex_message = 0; /* unused by output */ - midi->sysex_message_count = 0; /* unused by output */ - midi->filters = 0; /* not used for output */ - midi->channel_mask = 0xFFFF; - midi->sync_time = 0; - midi->first_message = TRUE; - midi->dictionary = descriptors[outputDevice].dictionary; - midi->fill_base = NULL; - midi->fill_offset_ptr = NULL; - midi->fill_length = 0; - descriptors[outputDevice].internalDescriptor = midi; + /* open system dependent output device */ err = (*midi->dictionary->open)(midi, outputDriverInfo); if (err) { *stream = NULL; - descriptors[outputDevice].internalDescriptor = NULL; + pm_descriptors[outputDevice].pm_internal = NULL; /* free portMidi data */ pm_free(midi); } else { /* portMidi input open successful */ - descriptors[outputDevice].pub.opened = TRUE; + pm_descriptors[outputDevice].pub.opened = TRUE; } error_return: /* note: system-dependent code must set pm_hosterror and @@ -828,6 +1001,91 @@ error_return: } +static PmError create_virtual_device(const char *name, const char *interf, + void *device_info, int is_input) +{ + PmError err = pmNoError; + int i; + pm_hosterror = FALSE; + + /* arg checking */ + if (!name) { + err = pmInvalidDeviceId; + goto error_return; + } + + Pm_Initialize(); /* just in case */ + + /* create the virtual device */ + if (pm_interf_list_len == 0) { + return pmNotImplemented; + } + if (!interf) { + /* default interface is the first one */ + interf = pm_interf_list[0].interf; + } + /* look up and call the create_fn for interf(ace), e.g. "CoreMIDI" */ + for (i = 0; i < pm_interf_list_len; i++) { + if (strcmp(pm_interf_list[i].interf, interf) == 0) { + int id = (*pm_interf_list[i].create_fn)(is_input, + name, device_info); + /* id could be pmNameConflict or an actual descriptor index */ + if (id >= 0) { + pm_descriptors[id].pub.is_virtual = TRUE; + } + err = id; + goto error_return; + } + } + err = pmInterfaceNotSupported; + +error_return: + /* note: if there is a pmHostError, it is the responsibility + * of the system-dependent code (*midi->dictionary->open)() + * to set pm_hosterror and pm_hosterror_text + */ + return pm_errmsg(err); +} + + +PMEXPORT PmError Pm_CreateVirtualInput(const char *name, + const char *interf, + void *deviceInfo) +{ + return create_virtual_device(name, interf, deviceInfo, TRUE); +} + +PMEXPORT PmError Pm_CreateVirtualOutput(const char *name, const char *interf, + void *deviceInfo) +{ + return create_virtual_device(name, interf, deviceInfo, FALSE); +} + +PmError Pm_DeleteVirtualDevice(PmDeviceID id) +{ + int i; + const char *interf = pm_descriptors[id].pub.interf; + PmError err = pmBadData; /* returned if we cannot find the interface- + * specific delete function */ + /* arg checking */ + if (id < 0 || id >= pm_descriptor_len || + pm_descriptors[id].pub.opened || pm_descriptors[id].deleted) { + return pmInvalidDeviceId; + } + /* delete function pointer is in interfaces list */ + for (i = 0; i < pm_interf_list_len; i++) { + if (strcmp(pm_interf_list[i].interf, interf) == 0) { + err = (*pm_interf_list[i].delete_fn)(id); + break; + } + } + pm_descriptors[id].deleted = TRUE; + /* (pm_internal should already be NULL because !pub.opened) */ + pm_descriptors[id].pm_internal = NULL; + pm_descriptors[id].descriptor = NULL; + return err; +} + PMEXPORT PmError Pm_SetChannelMask(PortMidiStream *stream, int mask) { PmInternal *midi = (PmInternal *) stream; @@ -842,14 +1100,15 @@ PMEXPORT PmError Pm_SetChannelMask(PortMidiStream *stream, int mask) } -PMEXPORT PmError Pm_SetFilter(PortMidiStream *stream, int32_t filters) { +PMEXPORT PmError Pm_SetFilter(PortMidiStream *stream, int32_t filters) +{ PmInternal *midi = (PmInternal *) stream; PmError err = pmNoError; /* arg checking */ if (midi == NULL) err = pmBadPtr; - else if (!descriptors[midi->device_id].pub.opened) + else if (!pm_descriptors[midi->device_id].pub.opened) err = pmBadPtr; else midi->filters = filters; @@ -857,7 +1116,8 @@ PMEXPORT PmError Pm_SetFilter(PortMidiStream *stream, int32_t filters) { } -PMEXPORT PmError Pm_Close( PortMidiStream *stream ) { +PMEXPORT PmError Pm_Close(PortMidiStream *stream) +{ PmInternal *midi = (PmInternal *) stream; PmError err = pmNoError; @@ -866,10 +1126,10 @@ PMEXPORT PmError Pm_Close( PortMidiStream *stream ) { if (midi == NULL) /* midi must point to something */ err = pmBadPtr; /* if it is an open device, the device_id will be valid */ - else if (midi->device_id < 0 || midi->device_id >= pm_descriptor_index) + else if (midi->device_id < 0 || midi->device_id >= pm_descriptor_len) err = pmBadPtr; /* and the device should be in the opened state */ - else if (!descriptors[midi->device_id].pub.opened) + else if (!pm_descriptors[midi->device_id].pub.opened) err = pmBadPtr; if (err != pmNoError) @@ -878,8 +1138,8 @@ PMEXPORT PmError Pm_Close( PortMidiStream *stream ) { /* close the device */ err = (*midi->dictionary->close)(midi); /* even if an error occurred, continue with cleanup */ - descriptors[midi->device_id].internalDescriptor = NULL; - descriptors[midi->device_id].pub.opened = FALSE; + pm_descriptors[midi->device_id].pm_internal = NULL; + pm_descriptors[midi->device_id].pub.opened = FALSE; if (midi->queue) Pm_QueueDestroy(midi->queue); pm_free(midi); error_return: @@ -889,56 +1149,57 @@ error_return: return pm_errmsg(err); } -PmError Pm_Synchronize( PortMidiStream* stream ) { +PmError Pm_Synchronize(PortMidiStream* stream) +{ PmInternal *midi = (PmInternal *) stream; PmError err = pmNoError; if (midi == NULL) err = pmBadPtr; - else if (!descriptors[midi->device_id].pub.output) + else if (!pm_descriptors[midi->device_id].pub.output) err = pmBadPtr; - else if (!descriptors[midi->device_id].pub.opened) + else if (!pm_descriptors[midi->device_id].pub.opened) err = pmBadPtr; else midi->first_message = TRUE; return err; } -PMEXPORT PmError Pm_Abort( PortMidiStream* stream ) { +PMEXPORT PmError Pm_Abort(PortMidiStream* stream) +{ PmInternal *midi = (PmInternal *) stream; PmError err; /* arg checking */ if (midi == NULL) err = pmBadPtr; - else if (!descriptors[midi->device_id].pub.output) + else if (!pm_descriptors[midi->device_id].pub.output) err = pmBadPtr; - else if (!descriptors[midi->device_id].pub.opened) + else if (!pm_descriptors[midi->device_id].pub.opened) err = pmBadPtr; else err = (*midi->dictionary->abort)(midi); if (err == pmHostError) { - midi->dictionary->host_error(midi, pm_hosterror_text, - PM_HOST_ERROR_MSG_LEN); - pm_hosterror = TRUE; + midi->dictionary->check_host_error(midi); } return pm_errmsg(err); } -/* pm_channel_filtered returns non-zero if the channel mask is blocking the current channel */ +/* pm_channel_filtered returns non-zero if the channel mask is + blocking the current channel */ #define pm_channel_filtered(status, mask) \ ((((status) & 0xF0) != 0xF0) && (!(Pm_Channel((status) & 0x0F) & (mask)))) -/* The following two functions will checks to see if a MIDI message matches - the filtering criteria. Since the sysex routines only want to filter realtime messages, - we need to have separate routines. +/* The following two functions will checks to see if a MIDI message + matches the filtering criteria. Since the sysex routines only want + to filter realtime messages, we need to have separate routines. */ -/* pm_realtime_filtered returns non-zero if the filter will kill the current message. - Note that only realtime messages are checked here. +/* pm_realtime_filtered returns non-zero if the filter will kill the + current message. Note that only realtime messages are checked here. */ #define pm_realtime_filtered(status, filters) \ ((((status) & 0xF0) == 0xF0) && ((1 << ((status) & 0xF)) & (filters))) @@ -959,18 +1220,21 @@ PMEXPORT PmError Pm_Abort( PortMidiStream* stream ) { }*/ -/* pm_status_filtered returns non-zero if a filter will kill the current message, based on status. - Note that sysex and real time are not checked. It is up to the subsystem (winmm, core midi, alsa) - to filter sysex, as it is handled more easily and efficiently at that level. - Realtime message are filtered in pm_realtime_filtered. +/* pm_status_filtered returns non-zero if a filter will kill the + current message, based on status. Note that sysex and real time are + not checked. It is up to the subsystem (winmm, core midi, alsa) to + filter sysex, as it is handled more easily and efficiently at that + level. Realtime message are filtered in pm_realtime_filtered. */ -#define pm_status_filtered(status, filters) ((1 << (16 + ((status) >> 4))) & (filters)) +#define pm_status_filtered(status, filters) \ + ((1 << (16 + ((status) >> 4))) & (filters)) /* return ((status == MIDI_NOTE_ON) && (filters & PM_FILT_NOTE)) || ((status == MIDI_NOTE_OFF) && (filters & PM_FILT_NOTE)) - || ((status == MIDI_CHANNEL_AT) && (filters & PM_FILT_CHANNEL_AFTERTOUCH)) + || ((status == MIDI_CHANNEL_AT) && + (filters & PM_FILT_CHANNEL_AFTERTOUCH)) || ((status == MIDI_POLY_AT) && (filters & PM_FILT_POLY_AFTERTOUCH)) || ((status == MIDI_PROGRAM) && (filters & PM_FILT_PROGRAM)) || ((status == MIDI_CONTROL) && (filters & PM_FILT_CONTROL)) diff --git a/3rdparty/portmidi/pm_common/portmidi.h b/3rdparty/portmidi/pm_common/portmidi.h index c57432fae12..1a4c7e7d0ab 100644 --- a/3rdparty/portmidi/pm_common/portmidi.h +++ b/3rdparty/portmidi/pm_common/portmidi.h @@ -48,69 +48,43 @@ extern "C" { * * NOTES ON HOST ERROR REPORTING: * - * PortMidi errors (of type PmError) are generic, system-independent errors. - * When an error does not map to one of the more specific PmErrors, the - * catch-all code pmHostError is returned. This means that PortMidi has - * retained a more specific system-dependent error code. The caller can - * get more information by calling Pm_HasHostError() to test if there is - * a pending host error, and Pm_GetHostErrorText() to get a text string - * describing the error. Host errors are reported on a per-device basis - * because only after you open a device does PortMidi have a place to - * record the host error code. I.e. only - * those routines that receive a (PortMidiStream *) argument check and - * report errors. One exception to this is that Pm_OpenInput() and - * Pm_OpenOutput() can report errors even though when an error occurs, - * there is no PortMidiStream* to hold the error. Fortunately, both - * of these functions return any error immediately, so we do not really - * need per-device error memory. Instead, any host error code is stored - * in a global, pmHostError is returned, and the user can call - * Pm_GetHostErrorText() to get the error message (and the invalid stream - * parameter will be ignored.) The functions - * pm_init and pm_term do not fail or raise - * errors. The job of pm_init is to locate all available devices so that - * the caller can get information via PmDeviceInfo(). If an error occurs, - * the device is simply not listed as available. - * - * Host errors come in two flavors: - * a) host error - * b) host error during callback - * These can occur w/midi input or output devices. (b) can only happen - * asynchronously (during callback routines), whereas (a) only occurs while - * synchronously running PortMidi and any resulting system dependent calls. - * Both (a) and (b) are reported by the next read or write call. You can - * also query for asynchronous errors (b) at any time by calling - * Pm_HasHostError(). + * PortMidi errors (of type PmError) are generic, + * system-independent errors. When an error does not map to one of + * the more specific PmErrors, the catch-all code pmHostError is + * returned. This means that PortMidi has retained a more specific + * system-dependent error code. The caller can get more information + * by calling Pm_GetHostErrorText() to get a text string describing + * the error. Host errors can arise asynchronously from callbacks, + * * so there is no specific return code. Asynchronous errors are + * checked and reported by Pm_Poll. You can also check by calling + * Pm_HasHostError(). If this returns TRUE, Pm_GetHostErrorText() + * will return a text description of the error. * * NOTES ON COMPILE-TIME SWITCHES * - * DEBUG assumes stdio and a console. Use this if you want automatic, simple - * error reporting, e.g. for prototyping. If you are using MFC or some - * other graphical interface with no console, DEBUG probably should be - * undefined. - * PM_CHECK_ERRORS more-or-less takes over error checking for return values, - * stopping your program and printing error messages when an error - * occurs. This also uses stdio for console text I/O. + * DEBUG assumes stdio and a console. Use this if you want + * automatic, simple error reporting, e.g. for prototyping. If + * you are using MFC or some other graphical interface with no + * console, DEBUG probably should be undefined. + * PM_CHECK_ERRORS more-or-less takes over error checking for + * return values, stopping your program and printing error + * messages when an error occurs. This also uses stdio for + * console text I/O. You can selectively disable this error + * checking by declaring extern int pm_check_errors; and + * setting pm_check_errors = FALSE; You can also reenable. */ +/** + \defgroup grp_basics Basic Definitions + @{ +*/ -#ifndef WIN32 -// Linux and OS X have stdint.h #include <stdint.h> -#else -#ifndef INT32_DEFINED -// rather than having users install a special .h file for windows, -// just put the required definitions inline here. porttime.h uses -// these too, so the definitions are (unfortunately) duplicated there -typedef int int32_t; -typedef unsigned int uint32_t; -#define INT32_DEFINED -#endif -#endif -//#ifdef _WINDLL -//#define PMEXPORT __declspec(dllexport) -//#else +#ifdef _WINDLL +#define PMEXPORT __declspec(dllexport) +#else #define PMEXPORT -//#endif +#endif #ifndef FALSE #define FALSE 0 @@ -122,113 +96,206 @@ typedef unsigned int uint32_t; /* default size of buffers for sysex transmission: */ #define PM_DEFAULT_SYSEX_BUFFER_SIZE 1024 -/** List of portmidi errors.*/ + typedef enum { - pmNoError = 0, - pmNoData = 0, /**< A "no error" return that also indicates no data avail. */ - pmGotData = 1, /**< A "no error" return that also indicates data available */ + pmNoError = 0, /**< Normal return value indicating no error. */ + pmNoData = 0, /**< @brief No error, also indicates no data available. + * Use this constant where a value greater than zero would + * indicate data is available. + */ + pmGotData = 1, /**< A "no error" return also indicating data available. */ pmHostError = -10000, - pmInvalidDeviceId, /** out of range or + pmInvalidDeviceId, /**< Out of range or * output device when input is requested or * input device when output is requested or - * device is already opened + * device is already opened. */ pmInsufficientMemory, pmBufferTooSmall, pmBufferOverflow, - pmBadPtr, /* PortMidiStream parameter is NULL or + pmBadPtr, /**< #PortMidiStream parameter is NULL or * stream is not opened or * stream is output when input is required or - * stream is input when output is required */ - pmBadData, /** illegal midi data, e.g. missing EOX */ + * stream is input when output is required. */ + pmBadData, /**< Illegal midi data, e.g., missing EOX. */ pmInternalError, - pmBufferMaxSize /** buffer is already as large as it can be */ - /* NOTE: If you add a new error type, be sure to update Pm_GetErrorText() */ -} PmError; + pmBufferMaxSize, /**< Buffer is already as large as it can be. */ + pmNotImplemented, /**< The function is not implemented, nothing was done. */ + pmInterfaceNotSupported, /**< The requested interface is not supported. */ + pmNameConflict /**< Cannot create virtual device because name is taken. */ + /* NOTE: If you add a new error type, you must update Pm_GetErrorText(). */ +} PmError; /**< @brief @enum PmError PortMidi error code; a common return type. + * No error is indicated by zero; errors are indicated by < 0. + */ /** - Pm_Initialize() is the library initialisation function - call this before + Pm_Initialize() is the library initialization function - call this before using the library. + + *NOTE:* PortMidi scans for available devices when #Pm_Initialize + is called. To observe subsequent changes in the available + devices, you must shut down PortMidi by calling #Pm_Terminate and + then restart by calling #Pm_Initialize again. *IMPORTANT*: On + MacOS, #Pm_Initialize *must* always be called on the same + thread. Otherwise, changes in the available MIDI devices will + *not* be seen by PortMidi. As an example, if you start PortMidi in + a thread for processing MIDI, do not try to rescan devices by + calling #Pm_Initialize in a GUI thread. Instead, start PortMidi + the first time and every time in the GUI thread. Alternatively, + let the GUI request a restart in the MIDI thread. (These + restrictions only apply to macOS.) Speaking of threads, on all + platforms, you are allowed to call #Pm_Initialize in one thread, + yet send MIDI or poll for incoming MIDI in another + thread. However, PortMidi is not "thread safe," which means you + cannot allow threads to call PortMidi functions concurrently. + + @return pmNoError. + + PortMidi is designed to support multiple interfaces (such as ALSA, + CoreMIDI and WinMM). It is possible to return pmNoError because there + are no supported interfaces. In that case, zero devices will be + available. */ -PMEXPORT PmError Pm_Initialize( void ); +PMEXPORT PmError Pm_Initialize(void); /** Pm_Terminate() is the library termination function - call this after using the library. */ -PMEXPORT PmError Pm_Terminate( void ); +PMEXPORT PmError Pm_Terminate(void); -/** A single PortMidiStream is a descriptor for an open MIDI device. -*/ +/** Represents an open MIDI device. */ typedef void PortMidiStream; + +/** A shorter form of #PortMidiStream. */ #define PmStream PortMidiStream -/** - Test whether stream has a pending host error. Normally, the client finds - out about errors through returned error codes, but some errors can occur - asynchronously where the client does not - explicitly call a function, and therefore cannot receive an error code. - The client can test for a pending error using Pm_HasHostError(). If true, - the error can be accessed and cleared by calling Pm_GetErrorText(). - Errors are also cleared by calling other functions that can return - errors, e.g. Pm_OpenInput(), Pm_OpenOutput(), Pm_Read(), Pm_Write(). The - client does not need to call Pm_HasHostError(). Any pending error will be - reported the next time the client performs an explicit function call on - the stream, e.g. an input or output operation. Until the error is cleared, - no new error codes will be obtained, even for a different stream. +/** Test whether stream has a pending host error. Normally, the client + finds out about errors through returned error codes, but some + errors can occur asynchronously where the client does not + explicitly call a function, and therefore cannot receive an error + code. The client can test for a pending error using + Pm_HasHostError(). If true, the error can be accessed by calling + Pm_GetHostErrorText(). Pm_Poll() is similar to Pm_HasHostError(), + but if there is no error, it will return TRUE (1) if there is a + pending input message. */ -PMEXPORT int Pm_HasHostError( PortMidiStream * stream ); +PMEXPORT int Pm_HasHostError(PortMidiStream * stream); -/** Translate portmidi error number into human readable message. +/** Translate portmidi error number into human readable message. These strings are constants (set at compile time) so client has - no need to allocate storage + no need to allocate storage. */ -PMEXPORT const char *Pm_GetErrorText( PmError errnum ); +PMEXPORT const char *Pm_GetErrorText(PmError errnum); -/** Translate portmidi host error into human readable message. +/** Translate portmidi host error into human readable message. These strings are computed at run time, so client has to allocate storage. After this routine executes, the host error is cleared. */ PMEXPORT void Pm_GetHostErrorText(char * msg, unsigned int len); -#define HDRLENGTH 50 -#define PM_HOST_ERROR_MSG_LEN 256u /* any host error msg will occupy less - than this number of characters */ - -/** - Device enumeration mechanism. - - Device ids range from 0 to Pm_CountDevices()-1. +/** Any host error msg has at most this many characters, including EOS. */ +#define PM_HOST_ERROR_MSG_LEN 256u +/** Devices are represented as small integers. Device ids range from 0 + to Pm_CountDevices()-1. Pm_GetDeviceInfo() is used to get information + about the device, and Pm_OpenInput() and PmOpenOutput() are used to + open the device. */ typedef int PmDeviceID; + +/** This PmDeviceID (constant) value represents no device and may be + returned by Pm_GetDefaultInputDeviceID() or + Pm_GetDefaultOutputDeviceID() if no default exists. +*/ #define pmNoDevice -1 -typedef struct { - int structVersion; /**< this internal structure version */ - const char *interf; /**< underlying MIDI API, e.g. MMSystem or DirectX */ - const char *name; /**< device name, e.g. USB MidiSport 1x1 */ - int input; /**< true iff input is available */ - int output; /**< true iff output is available */ - int opened; /**< used by generic PortMidi code to do error checking on arguments */ +/** MIDI device information is returned in this structure, which is + owned by PortMidi and read-only to applications. See Pm_GetDeviceInfo(). +*/ +#define PM_DEVICEINFO_VERS 200 +typedef struct { + int structVersion; /**< @brief this internal structure version */ + const char *interf; /**< @brief underlying MIDI API, e.g. + "MMSystem" or "DirectX" */ + char *name; /**< @brief device name, e.g. "USB MidiSport 1x1" */ + int input; /**< @brief true iff input is available */ + int output; /**< @brief true iff output is available */ + int opened; /**< @brief used by generic PortMidi for error checking */ + int is_virtual; /**< @brief true iff this is/was a virtual device */ } PmDeviceInfo; -/** Get devices count, ids range from 0 to Pm_CountDevices()-1. */ -PMEXPORT int Pm_CountDevices( void ); -/** - Pm_GetDefaultInputDeviceID(), Pm_GetDefaultOutputDeviceID() +/** Get devices count, ids range from 0 to Pm_CountDevices()-1. */ +PMEXPORT int Pm_CountDevices(void); +/** Return the default device ID or pmNoDevice if there are no devices. The result (but not pmNoDevice) can be passed to Pm_OpenMidi(). - The default device can be specified using a small application - named pmdefaults that is part of the PortMidi distribution. This - program in turn uses the Java Preferences object created by + The use of these functions is not recommended. There is no natural + "default device" on any system, so defaults must be set by users. + (Currently, PortMidi just returns the first device it finds as + "default".) The (unsolved) problem is how to implement simple + preferences for a cross-platform library. (More notes follow, but + you can stop reading here.) + + To implement preferences, you need (1) a standard place to put + them, (2) a representation for the preferences, (3) a graphical + interface to test and set preferences, (4) a "natural" way to + invoke the preference-setting program. To solve (3), PortMidi + originally chose to use Java and Swing to implement a + cross-platform GUI program called "pmdefaults." Java's Preferences + class already provide a location (problem 1) and representation + (problem 2). However, this solution was complex, requiring + PortMidi to parse binary Java preference files and requiring users + to install and invoke Java programs. It did not seem possible to + integrate pmdefaults into the system preference subsystems on + macOS, Windows, and Linux, so the user had to install and run + pmdefaults as an application. Moreover, Java is falling out of + favor. + + A simpler solution is pass the burden to applications. It is easy + to scan devices with PortMidi and build a device menu, and to save + menu selections in application preferences for next time. This is + my recommendation for any GUI program. For simple command-line + applications and utilities, see pm_test where all the test + programs now accept device numbers on the command line and/or + prompt for their entry. + + Some advice for preferences: MIDI devices used to be built-in or + plug-in cards, so the numbers rarely changed. Now MIDI devices are + often plug-in USB devices, so device numbers change, and you + probably need to design to reinitialize PortMidi to rescan + devices. MIDI is pretty stateless, so this isn't a big problem, + although it means you cannot find a new device while playing or + recording MIDI. + + Since device numbering can change whenever a USB device is plugged + in, preferences should record *names* of devices rather than + device numbers. It is simple enough to use string matching to find + a prefered device, so PortMidi does not provide any built-in + lookup function. See below for details of the Java preferences API. + + In the future, I would like to remove the legacy code that parses + Java preference data (macOS plist, linux prefs.xml, Windows + registry entries) and replace it with something more useful. Maybe + something really simple: $HOME/.portmidi? Or maybe a new + pmdefaults written with PyGame? Or use QT? If applications write + their own preferences, maybe a minimal command line preference + setter is all that's needed? Or maybe command line application + users are happy without a preference system? Comments and + proposals are welcome. + + For completeness, here is a description of the original use of + Java for preference setting: The default device can be specified + using a small application named pmdefaults that is part of the + PortMidi distribution. This program in turn uses the Java + Preferences object created by java.util.prefs.Preferences.userRoot().node("/PortMidi"); the - preference is set by calling - prefs.put("PM_RECOMMENDED_OUTPUT_DEVICE", prefName); - or prefs.put("PM_RECOMMENDED_INPUT_DEVICE", prefName); + preference is set by calling + prefs.put("PM_RECOMMENDED_OUTPUT_DEVICE", prefName); or + prefs.put("PM_RECOMMENDED_INPUT_DEVICE", prefName); In the statements above, prefName is a string describing the MIDI device in the form "interf, name" where interf identifies @@ -248,143 +315,274 @@ PMEXPORT int Pm_CountDevices( void ); the entire preference string is interpreted as a name, and the interface part is the empty string, which matches anything. - On the MAC, preferences are stored in - /Users/$NAME/Library/Preferences/com.apple.java.util.prefs.plist + On the MAC, preferences are stored in + /Users/$NAME/Library/Preferences/com.apple.java.util.prefs.plist which is a binary file. In addition to the pmdefaults program, there are utilities that can read and edit this preference file. - - On the PC, - - On Linux, - + On Windows, the Registry is used. On Linux, preferences are in an + XML file. */ -PMEXPORT PmDeviceID Pm_GetDefaultInputDeviceID( void ); -/** see PmDeviceID Pm_GetDefaultInputDeviceID() */ -PMEXPORT PmDeviceID Pm_GetDefaultOutputDeviceID( void ); +PMEXPORT PmDeviceID Pm_GetDefaultInputDeviceID(void); -/** - PmTimestamp is used to represent a millisecond clock with arbitrary - start time. The type is used for all MIDI timestampes and clocks. +/** @brief see PmDeviceID Pm_GetDefaultInputDeviceID() */ +PMEXPORT PmDeviceID Pm_GetDefaultOutputDeviceID(void); + +/** Represents a millisecond clock with arbitrary start time. + This type is used for all MIDI timestamps and clocks. */ typedef int32_t PmTimestamp; typedef PmTimestamp (*PmTimeProcPtr)(void *time_info); /** TRUE if t1 before t2 */ #define PmBefore(t1,t2) ((t1-t2) < 0) +/** @} */ /** \defgroup grp_device Input/Output Devices Handling @{ */ -/** - Pm_GetDeviceInfo() returns a pointer to a PmDeviceInfo structure - referring to the device specified by id. - If id is out of range the function returns NULL. +/** Get a PmDeviceInfo structure describing a MIDI device. + + @param id the device to be queried. - The returned structure is owned by the PortMidi implementation and must - not be manipulated or freed. The pointer is guaranteed to be valid - between calls to Pm_Initialize() and Pm_Terminate(). -*/ -PMEXPORT const PmDeviceInfo* Pm_GetDeviceInfo( PmDeviceID id ); + If \p id is out of range or if the device designates a deleted + virtual device, the function returns NULL. -/** - Pm_OpenInput() and Pm_OpenOutput() open devices. + The returned structure is owned by the PortMidi implementation and + must not be manipulated or freed. The pointer is guaranteed to be + valid between calls to Pm_Initialize() and Pm_Terminate(). +*/ +PMEXPORT const PmDeviceInfo *Pm_GetDeviceInfo(PmDeviceID id); - stream is the address of a PortMidiStream pointer which will receive - a pointer to the newly opened stream. +/** Open a MIDI device for input. - inputDevice is the id of the device used for input (see PmDeviceID above). + @param stream the address of a #PortMidiStream pointer which will + receive a pointer to the newly opened stream. - inputDriverInfo is a pointer to an optional driver specific data structure - containing additional information for device setup or handle processing. - inputDriverInfo is never required for correct operation. If not used - inputDriverInfo should be NULL. + @param inputDevice the ID of the device to be opened (see #PmDeviceID). - outputDevice is the id of the device used for output (see PmDeviceID above.) + @param inputDriverInfo a pointer to an optional driver-specific + data structure containing additional information for device setup + or handle processing. This parameter is never required for correct + operation. If not used, specify NULL. - outputDriverInfo is a pointer to an optional driver specific data structure - containing additional information for device setup or handle processing. - outputDriverInfo is never required for correct operation. If not used - outputDriverInfo should be NULL. + @param bufferSize the number of input events to be buffered + waiting to be read using Pm_Read(). Messages will be lost if the + number of unread messages exceeds this value. - For input, the buffersize specifies the number of input events to be - buffered waiting to be read using Pm_Read(). For output, buffersize - specifies the number of output events to be buffered waiting for output. - (In some cases -- see below -- PortMidi does not buffer output at all - and merely passes data to a lower-level API, in which case buffersize - is ignored.) - - latency is the delay in milliseconds applied to timestamps to determine - when the output should actually occur. (If latency is < 0, 0 is assumed.) - If latency is zero, timestamps are ignored and all output is delivered - immediately. If latency is greater than zero, output is delayed until the - message timestamp plus the latency. (NOTE: the time is measured relative - to the time source indicated by time_proc. Timestamps are absolute, - not relative delays or offsets.) In some cases, PortMidi can obtain - better timing than your application by passing timestamps along to the - device driver or hardware. Latency may also help you to synchronize midi - data to audio data by matching midi latency to the audio buffer latency. - - time_proc is a pointer to a procedure that returns time in milliseconds. It - may be NULL, in which case a default millisecond timebase (PortTime) is - used. If the application wants to use PortTime, it should start the timer - (call Pt_Start) before calling Pm_OpenInput or Pm_OpenOutput. If the - application tries to start the timer *after* Pm_OpenInput or Pm_OpenOutput, - it may get a ptAlreadyStarted error from Pt_Start, and the application's + @param time_proc (address of) a procedure that returns time in + milliseconds. It may be NULL, in which case a default millisecond + timebase (PortTime) is used. If the application wants to use + PortTime, it should start the timer (call Pt_Start) before calling + Pm_OpenInput or Pm_OpenOutput. If the application tries to start + the timer *after* Pm_OpenInput or Pm_OpenOutput, it may get a + ptAlreadyStarted error from Pt_Start, and the application's preferred time resolution and callback function will be ignored. - time_proc result values are appended to incoming MIDI data, and time_proc - times are used to schedule outgoing MIDI data (when latency is non-zero). + \p time_proc result values are appended to incoming MIDI data, + normally by mapping system-provided timestamps to the \p time_proc + timestamps to maintain the precision of system-provided + timestamps. - time_info is a pointer passed to time_proc. + @param time_info is a pointer passed to time_proc. - Example: If I provide a timestamp of 5000, latency is 1, and time_proc - returns 4990, then the desired output time will be when time_proc returns - timestamp+latency = 5001. This will be 5001-4990 = 11ms from now. - - return value: - Upon success Pm_Open() returns PmNoError and places a pointer to a - valid PortMidiStream in the stream argument. - If a call to Pm_Open() fails a nonzero error code is returned (see - PMError above) and the value of port is invalid. + @return #pmNoError and places a pointer to a valid + #PortMidiStream in the stream argument. If the open operation + fails, a nonzero error code is returned (see #PMError) and + the value of stream is invalid. Any stream that is successfully opened should eventually be closed by calling Pm_Close(). - */ -PMEXPORT PmError Pm_OpenInput( PortMidiStream** stream, +PMEXPORT PmError Pm_OpenInput(PortMidiStream** stream, PmDeviceID inputDevice, void *inputDriverInfo, int32_t bufferSize, PmTimeProcPtr time_proc, - void *time_info ); + void *time_info); + +/** Open a MIDI device for output. + + @param stream the address of a #PortMidiStream pointer which will + receive a pointer to the newly opened stream. + + @param outputDevice the ID of the device to be opened (see #PmDeviceID). + + @param outputDriverInfo a pointer to an optional driver-specific + data structure containing additional information for device setup + or handle processing. This parameter is never required for correct + operation. If not used, specify NULL. + + @param bufferSize the number of output events to be buffered + waiting for output. In some cases -- see below -- PortMidi does + not buffer output at all and merely passes data to a lower-level + API, in which case \p bufferSize is ignored. Since MIDI speeds now + vary from 1 to 50 or more messages per ms (over USB), put some + thought into this number. E.g. if latency is 20ms and you want to + burst 100 messages in that time (5000 messages per second), you + should set \p bufferSize to at least 100. The default on Windows + assumes an average rate of 500 messages per second and in this + example, output would be slowed waiting for free buffers. + + @param latency the delay in milliseconds applied to timestamps + to determine when the output should actually occur. (If latency is + < 0, 0 is assumed.) If latency is zero, timestamps are ignored + and all output is delivered immediately. If latency is greater + than zero, output is delayed until the message timestamp plus the + latency. (NOTE: the time is measured relative to the time source + indicated by time_proc. Timestamps are absolute, not relative + delays or offsets.) In some cases, PortMidi can obtain better + timing than your application by passing timestamps along to the + device driver or hardware, so the best strategy to minimize jitter + is: wait until the real time to send the message, compute the + message, attach the *ideal* output time (not the current real + time, because some time may have elapsed), and send the + message. The \p latency will be added to the timestamp, and + provided the elapsed computation time has not exceeded \p latency, + the message will be delivered according to the timestamp. If the + real time is already past the timestamp, the message will be + delivered as soon as possible. Latency may also help you to + synchronize MIDI data to audio data by matching \p latency to the + audio buffer latency. + + @param time_proc (address of) a pointer to a procedure that + returns time in milliseconds. It may be NULL, in which case a + default millisecond timebase (PortTime) is used. If the + application wants to use PortTime, it should start the timer (call + Pt_Start) before calling #Pm_OpenInput or #Pm_OpenOutput. If the + application tries to start the timer *after* #Pm_OpenInput or + #Pm_OpenOutput, it may get a #ptAlreadyStarted error from #Pt_Start, + and the application's preferred time resolution and callback + function will be ignored. \p time_proc times are used to schedule + outgoing MIDI data (when latency is non-zero), usually by mapping + from time_proc timestamps to internal system timestamps to + maintain the precision of system-supported timing. + + @param time_info a pointer passed to time_proc. + + @return #pmNoError and places a pointer to a valid #PortMidiStream + in the stream argument. If the operation fails, a nonzero error + code is returned (see PMError) and the value of \p stream is + invalid. + + Note: ALSA appears to have a fixed-size priority queue for timed + output messages. Testing indicates the queue can hold a little + over 400 3-byte MIDI messages. Thus, you can send 10,000 + messages/second if the latency is 30ms (30ms * 10000 msgs/sec * + 0.001 sec/ms = 300 msgs), but not if the latency is 50ms + (resulting in about 500 pending messages, which is greater than + the 400 message limit). Since timestamps in ALSA are relative, + they are of less value than absolute timestamps in macOS and + Windows. This is a limitation of ALSA and apparently a design + flaw. + + Example 1: If I provide a timestamp of 5000, latency is 1, and + time_proc returns 4990, then the desired output time will be when + time_proc returns timestamp+latency = 5001. This will be 5001-4990 + = 11ms from now. + + Example 2: If I want to send at exactly 5010, and latency is 10, I + should wait until 5000, compute the messages and provide a + timestamp of 5000. As long as computation takes less than 10ms, + the message will be delivered at time 5010. + + Example 3 (recommended): It is often convenient to ignore latency. + E.g. if a sequence says to output at time 5010, just wait until + 5010, compute the message and use 5010 for the timestamp. Delivery + will then be at 5010+latency, but unless you are synchronizing to + something else, the absolute delay by latency will not matter. -PMEXPORT PmError Pm_OpenOutput( PortMidiStream** stream, + Any stream that is successfully opened should eventually be closed + by calling Pm_Close(). +*/ +PMEXPORT PmError Pm_OpenOutput(PortMidiStream** stream, PmDeviceID outputDevice, void *outputDriverInfo, int32_t bufferSize, PmTimeProcPtr time_proc, void *time_info, - int32_t latency ); + int32_t latency); + +/** Create a virtual input device. + + @param name gives the virtual device name, which is visible to + other applications. + + @param interf is the interface (System API) used to create the + device Default interfaces are "MMSystem", "CoreMIDI" and + "ALSA". Currently, these are the only ones implemented, but future + implementations could support DirectMusic, Jack, sndio, or others. + + @param deviceInfo contains interface-dependent additional + information, e.g., hints or options. There are none at present, and + NULL is the recommended value. + + @return a device ID or #pmNameConflict (\p name is invalid or + already exists) or #pmInterfaceNotSupported (\p interf is does not + match a supported interface). + + The created virtual device appears to other applications as if it + is an output device. The device must be opened to obtain a stream + and read from it. + + Virtual devices are not supported by Windows (Multimedia API). Calls + on Windows do nothing except return #pmNotImplemented. +*/ +PMEXPORT PmError Pm_CreateVirtualInput(const char *name, + const char *interf, + void *deviceInfo); + +/** Create a virtual output device. + + @param name gives the virtual device name, which is visible to + other applications. + + @param interf is the interface (System API) used to create the + device Default interfaces are "MMSystem", "CoreMIDI" and + "ALSA". Currently, these are the only ones implemented, but future + implementations could support DirectMusic, Jack, sndio, or others. + + @param deviceInfo contains interface-dependent additional + information, e.g., hints or options. There are none at present, and + NULL is the recommended value. + + @return a device ID or #pmInvalidDeviceId (\p name is invalid or + already exists) or #pmInterfaceNotSupported (\p interf is does not + match a supported interface). + + The created virtual device appears to other applications as if it + is an input device. The device must be opened to obtain a stream + and write to it. + + Virtual devices are not supported by Windows (Multimedia API). Calls + on Windows do nothing except return #pmNotImplemented. +*/ +PMEXPORT PmError Pm_CreateVirtualOutput(const char *name, + const char *interf, + void *deviceInfo); + +/** Remove a virtual device. + + @param device a device ID (small integer) designating the device. + + The device is removed; other applications can no longer see or open + this virtual device, which may be either for input or output. The + device must not be open. The device ID may be reused, but existing + devices are not renumbered. This means that the device ID could be + in the range from 0 to #Pm_CountDevices(), yet the device ID does + not designate a device. In that case, passing the ID to + #Pm_GetDeviceInfo() will return NULL. + + @return #pmNoError if the device was deleted or #pmInvalidDeviceId + if the device is open, already deleted, or \p device is out of + range. +*/ +PMEXPORT PmError Pm_DeleteVirtualDevice(PmDeviceID device); /** @} */ /** - \defgroup grp_events_filters Events and Filters Handling + @defgroup grp_events_filters Events and Filters Handling @{ */ -/* \function PmError Pm_SetFilter( PortMidiStream* stream, int32_t filters ) - Pm_SetFilter() sets filters on an open input stream to drop selected - input types. By default, only active sensing messages are filtered. - To prohibit, say, active sensing and sysex messages, call - Pm_SetFilter(stream, PM_FILT_ACTIVE | PM_FILT_SYSEX); - - Filtering is useful when midi routing or midi thru functionality is being - provided by the user application. - For example, you may want to exclude timing messages (clock, MTC, start/stop/continue), - while allowing note-related messages to pass. - Or you may be using a sequencer or drum-machine for MIDI clock information but want to - exclude any notes it may play. - */ - /* Filter bit-mask definitions */ /** filter active sensing messages (0xFE): */ #define PM_FILT_ACTIVE (1 << 0x0E) @@ -412,7 +610,8 @@ PMEXPORT PmError Pm_OpenOutput( PortMidiStream** stream, /** per-note aftertouch (0xA0-0xAF) */ #define PM_FILT_POLY_AFTERTOUCH (1 << 0x1A) /** filter both channel and poly aftertouch */ -#define PM_FILT_AFTERTOUCH (PM_FILT_CHANNEL_AFTERTOUCH | PM_FILT_POLY_AFTERTOUCH) +#define PM_FILT_AFTERTOUCH (PM_FILT_CHANNEL_AFTERTOUCH | \ + PM_FILT_POLY_AFTERTOUCH) /** Program changes (0xC0-0xCF) */ #define PM_FILT_PROGRAM (1 << 0x1C) /** Control Changes (CC's) (0xB0-0xBF)*/ @@ -425,20 +624,48 @@ PMEXPORT PmError Pm_OpenOutput( PortMidiStream** stream, #define PM_FILT_SONG_POSITION (1 << 0x02) /** Song Select (0xF3)*/ #define PM_FILT_SONG_SELECT (1 << 0x03) -/** Tuning request (0xF6)*/ +/** Tuning request (0xF6) */ #define PM_FILT_TUNE (1 << 0x06) /** All System Common messages (mtc, song position, song select, tune request) */ -#define PM_FILT_SYSTEMCOMMON (PM_FILT_MTC | PM_FILT_SONG_POSITION | PM_FILT_SONG_SELECT | PM_FILT_TUNE) +#define PM_FILT_SYSTEMCOMMON (PM_FILT_MTC | PM_FILT_SONG_POSITION | \ + PM_FILT_SONG_SELECT | PM_FILT_TUNE) + + +/* Set filters on an open input stream to drop selected input types. + + @param stream an open MIDI input stream. + @param filters indicate message types to filter (block). -PMEXPORT PmError Pm_SetFilter( PortMidiStream* stream, int32_t filters ); + @return #pmNoError or an error code. + By default, only active sensing messages are filtered. + To prohibit, say, active sensing and sysex messages, call + Pm_SetFilter(stream, PM_FILT_ACTIVE | PM_FILT_SYSEX); + + Filtering is useful when midi routing or midi thru functionality + is being provided by the user application. + For example, you may want to exclude timing messages (clock, MTC, + start/stop/continue), while allowing note-related messages to pass. + Or you may be using a sequencer or drum-machine for MIDI clock + information but want to exclude any notes it may play. + */ +PMEXPORT PmError Pm_SetFilter(PortMidiStream* stream, int32_t filters); + +/** Create a mask that filters one channel. */ #define Pm_Channel(channel) (1<<(channel)) -/** - Pm_SetChannelMask() filters incoming messages based on channel. - The mask is a 16-bit bitfield corresponding to appropriate channels. - The Pm_Channel macro can assist in calling this function. - i.e. to set receive only input on channel 1, call with + +/** Filter incoming messages based on channel. + + @param stream an open MIDI input stream. + + @param mask indicates channels to be received. + + @return #pmNoError or an error code. + + The \p mask is a 16-bit bitfield corresponding to appropriate channels. + The #Pm_Channel macro can assist in calling this function. + I.e. to receive only input on channel 1, call with Pm_SetChannelMask(Pm_Channel(1)); Multiple channels should be OR'd together, like Pm_SetChannelMask(Pm_Channel(10) | Pm_Channel(11)) @@ -451,71 +678,94 @@ PMEXPORT PmError Pm_SetFilter( PortMidiStream* stream, int32_t filters ); */ PMEXPORT PmError Pm_SetChannelMask(PortMidiStream *stream, int mask); -/** - Pm_Abort() terminates outgoing messages immediately - The caller should immediately close the output port; - this call may result in transmission of a partial midi message. - There is no abort for Midi input because the user can simply - ignore messages in the buffer and close an input device at - any time. +/** Terminate outgoing messages immediately. + + @param stream an open MIDI output stream. + + @result #pmNoError or an error code. + + The caller should immediately close the output port; this call may + result in transmission of a partial MIDI message. There is no + abort for Midi input because the user can simply ignore messages + in the buffer and close an input device at any time. If the + specified behavior cannot be achieved through the system-level + interface (ALSA, CoreMIDI, etc.), the behavior may be that of + Pm_Close(). */ -PMEXPORT PmError Pm_Abort( PortMidiStream* stream ); +PMEXPORT PmError Pm_Abort(PortMidiStream* stream); -/** - Pm_Close() closes a midi stream, flushing any pending buffers. - (PortMidi attempts to close open streams when the application - exits -- this is particularly difficult under Windows.) -*/ -PMEXPORT PmError Pm_Close( PortMidiStream* stream ); +/** Close a midi stream, flush any pending buffers if possible. -/** - Pm_Synchronize() instructs PortMidi to (re)synchronize to the - time_proc passed when the stream was opened. Typically, this - is used when the stream must be opened before the time_proc - reference is actually advancing. In this case, message timing - may be erratic, but since timestamps of zero mean - "send immediately," initialization messages with zero timestamps - can be written without a functioning time reference and without - problems. Before the first MIDI message with a non-zero - timestamp is written to the stream, the time reference must - begin to advance (for example, if the time_proc computes time - based on audio samples, time might begin to advance when an - audio stream becomes active). After time_proc return values - become valid, and BEFORE writing the first non-zero timestamped - MIDI message, call Pm_Synchronize() so that PortMidi can observe - the difference between the current time_proc value and its - MIDI stream time. + @param stream an open MIDI input or output stream. + + @result #pmNoError or an error code. + + If the system-level interface (ALSA, CoreMIDI, etc.) does not + support flushing remaining messages, the behavior may be one of + the following (most preferred first): block until all pending + timestamped messages are delivered; deliver messages to a server + or kernel process for later delivery but return immediately; drop + messages (as in Pm_Abort()). Therefore, to be safe, applications + should wait until the output queue is empty before calling + Pm_Close(). E.g. calling Pt_Sleep(100 + latency); will give a + 100ms "cushion" beyond latency (if any) before closing. +*/ +PMEXPORT PmError Pm_Close(PortMidiStream* stream); + +/** (re)synchronize to the time_proc passed when the stream was opened. + + @param stream an open MIDI input or output stream. + + @result #pmNoError or an error code. + + Typically, this is used when the stream must be opened before the + time_proc reference is actually advancing. In this case, message + timing may be erratic, but since timestamps of zero mean "send + immediately," initialization messages with zero timestamps can be + written without a functioning time reference and without + problems. Before the first MIDI message with a non-zero timestamp + is written to the stream, the time reference must begin to advance + (for example, if the time_proc computes time based on audio + samples, time might begin to advance when an audio stream becomes + active). After time_proc return values become valid, and BEFORE + writing the first non-zero timestamped MIDI message, call + Pm_Synchronize() so that PortMidi can observe the difference + between the current time_proc value and its MIDI stream time. - In the more normal case where time_proc - values advance continuously, there is no need to call - Pm_Synchronize. PortMidi will always synchronize at the - first output message and periodically thereafter. + In the more normal case where time_proc values advance + continuously, there is no need to call #Pm_Synchronize. PortMidi + will always synchronize at the first output message and + periodically thereafter. */ -PmError Pm_Synchronize( PortMidiStream* stream ); +PMEXPORT PmError Pm_Synchronize(PortMidiStream* stream); -/** - Pm_Message() encodes a short Midi message into a 32-bit word. If data1 +/** Encode a short Midi message into a 32-bit word. If data1 and/or data2 are not present, use zero. - - Pm_MessageStatus(), Pm_MessageData1(), and - Pm_MessageData2() extract fields from a 32-bit midi message. */ #define Pm_Message(status, data1, data2) \ ((((data2) << 16) & 0xFF0000) | \ (((data1) << 8) & 0xFF00) | \ ((status) & 0xFF)) +/** Extract the status field from a 32-bit midi message. */ #define Pm_MessageStatus(msg) ((msg) & 0xFF) +/** Extract the 1st data field (e.g., pitch) from a 32-bit midi message. */ #define Pm_MessageData1(msg) (((msg) >> 8) & 0xFF) +/** Extract the 2nd data field (e.g., velocity) from a 32-bit midi message. */ #define Pm_MessageData2(msg) (((msg) >> 16) & 0xFF) -typedef int32_t PmMessage; /**< see PmEvent */ +typedef uint32_t PmMessage; /**< @brief see #PmEvent */ /** - All midi data comes in the form of PmEvent structures. A sysex + All MIDI data comes in the form of PmEvent structures. A sysex message is encoded as a sequence of PmEvent structures, with each structure carrying 4 bytes of the message, i.e. only the first PmEvent carries the status byte. + All other MIDI messages take 1 to 3 bytes and are encoded in a whole + PmMessage with status in the low-order byte and remaining bytes + unused, i.e., a 3-byte note-on message will occupy 3 low-order bytes + of PmMessage, leaving the high-order byte unused. + Note that MIDI allows nested messages: the so-called "real-time" MIDI messages can be inserted into the MIDI byte stream at any location, including within a sysex message. MIDI real-time messages are one-byte @@ -555,8 +805,8 @@ typedef int32_t PmMessage; /**< see PmEvent */ messages should be sent in the correct order, and timestamps MUST be non-decreasing. See also "Example" for Pm_OpenOutput() above. - A sysex message will generally fill many PmEvent structures. On - output to a PortMidiStream with non-zero latency, the first timestamp + A sysex message will generally fill many #PmEvent structures. On + output to a #PortMidiStream with non-zero latency, the first timestamp on sysex message data will determine the time to begin sending the message. PortMidi implementations may ignore timestamps for the remainder of the sysex message. @@ -580,71 +830,127 @@ typedef struct { PmTimestamp timestamp; } PmEvent; -/** - @} -*/ +/** @} */ + /** \defgroup grp_io Reading and Writing Midi Messages @{ */ -/** - Pm_Read() retrieves midi data into a buffer, and returns the number - of events read. Result is a non-negative number unless an error occurs, - in which case a PmError value will be returned. +/** Retrieve midi data into a buffer. - Buffer Overflow + @param stream the open input stream. - The problem: if an input overflow occurs, data will be lost, ultimately - because there is no flow control all the way back to the data source. - When data is lost, the receiver should be notified and some sort of - graceful recovery should take place, e.g. you shouldn't resume receiving - in the middle of a long sysex message. + @return the number of events read, or, if the result is negative, + a #PmError value will be returned. - With a lock-free fifo, which is pretty much what we're stuck with to - enable portability to the Mac, it's tricky for the producer and consumer - to synchronously reset the buffer and resume normal operation. + The Buffer Overflow Problem - Solution: the buffer managed by PortMidi will be flushed when an overflow - occurs. The consumer (Pm_Read()) gets an error message (pmBufferOverflow) - and ordinary processing resumes as soon as a new message arrives. The - remainder of a partial sysex message is not considered to be a "new - message" and will be flushed as well. + The problem: if an input overflow occurs, data will be lost, + ultimately because there is no flow control all the way back to + the data source. When data is lost, the receiver should be + notified and some sort of graceful recovery should take place, + e.g. you shouldn't resume receiving in the middle of a long sysex + message. + With a lock-free fifo, which is pretty much what we're stuck with + to enable portability to the Mac, it's tricky for the producer and + consumer to synchronously reset the buffer and resume normal + operation. + + Solution: the entire buffer managed by PortMidi will be flushed + when an overflow occurs. The consumer (Pm_Read()) gets an error + message (#pmBufferOverflow) and ordinary processing resumes as + soon as a new message arrives. The remainder of a partial sysex + message is not considered to be a "new message" and will be + flushed as well. */ -PMEXPORT int Pm_Read( PortMidiStream *stream, PmEvent *buffer, int32_t length ); +PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length); -/** - Pm_Poll() tests whether input is available, - returning TRUE, FALSE, or an error value. +/** Test whether input is available. + + @param stream an open input stream. + + @return TRUE, FALSE, or an error value. + + If there was an asynchronous error, pmHostError is returned and you must + call again to determine if input is (also) available. + + You should probably *not* use this function. Call Pm_Read() + instead. If it returns 0, then there is no data available. It is + possible for Pm_Poll() to return TRUE before the complete message + is available, so Pm_Read() could return 0 even after Pm_Poll() + returns TRUE. Only call Pm_Poll() if you want to know that data is + probably available even though you are not ready to receive data. */ -PMEXPORT PmError Pm_Poll( PortMidiStream *stream); +PMEXPORT PmError Pm_Poll(PortMidiStream *stream); -/** - Pm_Write() writes midi data from a buffer. This may contain: +/** Write MIDI data from a buffer. + + @param stream an open output stream. + + @param buffer (address of) an array of MIDI event data. + + @param length the length of the \p buffer. + + @return TRUE, FALSE, or an error value. + + \b buffer may contain: - short messages - or - sysex messages that are converted into a sequence of PmEvent structures, e.g. sending data from a file or forwarding them - from midi input. + from midi input, with 4 SysEx bytes per PmEvent message, + low-order byte first, until the last message, which may + contain from 1 to 4 bytes ending in MIDI EOX (0xF7). + - PortMidi allows 1-byte real-time messages to be embedded + within SysEx messages, but only on 4-byte boundaries so + that SysEx data always uses a full 4 bytes (except possibly + at the end). Each real-time message always occupies a full + PmEvent (3 of the 4 bytes in the PmEvent's message are + ignored) even when embedded in a SysEx message. Use Pm_WriteSysEx() to write a sysex message stored as a contiguous array of bytes. Sysex data may contain embedded real-time messages. + + \p buffer is managed by the caller. The buffer may be destroyed + as soon as this call returns. */ -PMEXPORT PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, int32_t length ); +PMEXPORT PmError Pm_Write(PortMidiStream *stream, PmEvent *buffer, + int32_t length); -/** - Pm_WriteShort() writes a timestamped non-system-exclusive midi message. - Messages are delivered in order as received, and timestamps must be - non-decreasing. (But timestamps are ignored if the stream was opened - with latency = 0.) +/** Write a timestamped non-system-exclusive midi message. + + @param stream an open output stream. + + @param when timestamp for the event. + + @param msg the data for the event. + + @result #pmNoError or an error code. + + Messages are delivered in order, and timestamps must be + non-decreasing. (But timestamps are ignored if the stream was + opened with latency = 0, and otherwise, non-decreasing timestamps + are "corrected" to the lowest valid value.) */ -PMEXPORT PmError Pm_WriteShort( PortMidiStream *stream, PmTimestamp when, int32_t msg); +PMEXPORT PmError Pm_WriteShort(PortMidiStream *stream, PmTimestamp when, + PmMessage msg); -/** - Pm_WriteSysEx() writes a timestamped system-exclusive midi message. +/** Write a timestamped system-exclusive midi message. + + @param stream an open output stream. + + @param when timestamp for the event. + + @param msg the sysex message, terminated with an EOX status byte. + + @result #pmNoError or an error code. + + \p msg is managed by the caller and may be destroyed when this + call returns. */ -PMEXPORT PmError Pm_WriteSysEx( PortMidiStream *stream, PmTimestamp when, unsigned char *msg); +PMEXPORT PmError Pm_WriteSysEx(PortMidiStream *stream, PmTimestamp when, + unsigned char *msg); /** @} */ diff --git a/3rdparty/portmidi/pm_csharp/README.txt b/3rdparty/portmidi/pm_csharp/README.txt deleted file mode 100644 index 06a1ad4e390..00000000000 --- a/3rdparty/portmidi/pm_csharp/README.txt +++ /dev/null @@ -1,20 +0,0 @@ -This code was offered by Aaron Oxford as is. The pm_managed directory contains the code. If you develop a more complete C# wrapper for PortMidi, please consider contributing your code to the project. -RBD - ----- from Aaron Oxford ---- - -I've attached the managed C++ project which I've inserted into my 2005 version of PortMIDI's VS solution. I wouldn't think the functions I've implemented would have changed so it all should still work with the latest version of PM. Obviously you won't want to permanently embed this since it means the whole solution can only be built under VS2005, but it's easy for a VS2005 user to insert the project after the solution is converted or even just build it separately. - -Making the managed wrapper turned out to be dead easy in the end (it was more of a battle finding the correct build settings & SDK's and learning to configure VS than anything else). Anyone wanting to use something I've not implemented yet simply needs to add more stubs like this - - int Pm_Initialize() - { - ::Pm_Initialize(); - return 0; - } - -to the code. To call from C# it's just a matter of - - ManagedPortMIDI mpm = new ManagedPortMIDI(); - int err = mpm.Pm_Initialize(); - -Anyway as the little code example above indicates, the support really is basic and more likely than not to break at the first hint of something unexpected. As I said, I'd be happy to contribute but I don't think there's much to contribute yet. :-) diff --git a/3rdparty/portmidi/pm_csharp/pm_managed/AssemblyInfo.cpp b/3rdparty/portmidi/pm_csharp/pm_managed/AssemblyInfo.cpp deleted file mode 100644 index 84033ec021d..00000000000 --- a/3rdparty/portmidi/pm_csharp/pm_managed/AssemblyInfo.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "stdafx.h" - -using namespace System; -using namespace System::Reflection; -using namespace System::Runtime::CompilerServices; -using namespace System::Runtime::InteropServices; -using namespace System::Security::Permissions; - -// -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -// -[assembly:AssemblyTitleAttribute("pm_managed")]; -[assembly:AssemblyDescriptionAttribute("")]; -[assembly:AssemblyConfigurationAttribute("")]; -[assembly:AssemblyCompanyAttribute("Innovative Computer Solutions")]; -[assembly:AssemblyProductAttribute("pm_managed")]; -[assembly:AssemblyCopyrightAttribute("Copyright (c) Innovative Computer Solutions 2006")]; -[assembly:AssemblyTrademarkAttribute("")]; -[assembly:AssemblyCultureAttribute("")]; - -// -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the value or you can default the Revision and Build Numbers -// by using the '*' as shown below: - -[assembly:AssemblyVersionAttribute("1.0.*")]; - -[assembly:ComVisible(false)]; - -[assembly:CLSCompliantAttribute(true)]; - -[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; diff --git a/3rdparty/portmidi/pm_csharp/pm_managed/ReadMe.txt b/3rdparty/portmidi/pm_csharp/pm_managed/ReadMe.txt deleted file mode 100644 index b01b06306cc..00000000000 --- a/3rdparty/portmidi/pm_csharp/pm_managed/ReadMe.txt +++ /dev/null @@ -1,31 +0,0 @@ -======================================================================== - DYNAMIC LINK LIBRARY : pm_managed Project Overview -======================================================================== - -AppWizard has created this pm_managed DLL for you. - -This file contains a summary of what you will find in each of the files that -make up your pm_managed application. - -pm_managed.vcproj - This is the main project file for VC++ projects generated using an Application Wizard. - It contains information about the version of Visual C++ that generated the file, and - information about the platforms, configurations, and project features selected with the - Application Wizard. - -pm_managed.cpp - This is the main DLL source file. - -pm_managed.h - This file contains a class declaration. - -AssemblyInfo.cpp - Contains custom attributes for modifying assembly metadata. - -///////////////////////////////////////////////////////////////////////////// -Other notes: - -AppWizard uses "TODO:" to indicate parts of the source code you -should add to or customize. - -///////////////////////////////////////////////////////////////////////////// diff --git a/3rdparty/portmidi/pm_csharp/pm_managed/Stdafx.cpp b/3rdparty/portmidi/pm_csharp/pm_managed/Stdafx.cpp deleted file mode 100644 index de4058cb399..00000000000 --- a/3rdparty/portmidi/pm_csharp/pm_managed/Stdafx.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// pm_managed.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" diff --git a/3rdparty/portmidi/pm_csharp/pm_managed/Stdafx.h b/3rdparty/portmidi/pm_csharp/pm_managed/Stdafx.h deleted file mode 100644 index 3cc4c24ef9f..00000000000 --- a/3rdparty/portmidi/pm_csharp/pm_managed/Stdafx.h +++ /dev/null @@ -1,7 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, -// but are changed infrequently - -#pragma once - - diff --git a/3rdparty/portmidi/pm_csharp/pm_managed/app.ico b/3rdparty/portmidi/pm_csharp/pm_managed/app.ico Binary files differdeleted file mode 100644 index 3a5525fd794..00000000000 --- a/3rdparty/portmidi/pm_csharp/pm_managed/app.ico +++ /dev/null diff --git a/3rdparty/portmidi/pm_csharp/pm_managed/app.rc b/3rdparty/portmidi/pm_csharp/pm_managed/app.rc deleted file mode 100644 index 41481bfc263..00000000000 --- a/3rdparty/portmidi/pm_csharp/pm_managed/app.rc +++ /dev/null @@ -1,63 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon placed first or with lowest ID value becomes application icon - -LANGUAGE 9, 3 -#pragma code_page(1252) -1 ICON "app.ico" - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" - "\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\0" -END - -#endif // APSTUDIO_INVOKED - -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/3rdparty/portmidi/pm_csharp/pm_managed/pm_managed.cpp b/3rdparty/portmidi/pm_csharp/pm_managed/pm_managed.cpp deleted file mode 100644 index 5389314e613..00000000000 --- a/3rdparty/portmidi/pm_csharp/pm_managed/pm_managed.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// This is the main DLL file. - -#include "stdafx.h" - -#include "pm_managed.h" - diff --git a/3rdparty/portmidi/pm_csharp/pm_managed/pm_managed.h b/3rdparty/portmidi/pm_csharp/pm_managed/pm_managed.h deleted file mode 100644 index 21898368ec8..00000000000 --- a/3rdparty/portmidi/pm_csharp/pm_managed/pm_managed.h +++ /dev/null @@ -1,53 +0,0 @@ -// pm_managed.h - -#pragma once - -#include "portmidi.h" - -using namespace System; - -namespace pm_managed { - - - public ref class MpmDeviceInfo - { - public: - int structVersion; - System::String^ interf; /* underlying MIDI API, e.g. MMSystem or DirectX */ - System::String^ name; /* device name, e.g. USB MidiSport 1x1 */ - bool input; /* true iff input is available */ - bool output; /* true iff output is available */ - int opened; /* used by generic PortMidi code to do error checking on arguments */ - - MpmDeviceInfo(const PmDeviceInfo* info) - { - structVersion = info->structVersion; - input = (info->input != 0); - output = (info->output != 0); - opened = info->opened; - - interf = gcnew System::String(info->interf); - name = gcnew System::String(info->name); - } - }; - - public ref class ManagedPortMIDI - { - public: - int Pm_Initialize() - { - ::Pm_Initialize(); - return 0; - } - - int Pm_CountDevices() - { - return ::Pm_CountDevices(); - } - - MpmDeviceInfo^ Pm_GetDeviceInfo(int id) - { - return gcnew MpmDeviceInfo(::Pm_GetDeviceInfo(id)); - } - }; -} diff --git a/3rdparty/portmidi/pm_csharp/pm_managed/pm_managed.vcproj b/3rdparty/portmidi/pm_csharp/pm_managed/pm_managed.vcproj deleted file mode 100644 index 4ce2052fe35..00000000000 --- a/3rdparty/portmidi/pm_csharp/pm_managed/pm_managed.vcproj +++ /dev/null @@ -1,260 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="8.00" - Name="pm_managed" - ProjectGUID="{65AABD9A-F5E3-4A30-8BC3-9C732B5447CF}" - RootNamespace="pm_managed" - Keyword="ManagedCProj" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="$(SolutionDir)pm_managed\$(ConfigurationName)" - IntermediateDirectory="$(ConfigurationName)" - ConfigurationType="2" - CharacterSet="1" - ManagedExtensions="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="../pm_common" - PreprocessorDefinitions="WIN32;_DEBUG" - RuntimeLibrary="3" - UsePrecompiledHeader="2" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="$(NoInherit) winmm.lib ..\pm_win\Debug\portmidi.lib ..\porttime\Debug\porttime.lib ..\pm_win\Debug\pm_dll.lib" - LinkIncremental="2" - GenerateDebugInformation="true" - AssemblyDebug="1" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCWebDeploymentTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="$(SolutionDir)pm_managed\$(ConfigurationName)" - IntermediateDirectory="$(ConfigurationName)" - ConfigurationType="2" - CharacterSet="1" - ManagedExtensions="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - FavorSizeOrSpeed="1" - AdditionalIncludeDirectories="../pm_common" - PreprocessorDefinitions="WIN32;NDEBUG" - RuntimeLibrary="2" - UsePrecompiledHeader="2" - WarningLevel="3" - DebugInformationFormat="0" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="$(NoInherit) winmm.lib ..\pm_win\Release\portmidi.lib ..\porttime\Release\porttime.lib ..\pm_win\Release\pm_dll.lib" - LinkIncremental="1" - ManifestFile="$(OutDir)\pm_managed.dll.manifest" - GenerateDebugInformation="false" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - OutputManifestFile="$(OutDir)\pm_managed.dll.manifest" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCWebDeploymentTool" - /> - <Tool - Name="VCPostBuildEventTool" - CommandLine="rem mt.exe –manifest Release\pm_managed.dll.manifest -outputresource:Release\pm_managed.dll;2" - /> - </Configuration> - </Configurations> - <References> - <AssemblyReference - RelativePath="System.dll" - AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL" - /> - <AssemblyReference - RelativePath="System.Data.dll" - AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86" - /> - <AssemblyReference - RelativePath="System.XML.dll" - AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL" - /> - </References> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File - RelativePath=".\AssemblyInfo.cpp" - > - </File> - <File - RelativePath=".\pm_managed.cpp" - > - </File> - <File - RelativePath=".\Stdafx.cpp" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCLCompilerTool" - UsePrecompiledHeader="1" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - UsePrecompiledHeader="1" - /> - </FileConfiguration> - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - <File - RelativePath=".\pm_managed.h" - > - </File> - <File - RelativePath=".\resource.h" - > - </File> - <File - RelativePath=".\Stdafx.h" - > - </File> - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - <File - RelativePath=".\app.ico" - > - </File> - <File - RelativePath=".\app.rc" - > - </File> - </Filter> - <File - RelativePath=".\ReadMe.txt" - > - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_csharp/pm_managed/resource.h b/3rdparty/portmidi/pm_csharp/pm_managed/resource.h deleted file mode 100644 index d5ac7c42aa0..00000000000 --- a/3rdparty/portmidi/pm_csharp/pm_managed/resource.h +++ /dev/null @@ -1,3 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by app.rc diff --git a/3rdparty/portmidi/pm_dylib/CMakeLists.txt b/3rdparty/portmidi/pm_dylib/CMakeLists.txt deleted file mode 100644 index f693dd6511a..00000000000 --- a/3rdparty/portmidi/pm_dylib/CMakeLists.txt +++ /dev/null @@ -1,127 +0,0 @@ -# pm_dylib - -# set the build directory for libraries to be in portmidi, not in -# portmidi/pm_dylib -if(APPLE OR WIN32) - # set the build directory for .dylib libraries - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) - # the "archive" output directory says where to put portmidi.lib, the - # static part of the lib/dll pair: - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) - - # the first time CMake configures, save off CMake's built-in flags - if(NOT DEFAULT_DEBUG_FLAGS) - set(DEFAULT_DEBUG_FLAGS ${CMAKE_C_FLAGS_DEBUG} CACHE - STRING "CMake's default debug flags" FORCE) - set(DEFAULT_RELEASE_FLAGS ${CMAKE_C_FLAGS_RELEASE} CACHE - STRING "CMake's default release flags" FORCE) - else(NOT DEFAULT_DEBUG_FLAGS) - message(STATUS "DEFAULT_DEBUG_FLAGS not nil: " ${DEFAULT_DEBUG_FLAGS}) - endif(NOT DEFAULT_DEBUG_FLAGS) -else(APPLE OR WIN32) - set(LINUX_FLAGS "-DPMALSA") -endif(APPLE OR WIN32) - -macro(prepend_path RESULT PATH) - set(${RESULT}) - foreach(FILE ${ARGN}) - list(APPEND ${RESULT} "${PATH}${FILE}") - endforeach(FILE) -endmacro(prepend_path) - -set(CMAKE_C_FLAGS_DEBUG - "${DEFAULT_DEBUG_FLAGS} -DPM_CHECK_ERRORS=1 -DDEBUG ${LINUX_FLAGS}" - CACHE STRING "enable extra checks for debugging" FORCE) - -set(CMAKE_C_FLAGS_RELEASE "${DEFAULT_RELEASE_FLAGS} ${LINUX_FLAGS}" - CACHE STRING "flags for release version" FORCE) - -# first include the appropriate system-dependent file: -if(UNIX) - # add the -g switch for Linux and Mac OS X (not used in Win32) - set (CMAKE_C_FLAGS_DEBUG "-g ${CMAKE_C_FLAGS_DEBUG}" - CACHE STRING "enable extra checks for debugging" FORCE) - if(APPLE) - set(MACSRC pmmacosxcm pmmac readbinaryplist finddefault) - prepend_path(LIBSRC ../pm_mac/ ${MACSRC}) - list(APPEND LIBSRC ../porttime/ptmacosx_mach) - - include_directories(${CMAKE_OSX_SYSROOT}/Developer/Headers/FlatCarbon) - set(FRAMEWORK_PATH ${CMAKE_OSX_SYSROOT}/System/Library/Frameworks) - set(COREAUDIO_LIB "${FRAMEWORK_PATH}/CoreAudio.framework") - set(COREFOUNDATION_LIB "${FRAMEWORK_PATH}/CoreFoundation.framework") - set(COREMIDI_LIB "${FRAMEWORK_PATH}/CoreMIDI.framework") - set(CORESERVICES_LIB "${FRAMEWORK_PATH}/CoreServices.framework") - set(PM_NEEDED_LIBS ${COREAUDIO_LIB} ${COREFOUNDATION_LIB} - ${COREMIDI_LIB} ${CORESERVICES_LIB} - CACHE INTERNAL "") - - set(JAVAVM_LIB "${FRAMEWORK_PATH}/JavaVM.framework") - set(JAVA_INCLUDE_PATHS ${JAVAVM_LIB}/Headers) - set(INSTALL_NAME_DIR "/usr/local/lib") - message(STATUS "SYSROOT: " ${CMAKE_OSX_SYSROOT}) - else(APPLE) - # LINUX settings... - include(FindJNI) - # message(STATUS "JAVA_JVM_LIB_PATH is " ${JAVA_JVM_LIB_PATH}) - # message(STATUS "JAVA_INCLUDE_PATH is " ${JAVA_INCLUDE_PATH}) - # note: should use JAVA_JVM_LIB_PATH, but it is not set properly - # note: user might need to set JAVA_INCLUDE_PATH manually - # - # this will probably break on BSD and other Unix systems; the fix - # depends on whether FindJNI can find Java or not. If yes, then - # we should try to rely on automatically set JAVA_INCLUDE_PATH and - # JAVA_INCLUDE_PATH2; if no, then we need to make both JAVA_INCLUDE_PATH - # and JAVA_INCLUDE_PATH2 set by user (will need clear documentation - # because JAVA_INCLUDE_PATH2 is pretty obscure) - set(JAVA_INCLUDE_PATH ${JAVA_INCLUDE_PATH-UNKNOWN} - CACHE STRING "where to find Java SDK include directory") - set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH}/linux) - # libjvm.so is found relative to JAVA_INCLUDE_PATH: - set(JAVAVM_LIB ${JAVA_INCLUDE_PATH}/../jre/lib/i386/client/libjvm.so) - - set(LINUXSRC pmlinuxalsa pmlinux finddefault) - prepend_path(LIBSRC ../pm_linux/ ${LINUXSRC}) - list(APPEND LIBSRC ../porttime/ptlinux) - - set(PM_NEEDED_LIBS pthread asound) - endif(APPLE) -else(UNIX) - if(WIN32) - # /MDd is multithread debug DLL, /MTd is multithread debug - # /MD is multithread DLL, /MT is multithread - - include(FindJNI) - # note: should use JAVA_JVM_LIB_PATH, but it is not set properly - set(JAVAVM_LIB ${JAVA_INCLUDE_PATH}/../lib/jvm.lib) - - set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2}) - # message(STATUS "JAVA_INCLUDE_PATHS: " ${JAVA_INCLUDE_PATHS}) - - set(WINSRC pmwin pmwinmm) - prepend_path(LIBSRC ../pm_win/ ${WINSRC}) - list(APPEND LIBSRC ../porttime/ptwinmm) - set(PM_NEEDED_LIBS winmm.lib) - # message(STATUS "JAVAVM_LIB: " ${JAVAVM_LIB}) - endif(WIN32) -endif(UNIX) -set(JNI_EXTRA_LIBS ${PM_NEEDED_LIBS} ${JAVAVM_LIB}) - -# this completes the list of library sources by adding shared code -set(SHARED_FILES pmutil portmidi) -prepend_path(SHARED_PATHS ../pm_common/ ${SHARED_FILES}) -list(APPEND LIBSRC ${SHARED_PATHS}) - -add_library(portmidi-dynamic SHARED ${LIBSRC}) -set_target_properties(portmidi-dynamic PROPERTIES OUTPUT_NAME "portmidi") -target_link_libraries(portmidi-dynamic ${PM_NEEDED_LIBS}) - -# install the libraries (Linux and Mac OS X command line) -if(UNIX) - INSTALL(TARGETS portmidi-dynamic - LIBRARY DESTINATION /usr/local/lib - ARCHIVE DESTINATION /usr/local/lib) - INSTALL(FILES ../pm_common/portmidi.h ../porttime/porttime.h - DESTINATION /usr/local/include) -endif(UNIX) diff --git a/3rdparty/portmidi/pm_dylib/README.txt b/3rdparty/portmidi/pm_dylib/README.txt deleted file mode 100644 index 133a01e94ab..00000000000 --- a/3rdparty/portmidi/pm_dylib/README.txt +++ /dev/null @@ -1,11 +0,0 @@ -pm_dylib - -The purpose of this directory is to provide a separate CMakeLists.txt -file for building a dynamic link library version of portmidi. This -version (in Windows) is linked using the Multithreaded C Runtime DLL -whereas the static library version in ../pm_common uses the (static) -Multithreaded C Runtime. There's no good reason not to build both -versions of portmidi in ../pm_common, but (the current) Cmake -has the restriction that you must either share compiler flags across -configurations (debug and release) or across targets (static and -dynamic). Here, we need individual settings for all combinations. diff --git a/3rdparty/portmidi/pm_dylib/portmidi-dynamic.vcproj b/3rdparty/portmidi/pm_dylib/portmidi-dynamic.vcproj deleted file mode 100644 index eeb83b3aecd..00000000000 --- a/3rdparty/portmidi/pm_dylib/portmidi-dynamic.vcproj +++ /dev/null @@ -1,158 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="portmidi-dynamic" - ProjectGUID="{7283FAD1-7415-4061-A19A-FF5C7BCE9306}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="portmidi-dynamic.dir\Debug" - ConfigurationType="2" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="3" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\",portmidi_dynamic_EXPORTS" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../Debug/portmidi.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\",portmidi_dynamic_EXPORTS"/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\",portmidi_dynamic_EXPORTS" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib winmm.lib " - OutputFile="..\Debug\portmidi.dll" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="..\Debug\portmidi.pdb" - GenerateDebugInformation="TRUE" - ImportLibrary="..\Debug\portmidi.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="portmidi-dynamic.dir\Release" - ConfigurationType="2" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="2" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\",portmidi_dynamic_EXPORTS" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../Release/portmidi.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\",portmidi_dynamic_EXPORTS"/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\",portmidi_dynamic_EXPORTS" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib winmm.lib " - OutputFile="..\Release\portmidi.dll" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="..\Release\portmidi.pdb" - ImportLibrary="..\Release\portmidi.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_win\pmwin.c"> - </File> - <File - RelativePath="..\pm_win\pmwinmm.c"> - </File> - <File - RelativePath="..\porttime\ptwinmm.c"> - </File> - <File - RelativePath="..\pm_common\pmutil.c"> - </File> - <File - RelativePath="..\pm_common\portmidi.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_haiku/pmhaiku.cpp b/3rdparty/portmidi/pm_haiku/pmhaiku.cpp new file mode 100644 index 00000000000..6d21d8c5a67 --- /dev/null +++ b/3rdparty/portmidi/pm_haiku/pmhaiku.cpp @@ -0,0 +1,514 @@ +/* pmhaiku.cpp -- PortMidi os-dependent code */ + +#include <stdio.h> +#include <stdlib.h> +#include <vector> +#include <MidiConsumer.h> +#include <MidiEndpoint.h> +#include <MidiProducer.h> +#include <MidiRoster.h> +#include <MidiSynth.h> +#include "portmidi.h" +#include "pmutil.h" +#include "pminternal.h" + +// as long as Java on Haiku uses ~/.java/... to store user preferences, we can directly reuse the Linux version +// (it shouldn't, see https://github.com/haikuports/haikuports/issues/7119) +extern "C" { +#include "../pm_linux/finddefault.h" +} + +namespace { + struct PmInputConsumer : BMidiLocalConsumer { + PmInputConsumer(PmInternal *midi) : + BMidiLocalConsumer("PortMidi input consumer"), + midi(midi) + { + } + + + void Data(uchar *data, size_t length, bool atomic, bigtime_t time) + { + if (!atomic) + return; // should these be also supported? + + if (data[0] == B_SYS_EX_START) { + pm_read_bytes(midi, data, length, time / 1000); + } else { + PmEvent event; + switch (length) { + case 1: + event.message = Pm_Message(data[0], 0, 0); + break; + case 2: + event.message = Pm_Message(data[0], data[1], 0); + break; + case 3: + event.message = Pm_Message(data[0], data[1], data[2]); + break; + default: + printf("Unexpected message length for short message, got %" B_PRIuSIZE "\n", length); + break; + } + event.timestamp = time / 1000; + pm_read_short(midi, &event); + } + } + + private: + PmInternal *midi; + }; + + struct PmOutputInfo { + BMidiLocalProducer *producer; + std::vector<unsigned char> sysexBuffer; + }; + + struct PmSynthOutputInfo { + BMidiSynth midiSynth; + std::vector<unsigned char> sysexBuffer; + }; + + + PmTimestamp synchronize(PmInternal *midi) + { + return 0; + } + + + PmError in_open(PmInternal *midi, void *driverInfo) + { + int32 endpointID = (int32)(intptr_t)pm_descriptors[midi->device_id].descriptor; + BMidiProducer *producer = BMidiRoster::FindProducer(endpointID); + if (!producer) + return pmInvalidDeviceId; + PmInputConsumer *consumer = new PmInputConsumer(midi); + status_t status = producer->Connect(consumer); + if (status != B_OK) { + consumer->Release(); + producer->Release(); + strcpy(pm_hosterror_text, strerror(status)); + pm_hosterror = TRUE; + return pmHostError; + } + midi->api_info = consumer; + producer->Release(); + return pmNoError; + } + + + PmError in_abort(PmInternal *midi) + { + return pmNoError; + } + + + PmError in_close(PmInternal *midi) + { + int32 endpointID = (int32)(intptr_t)pm_descriptors[midi->device_id].descriptor; + BMidiProducer *producer = BMidiRoster::FindProducer(endpointID); + if (!producer) + return pmInvalidDeviceId; + PmInputConsumer *consumer = (PmInputConsumer*)midi->api_info; + status_t status = producer->Disconnect(consumer); + if (status != B_OK) { + consumer->Release(); + producer->Release(); + strcpy(pm_hosterror_text, strerror(status)); + pm_hosterror = TRUE; + return pmHostError; + } + consumer->Release(); + midi->api_info = NULL; + producer->Release(); + return pmNoError; + } + + + PmError out_open(PmInternal *midi, void *driverInfo) + { + int32 endpointID = (int32)(intptr_t)pm_descriptors[midi->device_id].descriptor; + BMidiConsumer *consumer = BMidiRoster::FindConsumer(endpointID); + if (!consumer) + return pmInvalidDeviceId; + BMidiLocalProducer *producer = new BMidiLocalProducer("PortMidi output producer"); + status_t status = producer->Connect(consumer); + if (status != B_OK) { + consumer->Release(); + producer->Release(); + strcpy(pm_hosterror_text, strerror(status)); + pm_hosterror = TRUE; + return pmHostError; + } + PmOutputInfo *info = new PmOutputInfo; + info->producer = producer; + midi->api_info = info; + consumer->Release(); + return pmNoError; + } + + + PmError out_abort(PmInternal *midi) + { + return pmNoError; + } + + + PmError out_close(PmInternal *midi) + { + int32 endpointID = (int32)(intptr_t)pm_descriptors[midi->device_id].descriptor; + BMidiConsumer *consumer = BMidiRoster::FindConsumer(endpointID); + if (!consumer) + return pmInvalidDeviceId; + PmOutputInfo *info = (PmOutputInfo*)midi->api_info; + status_t status = info->producer->Disconnect(consumer); + if (status != B_OK) { + consumer->Release(); + midi->api_info = NULL; + info->producer->Release(); + delete info; + strcpy(pm_hosterror_text, strerror(status)); + pm_hosterror = TRUE; + return pmHostError; + } + consumer->Release(); + midi->api_info = NULL; + info->producer->Release(); + delete info; + return pmNoError; + } + + + // copied from the macOS implementation + size_t midi_length(uchar status) + { + int high, low; + static size_t high_lengths[] = { + 1, 1, 1, 1, 1, 1, 1, 1, /* 0x00 through 0x70 */ + 3, 3, 3, 3, 2, 2, 3, 1 /* 0x80 through 0xf0 */ + }; + static size_t low_lengths[] = { + 1, 2, 3, 2, 1, 1, 1, 1, /* 0xf0 through 0xf8 */ + 1, 1, 1, 1, 1, 1, 1, 1 /* 0xf9 through 0xff */ + }; + + high = status >> 4; + low = status & 15; + + return (high != 0xF) ? high_lengths[high] : low_lengths[low]; + } + + + PmError write_short(PmInternal *midi, PmEvent *buffer) + { + PmOutputInfo *info = (PmOutputInfo*)midi->api_info; + uchar data[3]; + data[0] = Pm_MessageStatus(buffer->message); + data[1] = Pm_MessageData1(buffer->message); + data[2] = Pm_MessageData2(buffer->message); + size_t length = midi_length(data[0]); + + info->producer->SprayData(data, length, true, buffer->timestamp * 1000); + + // TODO: handle latency != 0 + return pmNoError; + } + + + PmError begin_sysex(PmInternal *midi, PmTimestamp timestamp) + { + PmOutputInfo *info = (PmOutputInfo*)midi->api_info; + info->sysexBuffer.clear(); + return pmNoError; + } + + + PmError end_sysex(PmInternal *midi, PmTimestamp timestamp) + { + PmOutputInfo *info = (PmOutputInfo*)midi->api_info; + info->producer->SpraySystemExclusive(&info->sysexBuffer[0], info->sysexBuffer.size(), timestamp * 1000); + info->sysexBuffer.clear(); + return pmNoError; + } + + + PmError write_byte(PmInternal *midi, unsigned char byte, PmTimestamp timestamp) + { + PmOutputInfo *info = (PmOutputInfo*)midi->api_info; + info->sysexBuffer.push_back(byte); + return pmNoError; + } + + + PmError write_realtime(PmInternal *midi, PmEvent *buffer) + { + PmOutputInfo *info = (PmOutputInfo*)midi->api_info; + info->producer->SpraySystemRealTime(Pm_MessageStatus(buffer->message), buffer->timestamp * 1000); + return pmNoError; + } + + + PmError synth_open(PmInternal *midi, void *driverInfo) + { + PmSynthOutputInfo *info = new PmSynthOutputInfo; + info->midiSynth.EnableInput(true, true); + midi->api_info = info; + return pmNoError; + } + + + PmError synth_abort(PmInternal *midi) + { + return pmNoError; + } + + + PmError synth_close(PmInternal *midi) + { + PmSynthOutputInfo *info = (PmSynthOutputInfo*)midi->api_info; + delete info; + midi->api_info = NULL; + return pmNoError; + } + + + PmError write_short_synth(PmInternal *midi, PmEvent *buffer) + { + PmSynthOutputInfo *info = (PmSynthOutputInfo*)midi->api_info; + uchar data[3]; + data[0] = Pm_MessageStatus(buffer->message); + data[1] = Pm_MessageData1(buffer->message); + data[2] = Pm_MessageData2(buffer->message); + + switch(data[0] & 0xf0) { + case B_NOTE_OFF: + info->midiSynth.NoteOff((data[0] & 0x0f) + 1, data[1], data[2], buffer->timestamp); + break; + case B_NOTE_ON: + info->midiSynth.NoteOn((data[0] & 0x0f) + 1, data[1], data[2], buffer->timestamp); + break; + case B_KEY_PRESSURE: + info->midiSynth.KeyPressure((data[0] & 0x0f + 1), data[1], data[2], buffer->timestamp); + break; + case B_CONTROL_CHANGE: + info->midiSynth.ControlChange((data[0] & 0x0f) + 1, data[1], data[2], buffer->timestamp); + break; + case B_PROGRAM_CHANGE: + info->midiSynth.ProgramChange((data[0] & 0x0f) + 1, data[1], buffer->timestamp); + break; + case B_CHANNEL_PRESSURE: + info->midiSynth.ChannelPressure((data[0] & 0x0f) + 1, data[1], buffer->timestamp); + break; + case B_PITCH_BEND: + info->midiSynth.PitchBend((data[0] & 0x0f) + 1, data[1], data[2], buffer->timestamp); + break; + } + + // TODO: handle latency != 0 + return pmNoError; + } + + + PmError begin_sysex_synth(PmInternal *midi, PmTimestamp timestamp) + { + PmSynthOutputInfo *info = (PmSynthOutputInfo*)midi->api_info; + info->sysexBuffer.clear(); + return pmNoError; + } + + + PmError end_sysex_synth(PmInternal *midi, PmTimestamp timestamp) + { + PmSynthOutputInfo *info = (PmSynthOutputInfo*)midi->api_info; + info->midiSynth.SystemExclusive(&info->sysexBuffer[0], info->sysexBuffer.size(), timestamp); + info->sysexBuffer.clear(); + return pmNoError; + } + + + PmError write_byte_synth(PmInternal *midi, unsigned char byte, PmTimestamp timestamp) + { + PmSynthOutputInfo *info = (PmSynthOutputInfo*)midi->api_info; + info->sysexBuffer.push_back(byte); + return pmNoError; + } + + + PmError write_realtime_synth(PmInternal *midi, PmEvent *buffer) + { + PmSynthOutputInfo *info = (PmSynthOutputInfo*)midi->api_info; + info->midiSynth.SystemRealTime(Pm_MessageStatus(buffer->message), buffer->timestamp); + return pmNoError; + } + + + PmError write_flush(PmInternal *midi, PmTimestamp timestamp) + { + return pmNoError; + } + + + unsigned int check_host_error(PmInternal *midi) + { + return 0; + } + + + pm_fns_node pm_in_dictionary = { + none_write_short, + none_sysex, + none_sysex, + none_write_byte, + none_write_short, + none_write_flush, + synchronize, + in_open, + in_abort, + in_close, + success_poll, + check_host_error + }; + + pm_fns_node pm_out_dictionary = { + write_short, + begin_sysex, + end_sysex, + write_byte, + write_realtime, + write_flush, + synchronize, + out_open, + out_abort, + out_close, + none_poll, + check_host_error + }; + + + pm_fns_node pm_synth_dictionary = { + write_short_synth, + begin_sysex_synth, + end_sysex_synth, + write_byte_synth, + write_realtime_synth, + write_flush, + synchronize, + synth_open, + synth_abort, + synth_close, + none_poll, + check_host_error + }; + + + PmError create_virtual(int is_input, const char *name, void *driverInfo) + { + BMidiEndpoint *endpoint = is_input ? (BMidiEndpoint*)new BMidiLocalProducer(name) : new BMidiLocalConsumer(name); + if (!endpoint->IsValid()) { + endpoint->Release(); + strcpy(pm_hosterror_text, "Endpoint could not be created"); + pm_hosterror = TRUE; + return pmHostError; + } + status_t status = endpoint->Register(); + if (status != B_OK) { + endpoint->Release(); + strcpy(pm_hosterror_text, strerror(status)); + pm_hosterror = TRUE; + return pmHostError; + } + return pm_add_device(const_cast<char*>("Haiku MIDI kit"), name, is_input, TRUE, (void*)(intptr_t)endpoint->ID(), is_input ? &pm_in_dictionary : &pm_out_dictionary); + } + + PmError delete_virtual(PmDeviceID id) + { + int32 endpointID = (int32)(intptr_t)pm_descriptors[id].descriptor; + BMidiEndpoint *endpoint = BMidiRoster::FindEndpoint(endpointID); + //TODO: handle connected producers and consumers + status_t status = endpoint->Unregister(); + // release twice to actually free the endpoint (FindEndpoint increases the ref-count) + endpoint->Release(); + endpoint->Release(); + if (status != B_OK) { + strcpy(pm_hosterror_text, strerror(status)); + pm_hosterror = TRUE; + return pmHostError; + } + return pmNoError; + } + + PmDeviceID pm_default_input_device_id = -1; + PmDeviceID pm_default_output_device_id = -1; +} + +extern "C" { + void pm_init() + { + pm_add_interf(const_cast<char*>("Haiku MIDI kit"), create_virtual, delete_virtual); + + pm_add_device(const_cast<char*>("Haiku MIDI kit"), "Soft Synth", FALSE, FALSE, NULL, &pm_synth_dictionary); + + int32 id = 0; + BMidiEndpoint *endpoint; + + while ((endpoint = BMidiRoster::NextEndpoint(&id)) != NULL) { + bool isInput = endpoint->IsProducer(); + pm_add_device(const_cast<char*>("Haiku MIDI kit"), endpoint->Name(), isInput, FALSE, (void*)(intptr_t)id, isInput ? &pm_in_dictionary : &pm_out_dictionary); + endpoint->Release(); + } + + // the following (default device handling) is copied from the Linux implementation + + // this is set when we return to Pm_Initialize, but we need it + // now in order to (successfully) call Pm_CountDevices() + pm_initialized = TRUE; + pm_default_input_device_id = find_default_device( + const_cast<char*>("/PortMidi/PM_RECOMMENDED_INPUT_DEVICE"), TRUE, + pm_default_input_device_id); + pm_default_output_device_id = find_default_device( + const_cast<char*>("/PortMidi/PM_RECOMMENDED_OUTPUT_DEVICE"), FALSE, + pm_default_output_device_id); + } + + + void pm_term() + { + int i; + for (i = 0; i < pm_descriptor_len; i++) { + PmInternal *midi = pm_descriptors[i].pm_internal; + if (midi && midi->api_info) { + // device is still open, close it + (*midi->dictionary->close)(midi); + } + if (pm_descriptors[i].pub.is_virtual && !pm_descriptors[i].deleted) { + delete_virtual(i); + } + } + } + + + PmDeviceID Pm_GetDefaultInputDeviceID() + { + Pm_Initialize(); + return pm_default_input_device_id; + } + + + PmDeviceID Pm_GetDefaultOutputDeviceID() + { + Pm_Initialize(); + return pm_default_output_device_id; + } + + + void *pm_alloc(size_t s) + { + return malloc(s); + } + + + void pm_free(void *ptr) + { + free(ptr); + } +} diff --git a/3rdparty/portmidi/pm_java/CMakeLists.txt b/3rdparty/portmidi/pm_java/CMakeLists.txt index a3506202792..0bec03f04ae 100644 --- a/3rdparty/portmidi/pm_java/CMakeLists.txt +++ b/3rdparty/portmidi/pm_java/CMakeLists.txt @@ -1,47 +1,86 @@ -# pm_java +# pm_java/CMakeLists.txt -- builds pmjni and pmdefaults program +find_package(Java) +message(STATUS "Java_JAVA_EXECUTABLE is " ${Java_JAVA_EXECUTABLE}) + +if(BUILD_PMDEFAULTS) + # Since pmdefaults and pmdefaults.bat are in the source tree and look + # for libpmjni in the same tree, out-of-source build will not create + # a working pmdefaults (without more work): + if(NOT (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})) + message(WARNING "PmDefaults only works when run in the pm_java/pmdefaults directory after an in-source build. This is an out-of-source build, so [probably] libpmjni will be built out-of-source, pmdefaults.jar will be built in-source, and the pmdefaults[.bat] script remains in-source. Rebuild in-source to use PmDefaults or adjust the file locations and scripts to suit yourself.") + endif() + + set(JPORTMIDICLASS JPortMidi.class JPortMidiException.class + JPortMidiApi.class) + set(PMDEFAULTSCLASS PmDefaultsFrame.class PmDefaults.class) + prepend_path(JPORTMIDIPATH jportmidi/ ${JPORTMIDICLASS}) + prepend_path(PMDEFAULTSPATH pmdefaults/ ${PMDEFAULTSCLASS}) + set(PMDEFAULTS_ALL ${JPORTMIDIPATH} ${PMDEFAULTSPATH}) + + project(pmdefaults NONE) + include(UseJava) + add_jar(pmdefaults + SOURCES pmdefaults/PmDefaults.java pmdefaults/PmDefaultsFrame.java + jportmidi/JPortMidi.java jportmidi/JPortMidiApi.java + jportmidi/JPortMidiException.java + RESOURCES NAMESPACE "." pmdefaults/portmusic_logo.png + MANIFEST pmdefaults/manifest.txt + OUTPUT_DIR pmdefaults) + if(WIN32) + set(JAVAVM_LIB ${JAVA_INCLUDE_PATH}/../jre/lib/i386/client/libjvm.so) + endif() + add_dependencies(pmdefaults pmjni) +endif(BUILD_PMDEFAULTS) + +# Build pmjni +# this CMakeLists.txt is only loaded if BUILD_JAVA_NATIVE_INTERFACE +# This jni library includes portmidi sources to give just +# one library for JPortMidi users to manage rather than two. if(UNIX) - if(APPLE) - # java not dealt with in CMake -- see pm_mac/pm_mac.xcodeproj - else(APPLE) - # linux - set(JPORTMIDICLASS JPortMidi.class JPortMidiException.class - JPortMidiApi.class) - set(PMDEFAULTSCLASS PmDefaultsFrame.class PmDefaults.class) - prepend_path(JPORTMIDICLASS2 jportmidi/ ${JPORTMIDICLASS}) - prepend_path(PMDEFAULTSCLASS2 pmdefaults/ ${PMDEFAULTSCLASS}) - set(PMDEFAULTS_ALL_CLASSES ${JPORTMIDICLASS2} ${PMDEFAULTSCLASS2}) - # message(STATUS "PMDEFAULTS_ALL_CLASSES is " ${PMDEFAULTS_ALL_CLASSES}) - add_custom_command(OUTPUT pmdefaults/PmDefaultsFrame.class - COMMAND javac -classpath . pmdefaults/PmDefaultsFrame.java - MAIN_DEPENDENCY pmdefaults/PmDefaultsFrame.java - DEPENDS pmdefaults/PmDefaults.java - WORKING_DIRECTORY pm_java) - add_custom_command(OUTPUT pmdefaults/PmDefaults.class - COMMAND javac -classpath . pmdefaults/PmDefaults.java - MAIN_DEPENDENCY pmdefaults/PmDefaults.java - DEPENDS pmdefaults/PmDefaultsFrame.java - WORKING_DIRECTORY pm_java) - add_custom_command(OUTPUT ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pmdefaults.jar - COMMAND cp pmdefaults/portmusic_logo.png . - COMMAND jar cmf pmdefaults/manifest.txt pmdefaults.jar - pmdefaults/*.class portmusic_logo.png jportmidi/*.class - COMMAND chmod +x pmdefaults/pmdefaults - COMMAND cp pmdefaults/pmdefaults ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} - COMMAND mv pmdefaults.jar ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} - COMMAND rm portmusic_logo.png - MAIN_DEPENDENCY pmdefaults/PmDefaults.class - DEPENDS ${PMDEFAULTS_ALL_CLASSES} - WORKING_DIRECTORY pm_java) - add_custom_target(pmdefaults_target ALL - DEPENDS ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pmdefaults.jar) - # message(STATUS "add_custom_target: pmdefaults.jar") - - # install the libraries (Linux only) - INSTALL(FILES ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pmdefaults.jar - DESTINATION /usr/share/java) - INSTALL(PROGRAMS ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pmdefaults - DESTINATION /usr/local/bin) - endif(APPLE) -endif(UNIX) -# In windows, use pm_java/make.bat + include(FindJNI) + # message(STATUS "JAVA_JVM_LIB_PATH is " ${JAVA_JVM_LIB_PATH}) + # message(STATUS "JAVA_INCLUDE_PATH is " ${JAVA_INCLUDE_PATH}) + # note: should use JAVA_JVM_LIB_PATH, but it is not set properly + # note: user might need to set JAVA_INCLUDE_PATH manually + # + # this will probably break on BSD and other Unix systems; the fix + # depends on whether FindJNI can find Java or not. If yes, then + # we should try to rely on automatically set JAVA_INCLUDE_PATH and + # JAVA_INCLUDE_PATH2; if no, then we need to make both JAVA_INCLUDE_PATH + # and JAVA_INCLUDE_PATH2 set by user (will need clear documentation + # because JAVA_INCLUDE_PATH2 is pretty obscure) + set(JAVA_INCLUDE_PATH ${JAVA_INCLUDE_PATH-UNKNOWN} + CACHE STRING "where to find Java SDK include directory") + # libjvm.so is found relative to JAVA_INCLUDE_PATH: + if (HAIKU) + set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH}/haiku) + else() + set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH}/linux) + endif() +elseif(WIN32) + include(FindJNI) + # note: should use JAVA_JVM_LIB_PATH, but it is not set properly + set(JAVAVM_LIB ${JAVA_INCLUDE_PATH}/../lib/jvm.lib) + + set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2}) + # message(STATUS "JAVA_INCLUDE_PATHS: " ${JAVA_INCLUDE_PATHS}) + # message(STATUS "JAVAVM_LIB: " ${JAVAVM_LIB}) +endif() + +add_library(pmjni SHARED pmjni/pmjni.c) +target_sources(pmjni PRIVATE ${PM_LIB_PUBLIC_SRC} ${PM_LIB_PRIVATE_SRC}) +message(STATUS "Java paths ${JAVA_INCLUDE_PATHS}") +# message(STATUS "Java pmjni src: pmjni/pmjni.c ${PM_LIB_SHARED_SRC} " +# "${PM_LIB_PRIVATE_SRC}") +target_include_directories(pmjni PUBLIC ${JAVA_INCLUDE_PATHS}) +target_link_libraries(pmjni ${PM_NEEDED_LIBS}) +set_target_properties(pmjni PROPERTIES + VERSION ${LIBRARY_VERSION} + SOVERSION ${LIBRARY_SOVERSION} + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" + EXECUTABLE_EXTENSION "jnilib" + MACOSX_RPATH ON) + diff --git a/3rdparty/portmidi/pm_java/JavaExe.exe b/3rdparty/portmidi/pm_java/JavaExe.exe Binary files differdeleted file mode 100644 index 8886d2e8672..00000000000 --- a/3rdparty/portmidi/pm_java/JavaExe.exe +++ /dev/null diff --git a/3rdparty/portmidi/pm_java/README.txt b/3rdparty/portmidi/pm_java/README.txt index 44c6fab4508..bf0d73768b2 100644 --- a/3rdparty/portmidi/pm_java/README.txt +++ b/3rdparty/portmidi/pm_java/README.txt @@ -1,33 +1,70 @@ README.txt Roger B. Dannenberg 16 Jun 2009 +updated 2021 -This directory was created to implement PmDefaults, a program to -set default input and output devices for PortMidi applications. +This directory implements a JNI library so that Java programs can use +the PortMidi API. This was mainly created to implement PmDefaults, a +program to set default input and output devices for PortMidi +applications. -There are three main sub-projects here: - 1) pmjni -- a JNI (Java Native Interface) to access PortMidi - 2) jportmidi -- a Java class to access PortMidi (uses pmjni) - 3) pmdefaults -- the PmDefaults application (uses jportmidi) +PmDefaults never found much use. I recommend you implement +per-application preferences and store default PortMidi device +numbers for input and output there. (Or better yet, store +device *names* since numbers can change if you plug in or +remove USB devices.) -For Mac OS X, you should build the PmDefaults application in Xcode. +Even without PmDefaults, a PortMidi API for Java is probably an +improvement over other Java libraries, but there is very little MIDI +development in Java, so I have not maintained this API. The only thing +probably seriously wrong now is an interface to the +Pm_CreateVirtualInput and Pm_CreateVirtualOutput functions, which are +new additions. -For Win32, an installer for PmDefaults is included in setup/. -To build from sources, you should first build everything including -the portmidi dll (that will be used by the Java application) using -Visual C++ and a provided .sln file in the portmidi home directory. -Then, run make.bat in this directory. The subdirectory win32 will be -created with the application pmdefaults.exe. You can run this application -in the normal way. To move the application, you need to copy *everything* -in win32. To build setup/pmdefaults-setup.exe, I have used both -Setup Generator from Gentee software and Inno Setup from jrsoftware.org. -A script for Inno Setup is included in this directory, but since paths -seem to be absolute, you will have to adjust the paths in the script -before you use it. +I will leave the code here, and if there is a demand, please either +update it or let your needs be known. Perhaps I or someone can help. + +================================================================== ----- implementation notes ---- +BUILDING PmDefaults PROGRAM -For windows, we use the free software JavaExe.exe. The copy here was +You must have a JDK installed (Java development kit including javac +(the Java compiler), jni.h, etc. + +Test java on the command line, e.g., type: javac -version + +Enable these options in the main CMakeLists.txt file (run CMake +from your top-level repository directory): + BUILD_JAVA_NATIVE_INTERFACE + BUILD_PMDEFAULTS +In my Ubuntu linux with jdk-15, ccmake was unable to find my JDK, so +I have to manually set CMake variables as follows (type 't' to see +these in ccmake): + JAVA_AWT_INCLUDE_PATH /usr/lib/jvm/jdk-15/include + JAVA_AWT_LIBRARY /usr/lib/jvm/jdk-15/lib + JAVA_INCLUDE_PATH /usr/lib/jvm/jdk-15/include + JAVA_INCLUDE_PATH2 /usr/lib/jvm/jdk-15/include + JAVA_JVM_LIBRARY /usr/lib/jvm/jdk-15/lib +Of course, your paths may differ. + + +RUNNING PmDefaults PROGRAM + +After building the pmdefaults target with make, Visual Studio, or Xcode: +In Windows: + [from the command line:] + cd portmidi\pm_java\pmdefaults -- change to this directory + pmdefaults -- runs pmdefaults.bat + [or from the finder:] + double-click on pmdefaults.bat +In macOS and Linux: + cd portmidi\pm_java\pmdefaults -- change to this directory + ./pmdefaults -- shell script to invoke java + + +---- old implementation notes ---- + +For Windows, we use the free software JavaExe.exe. The copy here was downloaded from http://software.techrepublic.com.com/abstract.aspx?kw=javaexe&docid=767485 @@ -40,9 +77,3 @@ Java application jar file and then *renaming* JavaExe.exe to the name of the jar file, but keeping the .exe extension. (See make.bat for this step.) Documentation for JavaExe can be obtained by downloading the whole program from the URL(s) above. - - - - - - diff --git a/3rdparty/portmidi/pm_java/UpdateRsrcJavaExe.exe b/3rdparty/portmidi/pm_java/UpdateRsrcJavaExe.exe Binary files differdeleted file mode 100644 index 492ec1679ea..00000000000 --- a/3rdparty/portmidi/pm_java/UpdateRsrcJavaExe.exe +++ /dev/null diff --git a/3rdparty/portmidi/pm_java/jportmidi/JPortMidi.java b/3rdparty/portmidi/pm_java/jportmidi/JPortMidi.java index dd3cc2a1c3a..7116e19640a 100644 --- a/3rdparty/portmidi/pm_java/jportmidi/JPortMidi.java +++ b/3rdparty/portmidi/pm_java/jportmidi/JPortMidi.java @@ -77,7 +77,9 @@ public class JPortMidi { throw new JPortMidiException(pmStreamOpen, "RefreshDeviceLists called while stream is open"); } + if (trace) System.out.println("Pm_Terminate"); checkError(pm.Pm_Terminate()); + if (trace) System.out.println("Pm_Initialize"); checkError(pm.Pm_Initialize()); } diff --git a/3rdparty/portmidi/pm_java/mac-make.sh b/3rdparty/portmidi/pm_java/mac-make.sh deleted file mode 100644 index e5e9592b0a0..00000000000 --- a/3rdparty/portmidi/pm_java/mac-make.sh +++ /dev/null @@ -1,26 +0,0 @@ -# script to build a jar file to run PmDefaults from the command line on OS X -# (This is for debugging. Normally, you would use XCode to build PmDefaults.app.) - -# Compile the java Portidi interface classes. -javac jportmidi/*.java - -# Compile the pmdefaults application. -javac -classpath . pmdefaults/*.java - -# Temporarily copy the portmusic_logo.png file here to add to the jar file. -cp pmdefaults/portmusic_logo.png . - -# Create a directory to hold the distribution. -mkdir mac-osx - -# Copy the interface DLL to the distribution directory. -cp ../Release/libpmjni.dylib mac-osx - -# Create a java archive (jar) file of the distribution. -jar cmf pmdefaults/manifest.txt mac-osx/pmdefaults.jar pmdefaults/*.class portmusic_logo.png jportmidi/*.class - -# Clean up the temporary image file now that it is in the jar file. -rm portmusic_logo.png - -echo "You now have a jar file in mac-osx" - diff --git a/3rdparty/portmidi/pm_java/pmdefaults-setup-script.iss b/3rdparty/portmidi/pm_java/pmdefaults-setup-script.iss deleted file mode 100644 index c7fe5f57e34..00000000000 --- a/3rdparty/portmidi/pm_java/pmdefaults-setup-script.iss +++ /dev/null @@ -1,44 +0,0 @@ -; Script generated by the Inno Setup Script Wizard. -; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! - -[Setup] -; NOTE: The value of AppId uniquely identifies this application. -; Do not use the same AppId value in installers for other applications. -; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) -AppId={{5094958B-3CD7-4780-A883-69C9E5B95AEF} -AppName=PmDefaults -AppVerName=PmDefaults -AppPublisher=Roger Dannenberg - Carnegie Mellon University -AppPublisherURL=http://portmedia.sourceforge.net/ -AppSupportURL=http://portmedia.sourceforge.net/ -AppUpdatesURL=http://portmedia.sourceforge.net/ -DefaultDirName={pf}\PmDefaults -DefaultGroupName=PmDefaults -LicenseFile=C:\Users\rbd\portmedia\portmidi\pm_java\win32\license.txt -OutputBaseFilename=setup -SetupIconFile=C:\Users\rbd\portmedia\portmidi\pm_java\pmdefaults\pmdefaults.ico -Compression=lzma -SolidCompression=yes - -[Languages] -Name: "english"; MessagesFile: "compiler:Default.isl" - -[Tasks] -Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked -Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked - -[Files] -Source: "C:\Users\rbd\portmedia\portmidi\pm_java\win32\pmdefaults.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\rbd\portmedia\portmidi\pm_java\win32\pmdefaults.jar"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\rbd\portmedia\portmidi\pm_java\win32\pmjni.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\rbd\portmedia\portmidi\pm_java\win32\license.txt"; DestDir: "{app}"; Flags: ignoreversion -; NOTE: Don't use "Flags: ignoreversion" on any shared system files - -[Icons] -Name: "{group}\PmDefaults"; Filename: "{app}\pmdefaults.exe" -Name: "{commondesktop}\PmDefaults"; Filename: "{app}\pmdefaults.exe"; Tasks: desktopicon -Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\PmDefaults"; Filename: "{app}\pmdefaults.exe"; Tasks: quicklaunchicon - -[Run] -Filename: "{app}\pmdefaults.exe"; Description: "{cm:LaunchProgram,PmDefaults}"; Flags: nowait postinstall skipifsilent - diff --git a/3rdparty/portmidi/pm_java/pmdefaults/PmDefaults.java b/3rdparty/portmidi/pm_java/pmdefaults/PmDefaults.java index 20708fc9b66..4cfdb9da96a 100644 --- a/3rdparty/portmidi/pm_java/pmdefaults/PmDefaults.java +++ b/3rdparty/portmidi/pm_java/pmdefaults/PmDefaults.java @@ -1,11 +1,15 @@ // PmDefaults -- a small application to set PortMIDI default input/output package pmdefaults; +import javax.swing.SwingUtilities; public class PmDefaults { public static void main(String[] args) { System.out.println("starting main"); - new PmDefaultsFrame("PortMIDI Setup"); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + new PmDefaultsFrame("PortMIDI Setup"); + } + }); } } - diff --git a/3rdparty/portmidi/pm_java/pmdefaults/README.txt b/3rdparty/portmidi/pm_java/pmdefaults/README.txt index e0a4d4b40e8..39fa1fd2c2f 100644 --- a/3rdparty/portmidi/pm_java/pmdefaults/README.txt +++ b/3rdparty/portmidi/pm_java/pmdefaults/README.txt @@ -2,20 +2,19 @@ README.txt Roger B. Dannenberg 2 Jan 2009 -PmDefaults is a program to set default input and output devices for PortMidi -applications. After running the PmDefaults program and choosing devices, -identifiers for these devices will be returned by -Pm_GetDefaultInputDeviceID() and Pm_GetDefaultOutputDeviceID(). +PmDefaults is a program to set default input and output devices for +PortMidi applications. After running the PmDefaults program and +choosing devices, identifiers for these devices will be returned by +calls (within any program) to Pm_GetDefaultInputDeviceID() and +Pm_GetDefaultOutputDeviceID(). Included in this directory are: manifest.txt -- used in pmdefaults.jar -pmdefaults-icon.* -- various icons for applications -pmdefaults-license.txt -- a version of portmidi/license.txt formatted for - the windows installer +pmdefaults-license.txt -- license text +pmdefaults-icon.{bmp,xcf,png,gif} -- icons +pmdefaults.{ico,icns} - icons portmusic_logo.png -- a logo displayed by the pmdefaults application -readme-win32.txt -- this becomes the readme file for the pmdefaults - application. It is copied to win32/README.txt by make.bat -TO BUILD THE APPLICATION: see ../README.txt +TO BUILD AND RUN THE APPLICATION: see ../README.txt diff --git a/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults b/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults index 80162469ae0..fb01fbf0f67 100644 --- a/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults +++ b/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults @@ -1 +1,8 @@ -java -jar /usr/share/java/pmdefaults.jar > /dev/null +#!/bin/sh +# Run PmDefaults, the GUI to select default MIDI input and output for PortMidi +# Due to the locations of the .jar file and libpmjni, this script only runs +# from <portmidi-repo-path>/pm_java/pmdefaults. PmDefaults is minimally +# supported -- if you would like it to appear as an app on your desktop, +# contact the developer(s) and let us know it's actually being used. +# library path here includes directory locations for macOS and Linux. +java -Djava.library.path=../../Release:../../Debug:../.. -jar pmdefaults.jar > /dev/null diff --git a/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults-license.txt b/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults-license.txt index 317f70e0eb6..703923c25b9 100644 --- a/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults-license.txt +++ b/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults-license.txt @@ -3,8 +3,6 @@ LICENSE INFORMATION PmDefaults is a small program to set default MIDI input and output devices for other programs using the PortMidi library. -Latest version available at: http://sourceforge.net/projects/portmedia - Copyright (c) 1999-2000 Ross Bencina and Phil Burk Copyright (c) 2001-2009 Roger B. Dannenberg diff --git a/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults.bat b/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults.bat new file mode 100644 index 00000000000..7ebfdf75e08 --- /dev/null +++ b/3rdparty/portmidi/pm_java/pmdefaults/pmdefaults.bat @@ -0,0 +1 @@ +java -Djava.library.path="../../Release;../../Debug" -jar pmdefaults.jar diff --git a/3rdparty/portmidi/pm_java/pmdefaults/readme-win32.txt b/3rdparty/portmidi/pm_java/pmdefaults/readme-win32.txt deleted file mode 100644 index 5ff168bd715..00000000000 --- a/3rdparty/portmidi/pm_java/pmdefaults/readme-win32.txt +++ /dev/null @@ -1,11 +0,0 @@ -README.txt -Roger B. Dannenberg -1 Jan 2009 - -This directory contains files that implement: - -pmdefaults -- a program to set PortMidi default input/output devices - -You can copy and rename this *whole directory* to move the application -to a convenient place. The application to run is pmdefaults.exe. - diff --git a/3rdparty/portmidi/pm_java/pmjni/pmjni-VC8.vcproj b/3rdparty/portmidi/pm_java/pmjni/pmjni-VC8.vcproj deleted file mode 100644 index 1b42bfac9bd..00000000000 --- a/3rdparty/portmidi/pm_java/pmjni/pmjni-VC8.vcproj +++ /dev/null @@ -1,225 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="8.00" - Name="pmjni" - ProjectGUID="{7AA255C8-48BF-40AC-97BA-F7E7BA4DDAA8}" - RootNamespace="pmjni" - Keyword="Win32Proj" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="$(SolutionDir)$(ConfigurationName)" - IntermediateDirectory="$(ConfigurationName)" - ConfigurationType="2" - CharacterSet="2" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories=""$(SolutionDir)\pm_common";"$(SolutionDir)\porttime";"$(ProjectDir)";"E:\Program Files\Java\jdk1.5.0_14\include";"E:\Program Files\Java\jdk1.5.0_14\include\win32"" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PMJNI_EXPORTS" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="winmm.lib" - LinkIncremental="2" - GenerateDebugInformation="true" - SubSystem="2" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCWebDeploymentTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="$(SolutionDir)$(ConfigurationName)" - IntermediateDirectory="$(ConfigurationName)" - ConfigurationType="2" - CharacterSet="2" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=""$(SolutionDir)\pm_common";"$(SolutionDir)\porttime";"$(ProjectDir)";"E:\Program Files\Java\jdk1.5.0_14\include";"E:\Program Files\Java\jdk1.5.0_14\include\win32"" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PMJNI_EXPORTS" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="winmm.lib" - LinkIncremental="1" - GenerateDebugInformation="true" - SubSystem="2" - OptimizeReferences="2" - EnableCOMDATFolding="2" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCWebDeploymentTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File - RelativePath=".\pmjni.c" - > - </File> - <File - RelativePath="..\..\pm_common\pmutil.c" - > - </File> - <File - RelativePath="..\..\pm_win\pmwin.c" - > - </File> - <File - RelativePath="..\..\pm_win\pmwinmm.c" - > - </File> - <File - RelativePath="..\..\pm_common\portmidi.c" - > - </File> - <File - RelativePath="..\..\porttime\porttime.c" - > - </File> - <File - RelativePath="..\..\porttime\ptwinmm.c" - > - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_java/pmjni/pmjni.c b/3rdparty/portmidi/pm_java/pmjni/pmjni.c index 95e51dda4c5..c60cffb45eb 100644 --- a/3rdparty/portmidi/pm_java/pmjni/pmjni.c +++ b/3rdparty/portmidi/pm_java/pmjni/pmjni.c @@ -13,11 +13,11 @@ // the size of a pointer. Finally cast int to pointer. All this // is supposed to avoid C compiler warnings and (worse) losing // address bits. -#define PMSTREAM(obj, fid) ((PmStream *) (long) (*env)->GetLongField(env, obj, fid)) +#define PMSTREAM(obj, fid) ((PmStream *) (intptr_t) (*env)->GetLongField(env, obj, fid)) // Cast stream to long to convert integer to pointer, then expand // integer to 64-bit jlong. This avoids compiler warnings. #define SET_PMSTREAM(obj, fid, stream) \ - (*env)->SetLongField(env, obj, fid, (jlong) (long) stream) + (*env)->SetLongField(env, obj, fid, (jlong) (intptr_t) stream) /* diff --git a/3rdparty/portmidi/pm_java/setup/pmdefaults-setup.exe b/3rdparty/portmidi/pm_java/setup/pmdefaults-setup.exe Binary files differdeleted file mode 100644 index 78ef52c3e44..00000000000 --- a/3rdparty/portmidi/pm_java/setup/pmdefaults-setup.exe +++ /dev/null diff --git a/3rdparty/portmidi/pm_linux/README_LINUX.txt b/3rdparty/portmidi/pm_linux/README_LINUX.txt index 818793e570f..cfbc43f571a 100644 --- a/3rdparty/portmidi/pm_linux/README_LINUX.txt +++ b/3rdparty/portmidi/pm_linux/README_LINUX.txt @@ -1,45 +1,25 @@ README_LINUX.txt for PortMidi Roger Dannenberg -14 Oct 2009 +6 Dec 2012, revised May 2022 -To make PortMidi, you need cmake and the Java SDK. -Go back up to the portmidi directory and type: +Contents: + To make PortMidi + The pmdefaults program + Setting LD_LIBRARY_PATH + A note about amd64 + Using autoconf + Using configure + Changelog -ccmake . -Type 'c' (configure) and then 'g' (generate). You may have -to manually set JAVA_INCLUDE_PATH and JAVA_JVM_LIBRARY -by typing 't' (toggle to advanced mode) and using the -editor to change the fields. You can find possible values -for JAVA_INCLUDE_PATH by typing "locate jni.h", and for -JAVA_JVM_LIBRARY by typing locate libjvm". - -You also need JAVA_INCLUDE_PATH2, but this will normally -be set automatically after you set JAVA_INCLUDE_PATH and -run "configure" (type "c" to ccmake). Normally, -JAVA_INCLUDE_PATH2 is the linux subdirectory within -JAVA_INCLUDE_PATH. - -Notice that the CMAKE_BUILD_TYPE can be Debug or Release. -Stick with Release if you are not debugging. - -After successfully generating make files with ccmake, you -can run make: - -make - -The Makefile will build all test programs and the portmidi -library. For experimental software, -especially programs running from the command line, we -recommend using the Debug version -- it will terminate your -program and print a helpful message if any PortMidi -function returns an error code. (Released software should -check for error codes and handle them, but for quick, -non-critical projects, the automatic "print and die" -handling can save some work.) +See ../README.md for general instructions. THE pmdefaults PROGRAM +(This may be obsolete. It is older than `../README.md` which +also discusses pmdefaults, and Java support may be removed +unless someone claims they use it... -RBD) + You should install pmdefaults. It provides a graphical interface for selecting default MIDI IN and OUT devices so that you don't have to build device selection interfaces into all your programs @@ -72,7 +52,7 @@ export LD_LIBRARY_PATH A NOTE ABOUT AMD64: -When compiling portmidi under linux on an AMD64, I had to add the -fPIC +When compiling portmidi under linux on an AMD64, I had to add the -fPIC flag to the gcc flags. Reason: when trying to build John Harrison's pyPortMidi gcc bailed out @@ -90,6 +70,12 @@ be "PIC-enabled". CHANGELOG +27-may-2022 Roger B. Dannenberg + Some updates to this file. + +6-dec-2012 Roger B. Dannenberg + Copied notes on Autoconf from Audacity sources + 22-jan-2010 Roger B. Dannenberg Updated instructions about Java paths diff --git a/3rdparty/portmidi/pm_linux/finddefault.c b/3rdparty/portmidi/pm_linux/finddefault.c index c3077701a60..6189a8b7148 100644 --- a/3rdparty/portmidi/pm_linux/finddefault.c +++ b/3rdparty/portmidi/pm_linux/finddefault.c @@ -7,8 +7,9 @@ #include <string.h> #include <ctype.h> #include "portmidi.h" - -extern int pm_find_default_device(char *pattern, int is_input); +#include "pmutil.h" +#include "pminternal.h" +#include "finddefault.h" #define STRING_MAX 256 @@ -21,7 +22,7 @@ void skip_spaces(FILE *inf) } /* trim leading spaces and match a string */ -int match_string(FILE *inf, char *s) +int match_string(FILE *inf, const char *s) { skip_spaces(inf); while (*s && *s == getc(inf)) s++; @@ -29,19 +30,21 @@ int match_string(FILE *inf, char *s) } -/* Parse preference files, find default device, search devices -- +/* + Parse preference files, find default device, search devices -- */ -PmDeviceID find_default_device(char *path, int input, PmDeviceID id) +PmDeviceID find_default_device(const char *path, int input, PmDeviceID id) /* path -- the name of the preference we are searching for input -- true iff this is an input device id -- current default device id returns matching device id if found, otherwise id */ { - static char *pref_2 = (char *)"/.java/.userPrefs/"; - static char *pref_3 = (char *)"prefs.xml"; - char *pref_1 = getenv("HOME"); - char *full_name, *path_ptr; + static char const *const pref_2 = "/.java/.userPrefs/"; + static char const *const pref_3 = "prefs.xml"; + const char *pref_1 = getenv("HOME"); + const char *path_ptr; + char *full_name; FILE *inf; int c, i; if (!pref_1) goto nopref; // cannot find preference file @@ -54,8 +57,8 @@ PmDeviceID find_default_device(char *path, int input, PmDeviceID id) if (*path == '/') path++; // skip initial slash in path path_ptr = strrchr(path, '/'); if (path_ptr) { // copy up to slash after full_name - path_ptr++; int offset = strlen(full_name); + path_ptr++; memcpy(full_name + offset, path, path_ptr - path); full_name[offset + path_ptr - path] = 0; // end of string } else { @@ -63,7 +66,6 @@ PmDeviceID find_default_device(char *path, int input, PmDeviceID id) } strcat(full_name, pref_3); inf = fopen(full_name, "r"); - free(full_name); if (!inf) goto nopref; // cannot open preference file // We're not going to build or link in a full XML parser. // Instead, find the path string and quoute. Then, look for @@ -74,9 +76,9 @@ PmDeviceID find_default_device(char *path, int input, PmDeviceID id) // look for quote string quote if (!match_string(inf, path_ptr)) continue; // path not found if (getc(inf) != '"') continue; // path not found, keep scanning - if (!match_string(inf, (char *)"value")) goto nopref; // value not found - if (!match_string(inf, (char *)"=")) goto nopref; // = not found - if (!match_string(inf, (char *)"\"")) goto nopref; // quote not found + if (!match_string(inf, "value")) goto nopref; // value not found + if (!match_string(inf, "=")) goto nopref; // = not found + if (!match_string(inf, "\"")) goto nopref; // quote not found // now read the value up to the close quote for (i = 0; i < STRING_MAX; i++) { if ((c = getc(inf)) == '"') break; diff --git a/3rdparty/portmidi/pm_linux/finddefault.h b/3rdparty/portmidi/pm_linux/finddefault.h new file mode 100644 index 00000000000..4599fff8697 --- /dev/null +++ b/3rdparty/portmidi/pm_linux/finddefault.h @@ -0,0 +1,5 @@ +/* finddefault.h -- find_default_device() declaration + Roger Dannenberg, Jan 2021 +*/ + +PmDeviceID find_default_device(const char *path, int input, PmDeviceID id); diff --git a/3rdparty/portmidi/pm_linux/pmlinux.c b/3rdparty/portmidi/pm_linux/pmlinux.c index b05c54fccb9..05ac332c368 100644 --- a/3rdparty/portmidi/pm_linux/pmlinux.c +++ b/3rdparty/portmidi/pm_linux/pmlinux.c @@ -14,6 +14,7 @@ #include "portmidi.h" #include "pmutil.h" #include "pminternal.h" +#include "finddefault.h" #ifdef PMALSA #include "pmlinuxalsa.h" @@ -23,32 +24,34 @@ #include "pmlinuxnull.h" #endif +#if !(defined(PMALSA) || defined(PMNULL)) +#error One of PMALSA or PMNULL must be defined +#endif + PmDeviceID pm_default_input_device_id = -1; PmDeviceID pm_default_output_device_id = -1; -extern PmDeviceID find_default_device(char *path, int input, PmDeviceID id); - -void pm_init() +void pm_init(void) { /* Note: it is not an error for PMALSA to fail to initialize. * It may be a design error that the client cannot query what subsystems * are working properly other than by looking at the list of available * devices. */ - #ifdef PMALSA - pm_linuxalsa_init(); - #endif - #ifdef PMNULL +#ifdef PMALSA + pm_linuxalsa_init(); +#endif +#ifdef PMNULL pm_linuxnull_init(); - #endif +#endif // this is set when we return to Pm_Initialize, but we need it // now in order to (successfully) call Pm_CountDevices() pm_initialized = TRUE; pm_default_input_device_id = find_default_device( - (char *)"/PortMidi/PM_RECOMMENDED_INPUT_DEVICE", TRUE, + "/PortMidi/PM_RECOMMENDED_INPUT_DEVICE", TRUE, pm_default_input_device_id); pm_default_output_device_id = find_default_device( - (char *)"/PortMidi/PM_RECOMMENDED_OUTPUT_DEVICE", FALSE, + "/PortMidi/PM_RECOMMENDED_OUTPUT_DEVICE", FALSE, pm_default_output_device_id); } @@ -57,14 +60,17 @@ void pm_term(void) #ifdef PMALSA pm_linuxalsa_term(); #endif + #ifdef PMNULL + pm_linuxnull_term(); + #endif } -PmDeviceID Pm_GetDefaultInputDeviceID() { +PmDeviceID Pm_GetDefaultInputDeviceID(void) { Pm_Initialize(); return pm_default_input_device_id; } -PmDeviceID Pm_GetDefaultOutputDeviceID() { +PmDeviceID Pm_GetDefaultOutputDeviceID(void) { Pm_Initialize(); return pm_default_output_device_id; } diff --git a/3rdparty/portmidi/pm_linux/pmlinuxalsa.c b/3rdparty/portmidi/pm_linux/pmlinuxalsa.c index 9ca2cf72adf..62b82d73b25 100644 --- a/3rdparty/portmidi/pm_linux/pmlinuxalsa.c +++ b/3rdparty/portmidi/pm_linux/pmlinuxalsa.c @@ -7,6 +7,11 @@ * Jason Cohen, Rico Colon, Matt Filippone (Alsa 0.5.x implementation) */ +/* omit this code if PMALSA is not defined -- this mechanism allows + * selection of different MIDI interfaces (at compile time). + */ +#ifdef PMALSA + #include "stdlib.h" #include "portmidi.h" #include "pmutil.h" @@ -15,16 +20,8 @@ #include "string.h" #include "porttime.h" #include "pmlinux.h" -#include <alsa/asoundlib.h> - -typedef unsigned int UINT32; -__extension__ typedef unsigned long long UINT64; -#ifdef PTR64 -typedef UINT64 FPTR; -#else -typedef UINT32 FPTR; -#endif +#include <alsa/asoundlib.h> /* I used many print statements to debug this code. I left them in the * source, and you can turn them on by changing false to true below: @@ -40,10 +37,9 @@ typedef UINT32 FPTR; #endif /* to store client/port in the device descriptor */ - -#define MAKE_DESCRIPTOR(client, port) ((void*)(FPTR)(((client) << 8) | (port))) -#define GET_DESCRIPTOR_CLIENT(info) ((((int)(FPTR)(info)) >> 8) & 0xff) -#define GET_DESCRIPTOR_PORT(info) (((int)(FPTR)(info)) & 0xff) +#define MAKE_DESCRIPTOR(client, port) ((void*)(long)(((client) << 8) | (port))) +#define GET_DESCRIPTOR_CLIENT(info) ((((long)(info)) >> 8) & 0xff) +#define GET_DESCRIPTOR_PORT(info) (((long)(info)) & 0xff) #define BYTE unsigned char @@ -54,14 +50,16 @@ static snd_seq_t *seq = NULL; // all input comes here, // output queue allocated on seq static int queue, queue_used; /* one for all ports, reference counted */ -typedef struct alsa_descriptor_struct { +#define PORT_IS_CLOSED -999999 + +typedef struct alsa_info_struct { + int is_virtual; int client; int port; int this_port; int in_sysex; snd_midi_event_t *parser; - int error; /* host error code */ -} alsa_descriptor_node, *alsa_descriptor_type; +} alsa_info_node, *alsa_info_type; /* get_alsa_error_text -- copy error text to potentially short string */ @@ -69,36 +67,45 @@ typedef struct alsa_descriptor_struct { static void get_alsa_error_text(char *msg, int len, int err) { int errlen = strlen(snd_strerror(err)); - if (errlen < len) { + if (errlen > 0 && errlen < len) { strcpy(msg, snd_strerror(err)); } else if (len > 20) { sprintf(msg, "Alsa error %d", err); - } else if (len > 4) { - strcpy(msg, "Alsa"); } else { msg[0] = 0; } } +static PmError check_hosterror(int err) +{ + if (err < 0) { + get_alsa_error_text(pm_hosterror_text, PM_HOST_ERROR_MSG_LEN, err); + pm_hosterror = TRUE; + return pmHostError; + } + return pmNoError; +} + + /* queue is shared by both input and output, reference counted */ static PmError alsa_use_queue(void) { + int err = 0; if (queue_used == 0) { snd_seq_queue_tempo_t *tempo; queue = snd_seq_alloc_queue(seq); if (queue < 0) { - pm_hosterror = queue; - return pmHostError; + return check_hosterror(queue); } snd_seq_queue_tempo_alloca(&tempo); snd_seq_queue_tempo_set_tempo(tempo, 480000); snd_seq_queue_tempo_set_ppq(tempo, 480); - pm_hosterror = snd_seq_set_queue_tempo(seq, queue, tempo); - if (pm_hosterror < 0) - return pmHostError; - + err = snd_seq_set_queue_tempo(seq, queue, tempo); + if (err < 0) { + return check_hosterror(err); + } snd_seq_start_queue(seq, queue, NULL); snd_seq_drain_output(seq); } @@ -135,77 +142,87 @@ static int midi_message_length(PmMessage message) } -static PmError alsa_out_open(PmInternal *midi, void *driverInfo) +static alsa_info_type alsa_info_create(int client_port, long id, int is_virtual) { - void *client_port = descriptors[midi->device_id].descriptor; - alsa_descriptor_type desc = (alsa_descriptor_type) - pm_alloc(sizeof(alsa_descriptor_node)); - snd_seq_port_info_t *info; - int err; + alsa_info_type info = (alsa_info_type) pm_alloc(sizeof(alsa_info_node)); + info->is_virtual = is_virtual; + info->this_port = id; + info->client = GET_DESCRIPTOR_CLIENT(client_port); + info->port = GET_DESCRIPTOR_PORT(client_port); + info->in_sysex = 0; + return info; +} - if (!desc) return pmInsufficientMemory; - - snd_seq_port_info_alloca(&info); - snd_seq_port_info_set_port(info, midi->device_id); - snd_seq_port_info_set_capability(info, SND_SEQ_PORT_CAP_WRITE | - SND_SEQ_PORT_CAP_READ); - snd_seq_port_info_set_type(info, SND_SEQ_PORT_TYPE_MIDI_GENERIC | - SND_SEQ_PORT_TYPE_APPLICATION); - snd_seq_port_info_set_port_specified(info, 1); - err = snd_seq_create_port(seq, info); - if (err < 0) goto free_desc; - /* fill in fields of desc, which is passed to pm_write routines */ - midi->descriptor = desc; - desc->client = GET_DESCRIPTOR_CLIENT(client_port); - desc->port = GET_DESCRIPTOR_PORT(client_port); - desc->this_port = midi->device_id; - desc->in_sysex = 0; - - desc->error = 0; +static PmError alsa_out_open(PmInternal *midi, void *driverInfo) +{ + int id = midi->device_id; + void *client_port = pm_descriptors[id].descriptor; + alsa_info_type ainfo = alsa_info_create((long) client_port, id, + pm_descriptors[id].pub.is_virtual); + snd_seq_port_info_t *pinfo; + int err = 0; + int queue_used = 0; - err = snd_midi_event_new(PM_DEFAULT_SYSEX_BUFFER_SIZE, &desc->parser); + if (!ainfo) return pmInsufficientMemory; + midi->api_info = ainfo; + + if (!ainfo->is_virtual) { + snd_seq_port_info_alloca(&pinfo); + snd_seq_port_info_set_port(pinfo, id); + snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_READ); + snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION); + snd_seq_port_info_set_port_specified(pinfo, 1); + err = snd_seq_create_port(seq, pinfo); + if (err < 0) goto free_ainfo; + } + + err = snd_midi_event_new(PM_DEFAULT_SYSEX_BUFFER_SIZE, &ainfo->parser); if (err < 0) goto free_this_port; if (midi->latency > 0) { /* must delay output using a queue */ err = alsa_use_queue(); if (err < 0) goto free_parser; + queue_used++; + } - err = snd_seq_connect_to(seq, desc->this_port, desc->client, desc->port); + if (!ainfo->is_virtual) { + err = snd_seq_connect_to(seq, ainfo->this_port, ainfo->client, + ainfo->port); if (err < 0) goto unuse_queue; /* clean up and return on error */ - } else { - err = snd_seq_connect_to(seq, desc->this_port, desc->client, desc->port); - if (err < 0) goto free_parser; /* clean up and return on error */ - } + } return pmNoError; unuse_queue: - alsa_unuse_queue(); + if (queue_used > 0) /* only for latency>0 case */ + alsa_unuse_queue(); free_parser: - snd_midi_event_free(desc->parser); + snd_midi_event_free(ainfo->parser); free_this_port: - snd_seq_delete_port(seq, desc->this_port); - free_desc: - pm_free(desc); - pm_hosterror = err; - if (err < 0) { - get_alsa_error_text(pm_hosterror_text, PM_HOST_ERROR_MSG_LEN, err); - } - return pmHostError; + snd_seq_delete_port(seq, ainfo->this_port); + free_ainfo: + pm_free(ainfo); + return check_hosterror(err); } static PmError alsa_write_byte(PmInternal *midi, unsigned char byte, - PmTimestamp timestamp) + PmTimestamp timestamp) { - alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; + alsa_info_type info = (alsa_info_type) midi->api_info; snd_seq_event_t ev; - int err; + int err = 0; snd_seq_ev_clear(&ev); - if (snd_midi_event_encode_byte(desc->parser, byte, &ev) == 1) { - snd_seq_ev_set_dest(&ev, desc->client, desc->port); - snd_seq_ev_set_source(&ev, desc->this_port); + if (snd_midi_event_encode_byte(info->parser, byte, &ev) == 1) { + if (info->is_virtual) { + snd_seq_ev_set_subs(&ev); + } else { + snd_seq_ev_set_dest(&ev, info->client, info->port); + } + snd_seq_ev_set_source(&ev, info->this_port); if (midi->latency > 0) { /* compute relative time of event = timestamp - now + latency */ PmTimestamp now = (midi->time_proc ? @@ -235,126 +252,165 @@ static PmError alsa_write_byte(PmInternal *midi, unsigned char byte, ev.dest.client = SND_SEQ_ADDRESS_SUBSCRIBERS; */ snd_seq_ev_set_direct(&ev); } - VERBOSE printf("sending event\n"); + VERBOSE printf("sending event, timestamp %d (%d+%dns) (%s, %s)\n", + ev.time.tick, ev.time.time.tv_sec, ev.time.time.tv_nsec, + (ev.flags & SND_SEQ_TIME_STAMP_MASK ? "real" : "tick"), + (ev.flags & SND_SEQ_TIME_MODE_MASK ? "rel" : "abs")); err = snd_seq_event_output(seq, &ev); - if (err < 0) { - desc->error = err; - return pmHostError; - } } - return pmNoError; + return check_hosterror(err); } static PmError alsa_out_close(PmInternal *midi) { - alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; - if (!desc) return pmBadPtr; - - if ((pm_hosterror = snd_seq_disconnect_to(seq, desc->this_port, - desc->client, desc->port))) { - // if there's an error, try to delete the port anyway, but don't - // change the pm_hosterror value so we retain the first error - snd_seq_delete_port(seq, desc->this_port); - } else { // if there's no error, delete the port and retain any error - pm_hosterror = snd_seq_delete_port(seq, desc->this_port); + alsa_info_type info = (alsa_info_type) midi->api_info; + int err = 0; + int error2 = 0; + if (!info) return pmBadPtr; + + if (info->this_port != PORT_IS_CLOSED) { + if (!info->is_virtual) { + err = snd_seq_disconnect_to(seq, info->this_port, + info->client, info->port); + /* even if there was an error, we still try to delete the port */ + error2 = snd_seq_delete_port(seq, info->this_port); + + if (!err) { /* retain original error if there was one */ + err = error2; /* otherwise, use port delete status */ + } + } } if (midi->latency > 0) alsa_unuse_queue(); - snd_midi_event_free(desc->parser); - midi->descriptor = NULL; /* destroy the pointer to signify "closed" */ - pm_free(desc); - if (pm_hosterror) { - get_alsa_error_text(pm_hosterror_text, PM_HOST_ERROR_MSG_LEN, - pm_hosterror); - return pmHostError; + snd_midi_event_free(info->parser); + midi->api_info = NULL; /* destroy the pointer to signify "closed" */ + pm_free(info); + return check_hosterror(err); +} + + +static PmError alsa_create_virtual(int is_input, const char *name, + void *device_info) +{ + snd_seq_port_info_t *pinfo; + int err; + int client, port; + + /* we need the id to set the port. */ + PmDeviceID id = pm_add_device("ALSA", name, is_input, TRUE, NULL, + (is_input ? &pm_linuxalsa_in_dictionary : + &pm_linuxalsa_out_dictionary)); + if (id < 0) { /* error -- out of memory? */ + return id; } - return pmNoError; + snd_seq_port_info_alloca(&pinfo); + snd_seq_port_info_set_capability(pinfo, + (is_input ? SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE : + SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)); + snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION); + snd_seq_port_info_set_name(pinfo, name); + snd_seq_port_info_set_port(pinfo, id); + snd_seq_port_info_set_port_specified(pinfo, 1); + /* next 3 lines needed to generate timestamp - PaulLiu */ + snd_seq_port_info_set_timestamping(pinfo, 1); + snd_seq_port_info_set_timestamp_real(pinfo, 0); + snd_seq_port_info_set_timestamp_queue(pinfo, queue); + err = snd_seq_create_port(seq, pinfo); + if (err < 0) { + pm_undo_add_device(id); + return check_hosterror(err); + } + client = snd_seq_port_info_get_client(pinfo); + port = snd_seq_port_info_get_port(pinfo); + pm_descriptors[id].descriptor = MAKE_DESCRIPTOR(client, port); + return id; } + static PmError alsa_delete_virtual(PmDeviceID id) + { + int err = snd_seq_delete_port(seq, id); + return check_hosterror(err); + } + + static PmError alsa_in_open(PmInternal *midi, void *driverInfo) { - void *client_port = descriptors[midi->device_id].descriptor; - alsa_descriptor_type desc = (alsa_descriptor_type) - pm_alloc(sizeof(alsa_descriptor_node)); - snd_seq_port_info_t *info; + int id = midi->device_id; + void *client_port = pm_descriptors[id].descriptor; + alsa_info_type ainfo = alsa_info_create((long) client_port, id, + pm_descriptors[id].pub.is_virtual); + snd_seq_port_info_t *pinfo; snd_seq_port_subscribe_t *sub; snd_seq_addr_t addr; - int err; - - if (!desc) return pmInsufficientMemory; + int err = 0; + int is_virtual = pm_descriptors[id].pub.is_virtual; + if (!ainfo) return pmInsufficientMemory; + midi->api_info = ainfo; + err = alsa_use_queue(); - if (err < 0) goto free_desc; + if (err < 0) goto free_ainfo; - snd_seq_port_info_alloca(&info); - snd_seq_port_info_set_port(info, midi->device_id); - snd_seq_port_info_set_capability(info, SND_SEQ_PORT_CAP_WRITE | - SND_SEQ_PORT_CAP_READ); - snd_seq_port_info_set_type(info, SND_SEQ_PORT_TYPE_MIDI_GENERIC | - SND_SEQ_PORT_TYPE_APPLICATION); - snd_seq_port_info_set_port_specified(info, 1); - err = snd_seq_create_port(seq, info); - if (err < 0) goto free_queue; - - /* fill in fields of desc, which is passed to pm_write routines */ - midi->descriptor = desc; - desc->client = GET_DESCRIPTOR_CLIENT(client_port); - desc->port = GET_DESCRIPTOR_PORT(client_port); - desc->this_port = midi->device_id; - desc->in_sysex = 0; - - desc->error = 0; - - VERBOSE printf("snd_seq_connect_from: %d %d %d\n", - desc->this_port, desc->client, desc->port); - snd_seq_port_subscribe_alloca(&sub); - addr.client = snd_seq_client_id(seq); - addr.port = desc->this_port; - snd_seq_port_subscribe_set_dest(sub, &addr); - addr.client = desc->client; - addr.port = desc->port; - snd_seq_port_subscribe_set_sender(sub, &addr); - snd_seq_port_subscribe_set_time_update(sub, 1); - /* this doesn't seem to work: messages come in with real timestamps */ - snd_seq_port_subscribe_set_time_real(sub, 0); - err = snd_seq_subscribe_port(seq, sub); - /* err = - snd_seq_connect_from(seq, desc->this_port, desc->client, desc->port); */ - if (err < 0) goto free_this_port; /* clean up and return on error */ + if (is_virtual) { + ainfo->is_virtual = TRUE; + } else { + /* create a port for this alsa client (seq) where the port + number matches the portmidi device ID of the input device */ + snd_seq_port_info_alloca(&pinfo); + snd_seq_port_info_set_port(pinfo, id); + snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_READ); + snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION); + snd_seq_port_info_set_port_specified(pinfo, 1); + err = snd_seq_create_port(seq, pinfo); + if (err < 0) goto free_queue; + + /* forward messages from input to this alsa client, so this + * alsa client is the destination, and the destination port is the + * port we just created using the device ID as port number + */ + snd_seq_port_subscribe_alloca(&sub); + addr.client = snd_seq_client_id(seq); + addr.port = ainfo->this_port; + snd_seq_port_subscribe_set_dest(sub, &addr); + + /* forward from the sender which is the device named by + client and port */ + addr.client = ainfo->client; + addr.port = ainfo->port; + snd_seq_port_subscribe_set_sender(sub, &addr); + snd_seq_port_subscribe_set_time_update(sub, 1); + /* this doesn't seem to work: messages come in with real timestamps */ + snd_seq_port_subscribe_set_time_real(sub, 0); + err = snd_seq_subscribe_port(seq, sub); + if (err < 0) goto free_this_port; /* clean up and return on error */ + } return pmNoError; - free_this_port: - snd_seq_delete_port(seq, desc->this_port); + snd_seq_delete_port(seq, ainfo->this_port); free_queue: alsa_unuse_queue(); - free_desc: - pm_free(desc); - pm_hosterror = err; - if (err < 0) { - get_alsa_error_text(pm_hosterror_text, PM_HOST_ERROR_MSG_LEN, err); - } - return pmHostError; + free_ainfo: + pm_free(ainfo); + return check_hosterror(err); } static PmError alsa_in_close(PmInternal *midi) { - alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; - if (!desc) return pmBadPtr; - if ((pm_hosterror = snd_seq_disconnect_from(seq, desc->this_port, - desc->client, desc->port))) { - snd_seq_delete_port(seq, desc->this_port); /* try to close port */ - } else { - pm_hosterror = snd_seq_delete_port(seq, desc->this_port); + int err = 0; + alsa_info_type info = (alsa_info_type) midi->api_info; + if (!info) return pmBadPtr; + /* virtual ports stay open because the represent devices */ + if (!info->is_virtual && info->this_port != PORT_IS_CLOSED) { + err = snd_seq_delete_port(seq, info->this_port); } alsa_unuse_queue(); - pm_free(desc); - if (pm_hosterror) { - get_alsa_error_text(pm_hosterror_text, PM_HOST_ERROR_MSG_LEN, - pm_hosterror); - return pmHostError; - } - return pmNoError; + midi->api_info = NULL; + pm_free(info); + return check_hosterror(err); } @@ -370,11 +426,11 @@ static PmError alsa_abort(PmInternal *midi) * upgrade my entire Linux OS -RBD */ /* - alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; + info_type info = (info_type) midi->api_info; snd_seq_remove_events_t info; snd_seq_addr_t addr; - addr.client = desc->client; - addr.port = desc->port; + addr.client = info->client; + addr.port = info->port; snd_seq_remove_events_set_dest(&info, &addr); snd_seq_remove_events_set_condition(&info, SND_SEQ_REMOVE_DEST); pm_hosterror = snd_seq_remove_events(seq, &info); @@ -389,65 +445,14 @@ static PmError alsa_abort(PmInternal *midi) } -#ifdef GARBAGE -This is old code here temporarily for reference -static PmError alsa_write(PmInternal *midi, PmEvent *buffer, int32_t length) -{ - alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; - int i, bytes; - unsigned char byte; - PmMessage msg; - - desc->error = 0; - for (; length > 0; length--, buffer++) { - VERBOSE printf("message 0x%x\n", buffer->message); - if (Pm_MessageStatus(buffer->message) == MIDI_SYSEX) - desc->in_sysex = TRUE; - if (desc->in_sysex) { - msg = buffer->message; - for (i = 0; i < 4; i++) { - byte = msg; /* extract next byte to send */ - alsa_write_byte(midi, byte, buffer->timestamp); - if (byte == MIDI_EOX) { - desc->in_sysex = FALSE; - break; - } - if (desc->error < 0) break; - msg >>= 8; /* shift next byte into position */ - } - } else { - bytes = midi_message_length(buffer->message); - msg = buffer->message; - for (i = 0; i < bytes; i++) { - byte = msg; /* extract next byte to send */ - VERBOSE printf("sending 0x%x\n", byte); - alsa_write_byte(midi, byte, buffer->timestamp); - if (desc->error < 0) break; - msg >>= 8; /* shift next byte into position */ - } - } - } - if (desc->error < 0) return pmHostError; - - VERBOSE printf("snd_seq_drain_output: 0x%x\n", (unsigned int) seq); - desc->error = snd_seq_drain_output(seq); - if (desc->error < 0) return pmHostError; - - desc->error = pmNoError; - return pmNoError; -} -#endif - - static PmError alsa_write_flush(PmInternal *midi, PmTimestamp timestamp) { - alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; - VERBOSE printf("snd_seq_drain_output: 0x%x\n", (unsigned int)(FPTR) seq); - desc->error = snd_seq_drain_output(seq); - if (desc->error < 0) return pmHostError; - - desc->error = pmNoError; - return pmNoError; + int err; + alsa_info_type info = (alsa_info_type) midi->api_info; + if (!info) return pmBadPtr; + VERBOSE printf("snd_seq_drain_output: %p\n", seq); + err = snd_seq_drain_output(seq); + return check_hosterror(err); } @@ -456,16 +461,16 @@ static PmError alsa_write_short(PmInternal *midi, PmEvent *event) int bytes = midi_message_length(event->message); PmMessage msg = event->message; int i; - alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; + alsa_info_type info = (alsa_info_type) midi->api_info; + if (!info) return pmBadPtr; for (i = 0; i < bytes; i++) { unsigned char byte = msg; VERBOSE printf("sending 0x%x\n", byte); alsa_write_byte(midi, byte, event->timestamp); - if (desc->error < 0) break; + if (pm_hosterror) break; msg >>= 8; /* shift next byte into position */ } - if (desc->error < 0) return pmHostError; - desc->error = pmNoError; + if (pm_hosterror) return pmHostError; return pmNoError; } @@ -489,25 +494,50 @@ static PmTimestamp alsa_synchronize(PmInternal *midi) static void handle_event(snd_seq_event_t *ev) { int device_id = ev->dest.port; - PmInternal *midi = descriptors[device_id].internalDescriptor; + PmInternal *midi = pm_descriptors[device_id].pm_internal; + // There is a race condition when closing a device and + // continuing to poll other open devices. The closed device may + // have outstanding events from before the close operation. + if (!midi) { + return; + } PmEvent pm_ev; - PmTimeProcPtr time_proc = midi->time_proc; - PmTimestamp timestamp; + PmTimestamp timestamp = midi->time_proc(midi->time_info); /* time stamp should be in ticks, using our queue where 1 tick = 1ms */ - assert((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_TICK); + /* assert((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_TICK); + * Currently, event timestamp is ignored. See long note below. */ - /* if no time_proc, just return "native" ticks (ms) */ - if (time_proc == NULL) { - timestamp = ev->time.tick; - } else { /* translate time to time_proc basis */ + VERBOSE { + /* translate time to time_proc basis */ snd_seq_queue_status_t *queue_status; snd_seq_queue_status_alloca(&queue_status); snd_seq_get_queue_status(seq, queue, queue_status); - /* return (now - alsa_now) + alsa_timestamp */ - timestamp = (*time_proc)(midi->time_info) + ev->time.tick - - snd_seq_queue_status_get_tick_time(queue_status); + printf("handle_event: alsa_now %d, " + "event timestamp %d (%d+%dns) (%s, %s)\n", + snd_seq_queue_status_get_tick_time(queue_status), + ev->time.tick, ev->time.time.tv_sec, ev->time.time.tv_nsec, + (ev->flags & SND_SEQ_TIME_STAMP_MASK ? "real" : "tick"), + (ev->flags & SND_SEQ_TIME_MODE_MASK ? "rel" : "abs")); + /* OLD: portmidi timestamp is (now - alsa_now) + alsa_timestamp */ + /* timestamp = (*time_proc)(midi->time_info) + ev->time.tick - + snd_seq_queue_status_get_tick_time(queue_status); */ } + /* CURRENT: portmidi timestamp is "now". In a test, timestamps from + * hardware (MIDI over USB) were timestamped with the current ALSA + * time (snd_seq_queue_status_get_tick_time) and flags indicating + * absolute ticks, but timestamps from another application's virtual + * port, sent direct with 0 absolute ticks, were received with a + * large value that is apparently the time since the start time of + * the other application. Without any reference to our local time, + * this seems useless. PortMidi is supposed to return the local + * PortMidi time of the arrival of the message, so the best we can + * do is set the timestamp to our local clock. This seems to be a + * design flaw in ALSA -- I pointed this out a decade ago, but if + * there is a workaround, I'd still like to know. Maybe there is a + * way to use absolute real time and maybe that's sharable across + * applications by referencing the system time? + */ pm_ev.timestamp = timestamp; switch (ev->type) { case SND_SEQ_EVENT_NOTEON: @@ -618,12 +648,31 @@ static void handle_event(snd_seq_event_t *ev) pm_read_bytes(midi, ptr, ev->data.ext.len, timestamp); break; } + case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: { + /* this happens if you have an input port open and the + * device or application with virtual ports closes. We + * mark the port as closed to avoid closing a 2nd time + * when Pm_Close() is called. + */ + alsa_info_type info = (alsa_info_type) midi->api_info; + /* printf("SND_SEQ_EVENT_UNSUBSCRIBE message\n"); */ + info->this_port = PORT_IS_CLOSED; + break; + } + case SND_SEQ_EVENT_PORT_SUBSCRIBED: + break; /* someone connected to a virtual output port, not reported */ + default: + printf("portmidi handle_event: not handled type %x\n", ev->type); + break; } } static PmError alsa_poll(PmInternal *midi) { + if (!midi) { + return pmBadPtr; + } snd_seq_event_t *ev; /* expensive check for input data, gets data from device: */ while (snd_seq_event_input_pending(seq, TRUE) > 0) { @@ -641,10 +690,9 @@ static PmError alsa_poll(PmInternal *midi) handle_event(ev); } else if (rslt == -ENOSPC) { int i; - for (i = 0; i < pm_descriptor_index; i++) { - if (descriptors[i].pub.input) { - PmInternal *midi = (PmInternal *) - descriptors[i].internalDescriptor; + for (i = 0; i < pm_descriptor_len; i++) { + if (pm_descriptors[i].pub.input) { + PmInternal *midi = pm_descriptors[i].pm_internal; /* careful, device may not be open! */ if (midi) Pm_SetOverflow(midi->queue); } @@ -656,18 +704,9 @@ static PmError alsa_poll(PmInternal *midi) } -static unsigned int alsa_has_host_error(PmInternal *midi) -{ - alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; - return desc->error; -} - - -static void alsa_get_host_error(PmInternal *midi, char *msg, unsigned int len) +static unsigned int alsa_check_host_error(PmInternal *midi) { - alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; - int err = (pm_hosterror || desc->error); - get_alsa_error_text(msg, len, err); + return FALSE; } @@ -683,8 +722,7 @@ pm_fns_node pm_linuxalsa_in_dictionary = { alsa_abort, alsa_in_close, alsa_poll, - alsa_has_host_error, - alsa_get_host_error + alsa_check_host_error }; pm_fns_node pm_linuxalsa_out_dictionary = { @@ -699,8 +737,7 @@ pm_fns_node pm_linuxalsa_out_dictionary = { alsa_abort, alsa_out_close, none_poll, - alsa_has_host_error, - alsa_get_host_error + alsa_check_host_error }; @@ -718,13 +755,16 @@ char *pm_strdup(const char *s) } -PmError pm_linuxalsa_init( void ) +PmError pm_linuxalsa_init(void) { int err; snd_seq_client_info_t *cinfo; snd_seq_port_info_t *pinfo; unsigned int caps; + /* Register interface ALSA with create_virtual fn */ + pm_add_interf("ALSA", &alsa_create_virtual, &alsa_delete_virtual); + /* Previously, the last parameter was SND_SEQ_NONBLOCK, but this * would cause messages to be dropped if the ALSA buffer fills up. * The correct behavior is for writes to block until there is @@ -735,56 +775,61 @@ PmError pm_linuxalsa_init( void ) * call seq_event_input_pending() to avoid blocking. */ err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); - if (err < 0) return err; + if (err < 0) goto error_return; snd_seq_client_info_alloca(&cinfo); snd_seq_port_info_alloca(&pinfo); snd_seq_client_info_set_client(cinfo, -1); while (snd_seq_query_next_client(seq, cinfo) == 0) { - snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo)); + snd_seq_port_info_set_client(pinfo, + snd_seq_client_info_get_client(cinfo)); snd_seq_port_info_set_port(pinfo, -1); while (snd_seq_query_next_port(seq, pinfo) == 0) { if (snd_seq_port_info_get_client(pinfo) == SND_SEQ_CLIENT_SYSTEM) continue; /* ignore Timer and Announce ports on client 0 */ caps = snd_seq_port_info_get_capability(pinfo); - if (!(caps & (SND_SEQ_PORT_CAP_SUBS_READ | SND_SEQ_PORT_CAP_SUBS_WRITE))) + if (!(caps & (SND_SEQ_PORT_CAP_SUBS_READ | + SND_SEQ_PORT_CAP_SUBS_WRITE))) continue; /* ignore if you cannot read or write port */ if (caps & SND_SEQ_PORT_CAP_SUBS_WRITE) { if (pm_default_output_device_id == -1) - pm_default_output_device_id = pm_descriptor_index; - // FIXME: pm_strdup() result is leaked - pm_add_device((char *)"ALSA", - pm_strdup(snd_seq_port_info_get_name(pinfo)), - FALSE, - MAKE_DESCRIPTOR(snd_seq_port_info_get_client(pinfo), - snd_seq_port_info_get_port(pinfo)), - &pm_linuxalsa_out_dictionary); + pm_default_output_device_id = pm_descriptor_len; + pm_add_device("ALSA", + pm_strdup(snd_seq_port_info_get_name(pinfo)), + FALSE, FALSE, + MAKE_DESCRIPTOR(snd_seq_port_info_get_client(pinfo), + snd_seq_port_info_get_port(pinfo)), + &pm_linuxalsa_out_dictionary); } if (caps & SND_SEQ_PORT_CAP_SUBS_READ) { if (pm_default_input_device_id == -1) - pm_default_input_device_id = pm_descriptor_index; - // FIXME: pm_strdup() result is leaked - pm_add_device((char *)"ALSA", - pm_strdup(snd_seq_port_info_get_name(pinfo)), - TRUE, - MAKE_DESCRIPTOR(snd_seq_port_info_get_client(pinfo), - snd_seq_port_info_get_port(pinfo)), - &pm_linuxalsa_in_dictionary); + pm_default_input_device_id = pm_descriptor_len; + pm_add_device("ALSA", + pm_strdup(snd_seq_port_info_get_name(pinfo)), + TRUE, FALSE, + MAKE_DESCRIPTOR(snd_seq_port_info_get_client(pinfo), + snd_seq_port_info_get_port(pinfo)), + &pm_linuxalsa_in_dictionary); } } } return pmNoError; + error_return: + pm_linuxalsa_term(); /* clean up */ + return check_hosterror(err); } - + void pm_linuxalsa_term(void) { if (seq) { snd_seq_close(seq); - pm_free(descriptors); - descriptors = NULL; - pm_descriptor_index = 0; + pm_free(pm_descriptors); + pm_descriptors = NULL; + pm_descriptor_len = 0; pm_descriptor_max = 0; } } + +#endif diff --git a/3rdparty/portmidi/pm_linux/pmlinuxnull.c b/3rdparty/portmidi/pm_linux/pmlinuxnull.c new file mode 100644 index 00000000000..841440917ad --- /dev/null +++ b/3rdparty/portmidi/pm_linux/pmlinuxnull.c @@ -0,0 +1,31 @@ +/* + * pmlinuxnull.c -- system specific definitions + * + * written by: + * Roger Dannenberg + * + * If there is no ALSA, you can define PMNULL and build PortMidi. It will + * not report any devices, so you will not be able to open any, but if + * you wanted to disable MIDI from some application, this could be used. + * Mainly, this code shows the possibility of supporting multiple + * interfaces, e.g., ALSA and Sndio on BSD, or ALSA and Jack on Linux. + * But as of Dec, 2021, the only supported MIDI API for Linux is ALSA. + */ + +#ifdef PMNULL + +#include "portmidi.h" +#include "pmlinuxnull.h" + + +PmError pm_linuxnull_init(void) +{ + return pmNoError; +} + + +void pm_linuxnull_term(void) +{ +} + +#endif diff --git a/3rdparty/portmidi/pm_linux/pmlinuxnull.h b/3rdparty/portmidi/pm_linux/pmlinuxnull.h new file mode 100644 index 00000000000..52607eb01bf --- /dev/null +++ b/3rdparty/portmidi/pm_linux/pmlinuxnull.h @@ -0,0 +1,6 @@ +/* pmlinuxnull.h -- system-specific definitions */ + +PmError pm_linuxnull_init(void); +void pm_linuxnull_term(void); + + diff --git a/3rdparty/portmidi/pm_mac/Makefile.osx b/3rdparty/portmidi/pm_mac/Makefile.osx index 8c6862e28f0..e34e33a92ff 100644 --- a/3rdparty/portmidi/pm_mac/Makefile.osx +++ b/3rdparty/portmidi/pm_mac/Makefile.osx @@ -4,7 +4,7 @@ # Sep 2009 # NOTE: you can use -# make -f pm_osx/Makefile.osx configuration=Release +# make -f pm_mac/Makefile.osx configuration=Release # to override the default Debug configuration configuration=Release @@ -23,12 +23,12 @@ all: $(CONFIG)/CMakeCache.txt cd $(CONFIG); make $(CONFIG)/CMakeCache.txt: - rm -f CMakeCache.txt + rm -f $(CONFIG)/CMakeCache.txt mkdir -p $(CONFIG) cd $(CONFIG); cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=$(CONFIG) -**** For instructions: make -f pm_mac\Makefile.osx help ****\n' +**** For instructions: make -f pm_mac/Makefile.osx help ****\n' help: echo $$'\n\n\ @@ -63,6 +63,8 @@ cleaner: clean rm -f pm_java/pmjni/Release/*.jnilib cleanest: cleaner + rm -f Debug/CMakeCache.txt Release/CMakeCache.txt + rm -f CMakeCache.txt rm -f Debug/libportmidi_s.a Release/libportmidi_s.a rm -f pm_test/Debug/test pm_test/Debug/sysex pm_test/Debug/midithread rm -f pm_test/Debug/latency pm_test/Debug/midithru diff --git a/3rdparty/portmidi/pm_mac/README_MAC.txt b/3rdparty/portmidi/pm_mac/README_MAC.txt index 1650dccecce..12cc40bbc17 100644 --- a/3rdparty/portmidi/pm_mac/README_MAC.txt +++ b/3rdparty/portmidi/pm_mac/README_MAC.txt @@ -1,163 +1,76 @@ README_MAC.txt for PortMidi Roger Dannenberg 20 nov 2009 -revised 20 Sep 2010 for Xcode 3.2.4 and CMake 8.2-2 +revised 20 Sep 2010 for Xcode 4.3.2 and CMake 2.8.8 +revised Jan 2022 for the PortMidi/portmidi repo on github.com + +This documents how I build PortMidi for macOS. It's not the only way, +and command-line/scripting enthusiasts will say it's not even a good +way. Feel free to contribute your approach if you are willing to +describe it carefully and test it. + +Install Xcode and the CMake application, CMake.app. I use the GUI +version of CMake which makes it easy to see/edit variables and +options. + +==== USING CMAKE ==== + +Run CMake.app and select your portmidi repo working directory as the +location for source and build. (Yes, I use so called "in-tree" +builds -- it doesn't hurt, but I don't think it is necessary.) + +Default settings should all be fine, but select options under BUILD if +you wish: + +BUILD_NATIVE_JAVA_INTERFACE and BUILD_PMDEFAULTS to build a Java-based +GUI for setting default MIDI devices. (Otherwise, calls to +Pm_DefaultInputDevice() and Pm_DefaultOutputDevice() will not be +useful, but maybe you are not going to use these anyway -- up to you.) + +BUILD_PORTMIDI_TESTS to create some test programs. Of particular +interest are test/mm, a handy command-line MIDI Input Monitor, and +test/testio, a simple command-line program to send or receive some +MIDI notes in case you need a quick test: What devices do I have? Does +this input work? Does this output work? + +I disable BUILD_SHARED_LIBS and always link statically: Static linking only +adds about 40KB to any application and then you don't have to worry +about versions, instally, copying or finding the dynamic link library, +etc. + +To make sure you link statically, I rename the library to +libportmidi_static.a. To do this, set PM_STATIC_LIB_NAME (in CMake, +under the "PM" group) to "portmidi_static", and of course your +application will have to specify portmidi_static as the library to +link to. + +If you are building simple command-line applications, you might want +to enable PM_CHECK_ERRORS. If you do, then calls into the PortMidi +library will print error messages and exit in the event of an error +(such as trying to open a device that does not exist). This saves you +from having to check for errors everytime you call a library function +or getting confused when errors are detected but not reported. For +high-quality applications, do NOT enable PM_CHECK_ERRORS -- any +failure could immediately abort your whole application, which is not +very friendly to users. + +Click on Configure (maybe a couple of times). + +Click on Generate and make an Xcode project. + +Open portmidi/portmidi.xcodeproj with Xcode and build what you +need. The simplest thing is to build the ALL_BUILD target. Be careful +to specify a Debug or Release depending on what you want. "ALL_BUILD" +is a misnomer -- it only builds the version you select. + +PmDefaults is minimally supported and may be removed in 2023 unless we +hear from users. To run it, +(1) make sure java runs from the command line. +(2) run the following command in an open Terminal: + cd portmidi/pm_java/pmdefaults + ./pmdefaults + +Feel free to write a short script that cd's to your pmdefaults +directory and runs pmdefaults, and put that script somewhere on your +path so you can type it anywhere. -To build PortMidi for Mac OS X, you must install Xcode and -CMake. - -CMake can build either command-line Makefiles or Xcode projects. -These approaches are described in separate sections below. - -==== CLEANING UP ==== -(Skip this for now, but later you might want start from a clean -slate.) - -Start in the portmedia/portmidi directory. - -make -f pm_mac/Makefile.osx clean - -will remove .o, CMakeFiles, and other intermediate files. - -Using "cleaner" instead of "clean" will also remove jni-related -intermediate files. - -Using "cleanest" instead of "clean" or "cleaner" will also remove -application binaries and the portmidi libraries. (It will not -uninstall anything, however.) - -==== USING CMAKE (AND COMMAND LINE TOOLS) ==== - -Start in the portmedia/portmidi directory. - -make -f pm_mac/Makefile.osx - -(Begin note: make will invoke cmake to build a Makefile and then make to -build portmidi. This extra level allows you to correctly build -both Release and Debug versions. Release is the default, so to get -the Debug version, use: - -make -f pm_mac/Makefile.osx configuration=Debug -) - -Release version executables and libraries are now in - portmedia/portmidi/Release - -Debug version executables and libraries are created in - portmedia/portmidi/Debug -The Debug versions are compiled with PM_CHECK_ERRORS which -prints an error message and aborts when an error code is returned -by PortMidi functions. This is useful for small command line -applications. Otherwise, you should check and handle error returns -in your program. - -You can install portmidi as follows: - -cd Release; sudo make install - -This will install /usr/local/include/{portmidi.h, porttime.h} -and /usr/local/lib/{libportmidi.dylib, libportmidi_s.a, libpmjni.dylib} - -You should now make the pmdefaults.app: - -make -f pm_mac/Makefile.osx pmdefaults - -NOTE: pmdefaults.app will be in pm_mac/Release/. - -Please copy pmdefaults.app to your Applications folder or wherever -you would normally expect to find it. - -==== USING CMAKE TO BUILD Xcode PROJECT ==== - -Before you can use Xcode, you need a portmidi.xcodeproj file. -CMake builds a location-dependent Xcode project, so unfortunately -it is not easy to provide an Xcode project that is ready to use. -Therefore, you should make your own. Once you have it, you can -use it almost like any other Xcode project, and you will not have -to go back to CMake. - -(1) Install CMake if you do not have it already. - -(2) Open portmedia/portmidi/CMakeLists.txt with CMake - -(3) Use Configure and Generate buttons - -(4) This creates portmedia/portmidi/portmidi.xcodeproj. - -Note: You will also use pm_mac/pm_mac.xcodeproj, which -is not generated by CMake. - -(5) Open portmidi/portmidi.xcodeproj with Xcode and -build what you need. The simplest thing is to build the -ALL_BUILD target. The default will be to build the Debug -version, but you may want to change this to Release. - -NOTE: ALL_BUILD may report errors. Try simply building again -or rebuilding specific targets that fail until they build -without errors. There appears to be a race condition or -missing dependencies in the build system. - -The Debug version is compiled with PM_CHECK_ERRORS, and the -Release version is not. PM_CHECK_ERRORS will print an error -message and exit your program if any error is returned from -a call into PortMidi. - -CMake (currently) also creates MinSizRel and RelWithDebInfo -versions, but only because I cannot figure out how to disable -them. - -You will probably want the application PmDefaults, which sets -default MIDI In and Out devices for PortMidi. You may also -want to build a Java application using PortMidi. Since I have -not figured out how to use CMake to make an OS X Java application, -use pm_mac/pm_mac.xcodeproj as follows: - -(6) open pm_mac/pm_mac.xcodeproj - -(7) pm_java/pmjni/portmidi_JportmidiApi.h is needed -by libpmjni.jnilib, the Java native interface library. Since -portmidi_JportmidiApi.h is included with PortMidi, you can skip -to step 8, but if you really want to rebuild everything from -scratch, build the JPortMidiHeaders project first, and continue -with step 8: - -(8) If you did not build libpmjni.dylib using portmidi.xcodeproj, -do it now. (It depends on portmidi_JportmidiApi.h, and the -PmDefaults project depends on libpmjni.dylib.) - -(9) Returning to pm_mac.xcodeproj, build the PmDefaults program. - -(10) If you wish, copy pm_mac/build/Deployment/PmDefaults.app to -your applications folder. - -(11) If you want to install libportmidi.dylib, first make it with -Xcode, then - sudo make -f pm_mac/Makefile.osx install -This command will install /usr/local/include/{porttime.h, portmidi.h} -and /usr/local/lib/libportmidi.dylib -Note that the "install" function of xcode creates portmidi/Release -and does not install the library to /usr/local/lib, so please use -the command line installer. - - -CHANGELOG - -20-Sep-2010 Roger B. Dannenberg - Adapted to Xcode 3.2.4 -20-Nov-2009 Roger B. Dannenberg - Added some install instructions -26-Sep-2009 Roger B. Dannenberg - More changes for using CMake, Makefiles, XCode -20-Sep-2009 Roger B. Dannenberg - Modifications for using CMake -14-Sep-2009 Roger B. Dannenberg - Modifications for using CMake -17-Jan-2007 Roger B. Dannenberg - Explicit instructions for Xcode -15-Jan-2007 Roger B. Dannenberg - Changed instructions because of changes to Makefile.osx -07-Oct-2006 Roger B. Dannenberg - Added directions for xcodebuild -29-aug-2006 Roger B. Dannenberg - Updated this documentation. - diff --git a/3rdparty/portmidi/pm_mac/finddefault.c b/3rdparty/portmidi/pm_mac/finddefault.c index bc95a4001a6..b4556e98d91 100644 --- a/3rdparty/portmidi/pm_mac/finddefault.c +++ b/3rdparty/portmidi/pm_mac/finddefault.c @@ -17,14 +17,14 @@ plist files (user and system) open at once (due to a simple memory management scheme). */ -PmDeviceID find_default_device(char *path, int input, PmDeviceID id) +PmDeviceID find_default_device(const char *path, int input, PmDeviceID id) /* path -- the name of the preference we are searching for input -- true iff this is an input device id -- current default device id returns matching device id if found, otherwise id */ { - static char *pref_file = (char *)"com.apple.java.util.prefs.plist"; + static char const *const pref_file = "com.apple.java.util.prefs.plist"; char *pref_str = NULL; // read device preferences value_ptr prefs = bplist_read_user_pref(pref_file); diff --git a/3rdparty/portmidi/pm_mac/osxsupport.h b/3rdparty/portmidi/pm_mac/osxsupport.h deleted file mode 100644 index 7771868d12a..00000000000 --- a/3rdparty/portmidi/pm_mac/osxsupport.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - osxsupport.h - Cocoa glue to emulated deprecated old Carbon path finder functions -*/ - -#ifndef _OSXSUPPORT_H_ -#define _OSXSUPPORT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -char *FindPrefsDir(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/3rdparty/portmidi/pm_mac/osxsupport.m b/3rdparty/portmidi/pm_mac/osxsupport.m deleted file mode 100644 index 1cf457f6bdb..00000000000 --- a/3rdparty/portmidi/pm_mac/osxsupport.m +++ /dev/null @@ -1,37 +0,0 @@ -/* - osxsupport.m - Cocoa glue to emulated deprecated old Carbon path finder functions -*/ - -#import <Cocoa/Cocoa.h> -#import <AvailabilityMacros.h> -#include "osxsupport.h" - -// convert an NSString to a C string -#ifndef OSX_PPC -static char *StringToChar(NSString *str) -{ - const char *charstr = [str UTF8String]; - char *resstr = (char *)malloc(strlen(charstr)+1); - - strcpy(resstr, charstr); - return resstr; -} - -char *FindPrefsDir(void) -{ - char *resstr = NULL; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSUserDomainMask, YES); - - if ([paths count] > 0) - { - resstr = StringToChar([paths objectAtIndex:0]) ; - } - - [pool release]; - - return resstr; -} -#endif - diff --git a/3rdparty/portmidi/pm_mac/pm_mac.xcodeproj/project.pbxproj b/3rdparty/portmidi/pm_mac/pm_mac.xcodeproj/project.pbxproj deleted file mode 100644 index 0d06e565eae..00000000000 --- a/3rdparty/portmidi/pm_mac/pm_mac.xcodeproj/project.pbxproj +++ /dev/null @@ -1,594 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 44; - objects = { - -/* Begin PBXAggregateTarget section */ - 3D634CAB1247805C0020F829 /* JPortMidiHeaders */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 3D634CAE1247807A0020F829 /* Build configuration list for PBXAggregateTarget "JPortMidiHeaders" */; - buildPhases = ( - 3D634CAA1247805C0020F829 /* ShellScript */, - ); - dependencies = ( - 3D634CB0124781580020F829 /* PBXTargetDependency */, - ); - name = JPortMidiHeaders; - productName = JPortMidiHeaders; - }; - 3DE2142D124662AA0033C839 /* CopyJavaSources */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 3DE21434124662FF0033C839 /* Build configuration list for PBXAggregateTarget "CopyJavaSources" */; - buildPhases = ( - 3DE2142C124662AA0033C839 /* CopyFiles */, - ); - comments = "The reason for copying files here is that the Compile Java target looks in a particular place for sources. It would be much better to simply have Compile Java look in the original location for all sources, but I don't know how to do that. -RBD\n"; - dependencies = ( - ); - name = CopyJavaSources; - productName = CopyJavaSources; - }; - 89D0F1C90F3B704E007831A7 /* PmDefaults */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 89D0F1D20F3B7080007831A7 /* Build configuration list for PBXAggregateTarget "PmDefaults" */; - buildPhases = ( - ); - dependencies = ( - 89D0F1D10F3B7062007831A7 /* PBXTargetDependency */, - 89D0F1CD0F3B7062007831A7 /* PBXTargetDependency */, - 3DE21431124662C50033C839 /* PBXTargetDependency */, - ); - name = PmDefaults; - productName = pmdefaults; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 3DE2137F124653FB0033C839 /* portmusic_logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 3DE2137E124653FB0033C839 /* portmusic_logo.png */; }; - 3DE21435124663860033C839 /* PmDefaultsFrame.java in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3DE2137D124653CB0033C839 /* PmDefaultsFrame.java */; }; - 3DE214361246638A0033C839 /* PmDefaults.java in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3DE2137B1246538B0033C839 /* PmDefaults.java */; }; - 3DE214371246638F0033C839 /* JPortMidiException.java in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3DE21382124654DE0033C839 /* JPortMidiException.java */; }; - 3DE214381246638F0033C839 /* JPortMidiApi.java in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3DE21381124654CF0033C839 /* JPortMidiApi.java */; }; - 3DE214391246638F0033C839 /* JPortMidi.java in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3DE21380124654BC0033C839 /* JPortMidi.java */; }; - 3DE216131246AC0E0033C839 /* libpmjni.dylib in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = 3DE216101246ABE30033C839 /* libpmjni.dylib */; }; - 3DE216951246D57A0033C839 /* pmdefaults.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3DE216901246C6410033C839 /* pmdefaults.icns */; }; - 89C3F2920F5250A300B0048E /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 89C3F2900F5250A300B0048E /* Credits.rtf */; }; - 89D0F0240F392F20007831A7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 89D0F0210F392F20007831A7 /* InfoPlist.strings */; }; - 89D0F0410F39306C007831A7 /* JavaApplicationStub in Copy Executable */ = {isa = PBXBuildFile; fileRef = 89D0F03E0F39304A007831A7 /* JavaApplicationStub */; }; - 89D0F16A0F3A124E007831A7 /* pmdefaults.jar in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = 89D0F15D0F3A0FF7007831A7 /* pmdefaults.jar */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 3D634CAF124781580020F829 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; - proxyType = 1; - remoteGlobalIDString = 89D0F1C90F3B704E007831A7; - remoteInfo = PmDefaults; - }; - 3DE21430124662C50033C839 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3DE2142D124662AA0033C839; - remoteInfo = CopyJavaSources; - }; - 3DE2145D124666900033C839 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3DE2142D124662AA0033C839; - remoteInfo = CopyJavaSources; - }; - 89D0F1CC0F3B7062007831A7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8D1107260486CEB800E47090; - remoteInfo = "Assemble Application"; - }; - 89D0F1D00F3B7062007831A7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; - proxyType = 1; - remoteGlobalIDString = 89D0F0480F393A6F007831A7; - remoteInfo = "Compile Java"; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 3DE2142C124662AA0033C839 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "${PROJECT_DIR}/pmdefaults/src/java"; - dstSubfolderSpec = 0; - files = ( - 3DE21435124663860033C839 /* PmDefaultsFrame.java in CopyFiles */, - 3DE214361246638A0033C839 /* PmDefaults.java in CopyFiles */, - 3DE214371246638F0033C839 /* JPortMidiException.java in CopyFiles */, - 3DE214381246638F0033C839 /* JPortMidiApi.java in CopyFiles */, - 3DE214391246638F0033C839 /* JPortMidi.java in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 89D0F0440F393070007831A7 /* Copy Executable */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 6; - files = ( - 89D0F0410F39306C007831A7 /* JavaApplicationStub in Copy Executable */, - ); - name = "Copy Executable"; - runOnlyForDeploymentPostprocessing = 0; - }; - 89D0F11F0F394189007831A7 /* Copy Java Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 15; - files = ( - 89D0F16A0F3A124E007831A7 /* pmdefaults.jar in Copy Java Resources */, - 3DE216131246AC0E0033C839 /* libpmjni.dylib in Copy Java Resources */, - ); - name = "Copy Java Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 3DE2137B1246538B0033C839 /* PmDefaults.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = PmDefaults.java; path = ../pm_java/pmdefaults/PmDefaults.java; sourceTree = SOURCE_ROOT; }; - 3DE2137D124653CB0033C839 /* PmDefaultsFrame.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = PmDefaultsFrame.java; path = ../pm_java/pmdefaults/PmDefaultsFrame.java; sourceTree = SOURCE_ROOT; }; - 3DE2137E124653FB0033C839 /* portmusic_logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = portmusic_logo.png; path = ../pm_java/pmdefaults/portmusic_logo.png; sourceTree = SOURCE_ROOT; }; - 3DE21380124654BC0033C839 /* JPortMidi.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = JPortMidi.java; path = ../pm_java/jportmidi/JPortMidi.java; sourceTree = SOURCE_ROOT; }; - 3DE21381124654CF0033C839 /* JPortMidiApi.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = JPortMidiApi.java; path = ../pm_java/jportmidi/JPortMidiApi.java; sourceTree = SOURCE_ROOT; }; - 3DE21382124654DE0033C839 /* JPortMidiException.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = JPortMidiException.java; path = ../pm_java/jportmidi/JPortMidiException.java; sourceTree = SOURCE_ROOT; }; - 3DE213841246555A0033C839 /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = /System/Library/Frameworks/CoreMIDI.framework; sourceTree = "<absolute>"; }; - 3DE21390124655760033C839 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; }; - 3DE213BE1246557F0033C839 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = "<absolute>"; }; - 3DE216101246ABE30033C839 /* libpmjni.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpmjni.dylib; path = ../Release/libpmjni.dylib; sourceTree = SOURCE_ROOT; }; - 3DE216901246C6410033C839 /* pmdefaults.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = pmdefaults.icns; path = ../pm_java/pmdefaults/pmdefaults.icns; sourceTree = SOURCE_ROOT; }; - 89C3F2910F5250A300B0048E /* English */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = English; path = English.lproj/Credits.rtf; sourceTree = "<group>"; }; - 89D0F0220F392F20007831A7 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; - 89D0F0230F392F20007831A7 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; - 89D0F03E0F39304A007831A7 /* JavaApplicationStub */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = JavaApplicationStub; path = /System/Library/Frameworks/JavaVM.framework/Versions/A/Resources/MacOS/JavaApplicationStub; sourceTree = "<absolute>"; }; - 89D0F0840F394066007831A7 /* JavaNativeFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaNativeFoundation.framework; path = /System/Library/Frameworks/JavaVM.framework/Versions/A/Frameworks/JavaNativeFoundation.framework; sourceTree = "<absolute>"; }; - 89D0F1390F3948A9007831A7 /* pmdefaults/make */ = {isa = PBXFileReference; lastKnownFileType = folder; path = pmdefaults/make; sourceTree = "<group>"; }; - 89D0F15D0F3A0FF7007831A7 /* pmdefaults.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; name = pmdefaults.jar; path = build/Release/pmdefaults.jar; sourceTree = SOURCE_ROOT; }; - 89D0F1860F3A2442007831A7 /* JavaVM.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaVM.framework; path = /System/Library/Frameworks/JavaVM.framework; sourceTree = "<absolute>"; }; - 8D1107320486CEB800E47090 /* PmDefaults.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PmDefaults.app; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXGroup section */ - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { - isa = PBXGroup; - children = ( - 3DE213841246555A0033C839 /* CoreMIDI.framework */, - 3DE21390124655760033C839 /* CoreFoundation.framework */, - 3DE213BE1246557F0033C839 /* CoreAudio.framework */, - 89D0F1860F3A2442007831A7 /* JavaVM.framework */, - 89D0F0840F394066007831A7 /* JavaNativeFoundation.framework */, - ); - name = "Linked Frameworks"; - sourceTree = "<group>"; - }; - 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { - isa = PBXGroup; - children = ( - ); - name = "Other Frameworks"; - sourceTree = "<group>"; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 89D0F15D0F3A0FF7007831A7 /* pmdefaults.jar */, - 8D1107320486CEB800E47090 /* PmDefaults.app */, - ); - name = Products; - sourceTree = "<group>"; - }; - 29B97314FDCFA39411CA2CEA /* pmdefaults */ = { - isa = PBXGroup; - children = ( - 3DE216101246ABE30033C839 /* libpmjni.dylib */, - 89D0F0260F392F48007831A7 /* Source */, - 89D0F0200F392F20007831A7 /* Resources */, - 89D0F1390F3948A9007831A7 /* pmdefaults/make */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = pmdefaults; - sourceTree = "<group>"; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, - 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, - ); - name = Frameworks; - sourceTree = "<group>"; - }; - 3DE2136A124652E20033C839 /* pm_java */ = { - isa = PBXGroup; - children = ( - 3DE21379124653150033C839 /* pmdefaults */, - 3DE2137A1246531D0033C839 /* jportmidi */, - ); - name = pm_java; - path = ..; - sourceTree = "<group>"; - }; - 3DE21379124653150033C839 /* pmdefaults */ = { - isa = PBXGroup; - children = ( - 3DE2137D124653CB0033C839 /* PmDefaultsFrame.java */, - 3DE2137B1246538B0033C839 /* PmDefaults.java */, - ); - name = pmdefaults; - sourceTree = "<group>"; - }; - 3DE2137A1246531D0033C839 /* jportmidi */ = { - isa = PBXGroup; - children = ( - 3DE21382124654DE0033C839 /* JPortMidiException.java */, - 3DE21381124654CF0033C839 /* JPortMidiApi.java */, - 3DE21380124654BC0033C839 /* JPortMidi.java */, - ); - name = jportmidi; - sourceTree = "<group>"; - }; - 89D0F0200F392F20007831A7 /* Resources */ = { - isa = PBXGroup; - children = ( - 3DE216901246C6410033C839 /* pmdefaults.icns */, - 3DE2137E124653FB0033C839 /* portmusic_logo.png */, - 89C3F2900F5250A300B0048E /* Credits.rtf */, - 89D0F0230F392F20007831A7 /* Info.plist */, - 89D0F0210F392F20007831A7 /* InfoPlist.strings */, - 89D0F03E0F39304A007831A7 /* JavaApplicationStub */, - ); - name = Resources; - path = pmdefaults/resources; - sourceTree = "<group>"; - }; - 89D0F0260F392F48007831A7 /* Source */ = { - isa = PBXGroup; - children = ( - 3DE2136A124652E20033C839 /* pm_java */, - ); - name = Source; - path = pmdefaults/src; - sourceTree = "<group>"; - }; -/* End PBXGroup section */ - -/* Begin PBXLegacyTarget section */ - 89D0F0480F393A6F007831A7 /* Compile Java */ = { - isa = PBXLegacyTarget; - buildArgumentsString = "-e -f \"${SRCROOT}/make/build.xml\" -debug \"$ACTION\""; - buildConfigurationList = 89D0F04B0F393AB7007831A7 /* Build configuration list for PBXLegacyTarget "Compile Java" */; - buildPhases = ( - ); - buildToolPath = /usr/bin/ant; - buildWorkingDirectory = ""; - dependencies = ( - 3DE2145E124666900033C839 /* PBXTargetDependency */, - ); - name = "Compile Java"; - passBuildSettingsInEnvironment = 1; - productName = "Compile Java"; - }; -/* End PBXLegacyTarget section */ - -/* Begin PBXNativeTarget section */ - 8D1107260486CEB800E47090 /* Assemble Application */ = { - isa = PBXNativeTarget; - buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Assemble Application" */; - buildPhases = ( - 89D0F0440F393070007831A7 /* Copy Executable */, - 89D0F11F0F394189007831A7 /* Copy Java Resources */, - 8D1107290486CEB800E47090 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Assemble Application"; - productInstallPath = "$(HOME)/Applications"; - productName = pmdefaults; - productReference = 8D1107320486CEB800E47090 /* PmDefaults.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "pm_mac" */; - compatibilityVersion = "Xcode 3.0"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* pmdefaults */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 3D634CAB1247805C0020F829 /* JPortMidiHeaders */, - 89D0F1C90F3B704E007831A7 /* PmDefaults */, - 3DE2142D124662AA0033C839 /* CopyJavaSources */, - 89D0F0480F393A6F007831A7 /* Compile Java */, - 8D1107260486CEB800E47090 /* Assemble Application */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 8D1107290486CEB800E47090 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3DE216951246D57A0033C839 /* pmdefaults.icns in Resources */, - 89D0F0240F392F20007831A7 /* InfoPlist.strings in Resources */, - 89C3F2920F5250A300B0048E /* Credits.rtf in Resources */, - 3DE2137F124653FB0033C839 /* portmusic_logo.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3D634CAA1247805C0020F829 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo BUILT_PRODUCTS_DIR is ${BUILT_PRODUCTS_DIR}\njavah -classpath \"${BUILT_PRODUCTS_DIR}/pmdefaults.jar\" -force -o \"${BUILT_PRODUCTS_DIR}/jportmidi_JportMidiApi.h\" \"jportmidi.JPortMidiApi\"\nmv \"${BUILT_PRODUCTS_DIR}/jportmidi_JportMidiApi.h\" ../pm_java/pmjni/\necho \"Created ../pm_java/pmjni/jportmidi_JportMidiApi.h\"\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 3D634CB0124781580020F829 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 89D0F1C90F3B704E007831A7 /* PmDefaults */; - targetProxy = 3D634CAF124781580020F829 /* PBXContainerItemProxy */; - }; - 3DE21431124662C50033C839 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3DE2142D124662AA0033C839 /* CopyJavaSources */; - targetProxy = 3DE21430124662C50033C839 /* PBXContainerItemProxy */; - }; - 3DE2145E124666900033C839 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3DE2142D124662AA0033C839 /* CopyJavaSources */; - targetProxy = 3DE2145D124666900033C839 /* PBXContainerItemProxy */; - }; - 89D0F1CD0F3B7062007831A7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 8D1107260486CEB800E47090 /* Assemble Application */; - targetProxy = 89D0F1CC0F3B7062007831A7 /* PBXContainerItemProxy */; - }; - 89D0F1D10F3B7062007831A7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 89D0F0480F393A6F007831A7 /* Compile Java */; - targetProxy = 89D0F1D00F3B7062007831A7 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 89C3F2900F5250A300B0048E /* Credits.rtf */ = { - isa = PBXVariantGroup; - children = ( - 89C3F2910F5250A300B0048E /* English */, - ); - name = Credits.rtf; - sourceTree = "<group>"; - }; - 89D0F0210F392F20007831A7 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 89D0F0220F392F20007831A7 /* English */, - ); - name = InfoPlist.strings; - sourceTree = "<group>"; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 3D634CAC1247805C0020F829 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - PRODUCT_NAME = JPortMidiHeaders; - }; - name = Debug; - }; - 3D634CAD1247805C0020F829 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - PRODUCT_NAME = JPortMidiHeaders; - ZERO_LINK = NO; - }; - name = Release; - }; - 3DE2142E124662AB0033C839 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - PRODUCT_NAME = CopyJavaSources; - }; - name = Debug; - }; - 3DE2142F124662AB0033C839 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - PRODUCT_NAME = CopyJavaSources; - ZERO_LINK = NO; - }; - name = Release; - }; - 89D0F0490F393A6F007831A7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = pmdefaults; - SRCROOT = ./pmdefaults; - }; - name = Debug; - }; - 89D0F04A0F393A6F007831A7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = pmdefaults; - SRCROOT = ./pmdefaults; - }; - name = Release; - }; - 89D0F1CA0F3B704F007831A7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = pmdefaults; - }; - name = Debug; - }; - 89D0F1CB0F3B704F007831A7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = pmdefaults; - }; - name = Release; - }; - C01FCF4B08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CONFIGURATION_BUILD_DIR = "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"; - COPY_PHASE_STRIP = NO; - INFOPLIST_FILE = pmdefaults/resources/Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - PRODUCT_NAME = pmdefaults; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - C01FCF4C08A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CONFIGURATION_BUILD_DIR = "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - INFOPLIST_FILE = pmdefaults/resources/Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - PRODUCT_NAME = PmDefaults; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; - ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; - ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 3D634CAE1247807A0020F829 /* Build configuration list for PBXAggregateTarget "JPortMidiHeaders" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3D634CAC1247805C0020F829 /* Debug */, - 3D634CAD1247805C0020F829 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3DE21434124662FF0033C839 /* Build configuration list for PBXAggregateTarget "CopyJavaSources" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3DE2142E124662AB0033C839 /* Debug */, - 3DE2142F124662AB0033C839 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 89D0F04B0F393AB7007831A7 /* Build configuration list for PBXLegacyTarget "Compile Java" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 89D0F0490F393A6F007831A7 /* Debug */, - 89D0F04A0F393A6F007831A7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 89D0F1D20F3B7080007831A7 /* Build configuration list for PBXAggregateTarget "PmDefaults" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 89D0F1CA0F3B704F007831A7 /* Debug */, - 89D0F1CB0F3B704F007831A7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Assemble Application" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4B08A954540054247B /* Debug */, - C01FCF4C08A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "pm_mac" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/3rdparty/portmidi/pm_mac/pmdefaults/make/build.xml b/3rdparty/portmidi/pm_mac/pmdefaults/make/build.xml deleted file mode 100644 index bd08c682082..00000000000 --- a/3rdparty/portmidi/pm_mac/pmdefaults/make/build.xml +++ /dev/null @@ -1,87 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project name="pmdefaults" default="jar" basedir=".."> - - <!-- Global Properties --> - <property environment="env"/> - - - <!-- building in Xcode --> - <condition property="product" value="${env.PRODUCT_NAME}"> - <isset property="env.PRODUCT_NAME"/> - </condition> - - <condition property="src" value="${env.SRCROOT}/src"> - <isset property="env.SRCROOT"/> - </condition> - - <condition property="obj" value="${env.OBJECT_FILE_DIR}"> - <isset property="env.OBJECT_FILE_DIR"/> - </condition> - - <condition property="dst" value="${env.BUILT_PRODUCTS_DIR}"> - <isset property="env.BUILT_PRODUCTS_DIR"/> - </condition> - - - <!-- building from the command line --> - <condition property="src" value="src"> - <not> - <isset property="src"/> - </not> - </condition> - - <condition property="obj" value="build/obj"> - <not> - <isset property="obj"/> - </not> - </condition> - - <condition property="dst" value="build"> - <not> - <isset property="dst"/> - </not> - </condition> - - <condition property="product" value="pmdefaults"> - <not> - <isset property="product"/> - </not> - </condition> - - - <!-- Targets --> - <target name="init" description="Create build directories"> - <mkdir dir="${obj}/${product}"/> - <mkdir dir="${dst}"/> - </target> - - <target name="compile" depends="init" description="Compile"> - <javac destdir="${obj}/${product}" deprecation="on" source="1.5" target="1.5" fork="true" debug="true" debuglevel="lines,source"> - <src path="${src}/java"/> - <classpath path="${src}/../lib/eawt-stubs.jar"/> - </javac> - </target> - - <target name="copy" depends="init" description="Copy resources"> - - </target> - - <target name="jar" depends="compile, copy" description="Assemble Jar file"> - <jar jarfile="${dst}/${product}.jar" basedir="${obj}/${product}" manifest="resources/Manifest" index="true"/> - </target> - - <target name="install" depends="jar" description="Alias for 'jar'"> - <!-- sent by Xcode --> - </target> - - <target name="clean" description="Removes build directories"> - <!-- sent by Xcode --> - <delete dir="${obj}/${product}"/> - <delete file="${dst}/${product}.jar"/> - </target> - - <target name="installhdrs" description=""> - <!-- sent by Xcode --> - <echo>"Nothing to do for install-headers phase"</echo> - </target> -</project> diff --git a/3rdparty/portmidi/pm_mac/pmdefaults/make/find-classrefs.sh b/3rdparty/portmidi/pm_mac/pmdefaults/make/find-classrefs.sh deleted file mode 100644 index 2217580d0d3..00000000000 --- a/3rdparty/portmidi/pm_mac/pmdefaults/make/find-classrefs.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -# Prints all class references made by all classes in a Jar file -# Depends on the output formatting of javap - -# create a temporary working directory -dir=`mktemp -d $TMPDIR/classrefs.XXXXXX` - -asm_dump="$dir/asm_dump" -all_classes="$dir/all_classes" - -# for each class in a Jar file, dump the full assembly -javap -c -classpath "$1" `/usr/bin/jar tf "$1" | grep "\.class" | sort | xargs | sed -e 's/\.class//g'` > $asm_dump - -# dump the initial list of all classes in the Jar file -/usr/bin/jar tf $1 | grep "\.class" | sed -e 's/\.class//g' >> $all_classes - -# dump all static class references -cat $asm_dump | grep //class | awk -F"//class " '{print $2}' | sort | uniq >> $all_classes - -# dump all references to classes made in methods -cat $asm_dump | grep //Method | awk -F"//Method " '{print $2}' | sort | uniq | grep "\." | awk -F"." '{print $1}' | sort | uniq >> $all_classes - -# dump all references to classes by direct field access -cat $asm_dump | grep //Field | awk -F"//Field " '{print $2}' | sort | uniq | grep "\:L" | awk -F"\:L" '{print $2}' | sort | uniq | awk -F"\;" '{print $1}' >> $all_classes - -# sort and reformat -sort $all_classes | uniq | grep -v "\"" | sed -e 's/\//\./g' - -# cleanup -rm -rf $dir diff --git a/3rdparty/portmidi/pm_mac/pmdefaults/resources/English.lproj/Credits.rtf b/3rdparty/portmidi/pm_mac/pmdefaults/resources/English.lproj/Credits.rtf deleted file mode 100644 index 18f83781e7b..00000000000 --- a/3rdparty/portmidi/pm_mac/pmdefaults/resources/English.lproj/Credits.rtf +++ /dev/null @@ -1,14 +0,0 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f0\b\fs24 \cf0 Author: -\b0 \ - Roger B. Dannenberg\ -\ - -\b With special thanks to: -\b0 \ - National Science Foundation\ -}
\ No newline at end of file diff --git a/3rdparty/portmidi/pm_mac/pmdefaults/resources/English.lproj/InfoPlist.strings b/3rdparty/portmidi/pm_mac/pmdefaults/resources/English.lproj/InfoPlist.strings Binary files differdeleted file mode 100644 index c7e5600f98a..00000000000 --- a/3rdparty/portmidi/pm_mac/pmdefaults/resources/English.lproj/InfoPlist.strings +++ /dev/null diff --git a/3rdparty/portmidi/pm_mac/pmdefaults/resources/Info.plist b/3rdparty/portmidi/pm_mac/pmdefaults/resources/Info.plist deleted file mode 100644 index 58bedb45013..00000000000 --- a/3rdparty/portmidi/pm_mac/pmdefaults/resources/Info.plist +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleDevelopmentRegion</key> - <string>English</string> - <key>CFBundleExecutable</key> - <string>JavaApplicationStub</string> - <key>CFBundleIconFile</key> - <string>pmdefaults.icns</string> - <key>CFBundleIdentifier</key> - <string></string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleName</key> - <string>PmDefaults</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleSignature</key> - <string>????</string> - <key>CFBundleVersion</key> - <string>1.0</string> - <key>CFBundleShortVersionString</key> - <string>1.0</string> - <key>Java</key> - <dict> - <key>ClassPath</key> - <string>$JAVAROOT/pmdefaults.jar</string> - <key>JVMVersion</key> - <string>1.5+</string> - <key>MainClass</key> - <string>pmdefaults.PmDefaults</string> - <key>Properties</key> - <dict> - <key>apple.laf.useScreenMenuBar</key> - <string>true</string> - </dict> - </dict> -</dict> -</plist> diff --git a/3rdparty/portmidi/pm_mac/pmdefaults/resources/Manifest b/3rdparty/portmidi/pm_mac/pmdefaults/resources/Manifest deleted file mode 100644 index 5dee9b0dc13..00000000000 --- a/3rdparty/portmidi/pm_mac/pmdefaults/resources/Manifest +++ /dev/null @@ -1 +0,0 @@ -Main-Class: pmdefaults/PmDefaults diff --git a/3rdparty/portmidi/pm_mac/pmmac.c b/3rdparty/portmidi/pm_mac/pmmac.c index 8160fa02bb1..6c310022465 100644 --- a/3rdparty/portmidi/pm_mac/pmmac.c +++ b/3rdparty/portmidi/pm_mac/pmmac.c @@ -18,7 +18,7 @@ non-CoreMIDI devices. PmDeviceID pm_default_input_device_id = -1; PmDeviceID pm_default_output_device_id = -1; -void pm_init() +void pm_init(void) { PmError err = pm_macosxcm_init(); // this is set when we return to Pm_Initialize, but we need it @@ -26,10 +26,10 @@ void pm_init() pm_initialized = TRUE; if (!err) { pm_default_input_device_id = find_default_device( - (char *)"/PortMidi/PM_RECOMMENDED_INPUT_DEVICE", TRUE, + "/PortMidi/PM_RECOMMENDED_INPUT_DEVICE", TRUE, pm_default_input_device_id); pm_default_output_device_id = find_default_device( - (char *)"/PortMidi/PM_RECOMMENDED_OUTPUT_DEVICE", FALSE, + "/PortMidi/PM_RECOMMENDED_OUTPUT_DEVICE", FALSE, pm_default_output_device_id); } } @@ -41,13 +41,14 @@ void pm_term(void) } -PmDeviceID Pm_GetDefaultInputDeviceID() +PmDeviceID Pm_GetDefaultInputDeviceID(void) { Pm_Initialize(); return pm_default_input_device_id; } -PmDeviceID Pm_GetDefaultOutputDeviceID() { +PmDeviceID Pm_GetDefaultOutputDeviceID(void) +{ Pm_Initialize(); return pm_default_output_device_id; } diff --git a/3rdparty/portmidi/pm_mac/pmmac.h b/3rdparty/portmidi/pm_mac/pmmac.h index 6cc0392c3f4..6b64fff2a95 100644 --- a/3rdparty/portmidi/pm_mac/pmmac.h +++ b/3rdparty/portmidi/pm_mac/pmmac.h @@ -1,4 +1,4 @@ /* pmmac.h */ extern PmDeviceID pm_default_input_device_id; -extern PmDeviceID pm_default_output_device_id;
\ No newline at end of file +extern PmDeviceID pm_default_output_device_id; diff --git a/3rdparty/portmidi/pm_mac/pmmacosxcm.c b/3rdparty/portmidi/pm_mac/pmmacosxcm.c index 71177dded11..81c531e033b 100644 --- a/3rdparty/portmidi/pm_mac/pmmacosxcm.c +++ b/3rdparty/portmidi/pm_mac/pmmacosxcm.c @@ -9,21 +9,67 @@ */ /* Notes: - since the input and output streams are represented by MIDIEndpointRef - values and almost no other state, we store the MIDIEndpointRef on - descriptors[midi->device_id].descriptor. The only other state we need - is for errors: we need to know if there is an error and if so, what is - the error text. We use a structure with two kinds of - host error: "error" and "callback_error". That way, asynchronous callbacks - do not interfere with other error information. + + Since the input and output streams are represented by + MIDIEndpointRef values and almost no other state, we store the + MIDIEndpointRef on pm_descriptors[midi->device_id].descriptor. - OS X does not seem to have an error-code-to-text function, so we will - just use text messages instead of error codes. + OS X does not seem to have an error-code-to-text function, so we + will just use text messages instead of error codes. + + Virtual device input synchronization: Once we create a virtual + device, it is always "on" and receiving messages, but it must drop + messages unless the device has been opened with Pm_OpenInput. To + open, the main thread should create all the data structures, then + call OSMemoryBarrier so that writes are observed, then set + is_opened = TRUE. To close without locks, we need to get the + callback to set is_opened to FALSE before we free data structures; + otherwise, there's a race condition where closing could delete + structures in use by the virtual_read_callback function. We send + 8 MIDI resets (FF) in a single packet to our own port to signal + the virtual_read_callback to close it. Then, we wait for the + callback to recognize the "close" packet and reset is_opened. + + Device scanning is done when you first open an application. + PortMIDI does not actively update the devices. Instead, you must + Pm_Terminate() and Pm_Initialize(), basically starting over. But + CoreMIDI does not have a way to shut down(!), and even + MIDIClientDispose() somehow retains state (and docs say do not + call it even if it worked). The solution, apparently, is to + call CFRunLoopRunInMode(), which somehow updates CoreMIDI + state. + + But when do we call CFRunLoopRunInMode()? I tried calling it + in midi_in_poll() which is called when you call Pm_Read() since + that is called often. I observed that this caused the program + to block for as long as 50ms and fairly often for 2 or 3ms. + What was Apple thinking? Is it really OK to design systems that + can only function with a tricky multi-threaded, non-blocking + priority-based solution, and then not provide a proof of concept + or documentation? Or is Apple's design really flawed? If anyone + at Apple reads this, please let me know -- I'm curious. + + But I digress... Here's the PortMidi approach: Since + CFRunLoopRunInMode() is potentially a non-realtime operation, + we only call it in Pm_Initialize(), where other calls to look + up devices and device names are quite slow to begin with. Again, + PortMidi does not actively scan for new or deleted devices, so + if devices change, you won't see it until the next Pm_Terminate + and Pm_Initialize. + + Calling CFRunLoopRunInMode() once is probably not enough. There + might be better way, but it seems to work to just call it 100 + times and insert 20 1ms delays (in case some inter-process + communication or synchronization is going on). + This adds 20ms to the wall time of Pm_Initialize(), but it + typically runs 30ms to much more (~4s), so this has little impact. */ #include <stdlib.h> -//#define CM_DEBUG 1 +/* turn on lots of debugging print statements */ +#define CM_DEBUG if (0) +/* #define CM_DEBUG if (1) */ #include "portmidi.h" #include "pmutil.h" @@ -39,39 +85,101 @@ #include <CoreMIDI/MIDIServices.h> #include <CoreAudio/HostTime.h> #include <unistd.h> +#include <libkern/OSAtomic.h> #define PACKET_BUFFER_SIZE 1024 -/* maximum overall data rate (OS X limit is 15000 bytes/second) */ -#define MAX_BYTES_PER_S 14000 - -/* Apple reports that packets are dropped when the MIDI bytes/sec - exceeds 15000. This is computed by "tracking the number of MIDI - bytes scheduled into 1-second buckets over the last six seconds - and averaging these counts." - - This is apparently based on timestamps, not on real time, so - we have to avoid constructing packets that schedule high speed - output even if the actual writes are delayed (which was my first - solution). - - The LIMIT_RATE symbol, if defined, enables code to modify - timestamps as follows: - After each packet is formed, the next allowable timestamp is - computed as this_packet_time + this_packet_len * delay_per_byte +/* maximum overall data rate (OS X limits MIDI rate in case there + * is a cycle among IAC ports. + */ - This is the minimum timestamp allowed in the next packet. +#define MAX_BYTES_PER_S 5400 - Note that this distorts accurate timestamps somewhat. +/* Apple reports that packets are dropped when the MIDI bytes/sec + exceeds 15000. This is computed by "tracking the number of MIDI + bytes scheduled into 1-second buckets over the last six seconds and + averaging these counts." This was confirmed in measurements + (2021) with pm_test/fast.c and pm_test/fastrcv.c Now, in 2022, with + macOS 12, pm_test/fast{rcv}.c show problems begin at 6000 bytes/sec. + Previously, we set MAX_BYTES_PER_S to 14000. This is reduced to + 5400 based on testing (which shows 5700 is too high) to fix the + packet loss problem that showed up with macOS 12. + + Experiments show this restriction applies to IAC bus MIDI, but not + to hardware interfaces. (I measured 0.5 Mbps each way over USB to a + Teensy 3.2 microcontroller implementing a USB MIDI loopback. Maybe + it would get 1 Mbps one-way, which would make the CoreMIDI + restriction 18x slower than USB. Maybe other USB MIDI + implementations are faster -- USB top speed for other protocols is + certainly higher than 1 Mbps!) + + This is apparently based on timestamps, not on real time, so we + have to avoid constructing packets that schedule high speed output + regardless of when writes occur. The solution is to alter + timestamps to limit data rates. This adds a slight time + distortion, e.g. an 11 note chord with all notes on the same + timestamp will be altered so that the last message is delayed by + 11 messages x 3 bytes/message / 5400 bytes/second = 6.1 ms. + Note that this is about 2x MIDI speed, but at least 18x slower + than USB MIDI. + + Altering timestamps creates another problem, which is that a sender + that exceeds the maximum rate can queue up an unbounded number of + messages. With non-USB MIDI devices, you could be writing 5x faster + to CoreMIDI than the hardware interface can send, causing an + unbounded backlog, not to mention that the output stream will be a + steady byte stream (e.g., one 3-byte MIDI message every 0.55 ms), + losing any original timing or rhythm. PortMidi does not guarantee + delivery if, over the long run, you write faster than the hardware + can send. + + The LIMIT_RATE symbol, if defined (which is the default), enables + code to modify timestamps for output to an IAC device as follows: + + Before a packet is formed, the message timestamp is set to the + maximum of the PortMidi timestamp (converted to CoreMIDI time) + and min_next_time. After each send, min_next_time is updated to + the packet time + packet length * delay_per_byte, which limits + the scheduled bytes-per-second. Also, after each packet list + flush, min_next_time is updated to the maximum of min_next_time + and the real time, which prevents many bytes to be scheduled in + the past. (We could more directly just say packets are never + scheduled in the past, but we prefer to get the current time -- a + system call -- only when we perform the more expensive operation + of flushing packets, so that's when we update min_next_time to + the current real time. If we are sending a lot, we have to flush + a lot, so the time will be updated frequently when it matters.) + + This possible adjustment to timestamps can distort accurate + timestamps by up to 0.556 us per 3-byte MIDI message. + + Nothing blocks the sender from queueing up an arbitrary number of + messages. Timestamps should be used for accurate timing by sending + timestamped messages a little ahead of real time, not for + scheduling an entire MIDI sequence at once! */ #define LIMIT_RATE 1 #define SYSEX_BUFFER_SIZE 128 +/* What is the maximum PortMidi device number for an IAC device? A + * cleaner design would be to not use the endpoint as our device + * representation. Instead, we could have a private extensible struct + * to keep all device information, including whether the device is + * implemented with the AppleMIDIIACDriver, which we need because we + * have to limit the data rate to this particular driver to avoid + * dropping messages. Rather than rewrite a lot of code, I am just + * allocating 64 bytes to flag which devices are IAC ones. If an IAC + * device number is greater than 63, PortMidi will fail to limit + * writes to it, but will not complain and will not access memory + * outside the 64-element array of char. + */ +#define MAX_IAC_NUM 63 #define VERBOSE_ON 1 #define VERBOSE if (VERBOSE_ON) -#define MIDI_SYSEX 0xf0 -#define MIDI_EOX 0xf7 +#define MIDI_SYSEX 0xf0 +#define MIDI_EOX 0xf7 +#define MIDI_CLOCK 0xf8 #define MIDI_STATUS_MASK 0x80 // "Ref"s are pointers on 32-bit machines and ints on 64 bit machines @@ -82,18 +190,17 @@ #define NULL_REF NULL #endif -static MIDIClientRef client = NULL_REF; /* Client handle to the MIDI server */ -static MIDIPortRef portIn = NULL_REF; /* Input port handle */ -static MIDIPortRef portOut = NULL_REF; /* Output port handle */ +static MIDIClientRef client = NULL_REF; /* Client handle to the MIDI server */ +static MIDIPortRef portIn = NULL_REF; /* Input port handle */ +static MIDIPortRef portOut = NULL_REF; /* Output port handle */ +static char isIAC[MAX_IAC_NUM + 1]; /* is device an IAC device */ extern pm_fns_node pm_macosx_in_dictionary; extern pm_fns_node pm_macosx_out_dictionary; -typedef struct midi_macosxcm_struct { - PmTimestamp sync_time; /* when did we last determine delta? */ +typedef struct coremidi_info_struct { + int is_virtual; /* virtual device (TRUE) or actual device (FALSE)? */ UInt64 delta; /* difference between stream time and real time in ns */ - UInt64 last_time; /* last output time in host units*/ - int first_message; /* tells midi_write to sychronize timestamps */ int sysex_mode; /* middle of sending sysex */ uint32_t sysex_word; /* accumulate data when receiving sysex */ uint32_t sysex_byte_count; /* count how many received */ @@ -103,26 +210,34 @@ typedef struct midi_macosxcm_struct { MIDIPacketList *packetList; /* a pointer to packetBuffer */ MIDIPacket *packet; Byte sysex_buffer[SYSEX_BUFFER_SIZE]; /* temp storage for sysex data */ - MIDITimeStamp sysex_timestamp; /* timestamp to use with sysex data */ + MIDITimeStamp sysex_timestamp; /* host timestamp to use with sysex data */ /* allow for running status (is running status possible here? -rbd): -cpr */ unsigned char last_command; int32_t last_msg_length; - /* limit midi data rate (a CoreMidi requirement): */ - UInt64 min_next_time; /* when can the next send take place? */ - int byte_count; /* how many bytes in the next packet list? */ + UInt64 min_next_time; /* when can the next send take place? (host time) */ + int isIACdevice; Float64 us_per_host_tick; /* host clock frequency, units of min_next_time */ UInt64 host_ticks_per_byte; /* host clock units per byte at maximum rate */ -} midi_macosxcm_node, *midi_macosxcm_type; +} coremidi_info_node, *coremidi_info_type; /* private function declarations */ -MIDITimeStamp timestamp_pm_to_cm(PmTimestamp timestamp); -PmTimestamp timestamp_cm_to_pm(MIDITimeStamp timestamp); +MIDITimeStamp timestamp_pm_to_cm(PmTimestamp timestamp); // returns host time +PmTimestamp timestamp_cm_to_pm(MIDITimeStamp timestamp); // returns ms -char* cm_get_full_endpoint_name(MIDIEndpointRef endpoint); +char* cm_get_full_endpoint_name(MIDIEndpointRef endpoint, int *isIAC); + +static PmError check_hosterror(OSStatus err, const char *msg) +{ + if (err != noErr) { + sprintf(pm_hosterror_text, "Host error %ld: %s", (long) err, msg); + pm_hosterror = TRUE; + return pmHostError; + } + return pmNoError; +} -static int -midi_length(int32_t msg) +static int midi_length(int32_t msg) { int status, high, low; static int high_lengths[] = { @@ -143,31 +258,31 @@ midi_length(int32_t msg) static PmTimestamp midi_synchronize(PmInternal *midi) { - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; - UInt64 pm_stream_time_2 = + coremidi_info_type info = (coremidi_info_type) midi->api_info; + UInt64 pm_stream_time_2 = // current time in ns AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); - PmTimestamp real_time; - UInt64 pm_stream_time; + PmTimestamp real_time; // in ms + UInt64 pm_stream_time; // in ns /* if latency is zero and this is an output, there is no time reference and midi_synchronize should never be called */ assert(midi->time_proc); - assert(!(midi->write_flag && midi->latency == 0)); + assert(midi->is_input || midi->latency != 0); do { /* read real_time between two reads of stream time */ pm_stream_time = pm_stream_time_2; real_time = (*midi->time_proc)(midi->time_info); - pm_stream_time_2 = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); + pm_stream_time_2 = AudioConvertHostTimeToNanos( + AudioGetCurrentHostTime()); /* repeat if more than 0.5 ms has elapsed */ } while (pm_stream_time_2 > pm_stream_time + 500000); - m->delta = pm_stream_time - ((UInt64) real_time * (UInt64) 1000000); - m->sync_time = real_time; + info->delta = pm_stream_time - ((UInt64) real_time * (UInt64) 1000000); + midi->sync_time = real_time; return real_time; } -static void -process_packet(MIDIPacket *packet, PmEvent *event, - PmInternal *midi, midi_macosxcm_type m) +static void process_packet(MIDIPacket *packet, PmEvent *event, + PmInternal *midi, coremidi_info_type info) { /* handle a packet of MIDI messages from CoreMIDI */ /* there may be multiple short messages in one packet (!) */ @@ -176,9 +291,9 @@ process_packet(MIDIPacket *packet, PmEvent *event, while (remaining_length > 0) { if (cur_packet_data[0] == MIDI_SYSEX || /* are we in the middle of a sysex message? */ - (m->last_command == 0 && + (info->last_command == 0 && !(cur_packet_data[0] & MIDI_STATUS_MASK))) { - m->last_command = 0; /* no running status */ + info->last_command = 0; /* no running status */ unsigned int amt = pm_read_bytes(midi, cur_packet_data, remaining_length, event->timestamp); @@ -188,7 +303,7 @@ process_packet(MIDIPacket *packet, PmEvent *event, /* this should never happen, because pm_read_bytes should * get and read all EOX bytes*/ midi->sysex_in_progress = FALSE; - m->last_command = 0; + info->last_command = 0; } else if (cur_packet_data[0] & MIDI_STATUS_MASK) { /* compute the length of the next (short) msg in packet */ unsigned int cur_message_length = midi_length(cur_packet_data[0]); @@ -199,8 +314,15 @@ process_packet(MIDIPacket *packet, PmEvent *event, /* since there's no more data, we're done */ return; } - m->last_msg_length = cur_message_length; - m->last_command = cur_packet_data[0]; + if (cur_packet_data[0] < MIDI_SYSEX) { + /* channel messages set running status */ + info->last_command = cur_packet_data[0]; + info->last_msg_length = cur_message_length; + } else if (cur_packet_data[0] < MIDI_CLOCK) { + /* system messages clear running status */ + info->last_command = 0; + info->last_msg_length = 0; + } switch (cur_message_length) { case 1: event->message = Pm_Message(cur_packet_data[0], 0, 0); @@ -220,9 +342,9 @@ process_packet(MIDIPacket *packet, PmEvent *event, return; /* give up on packet if continued after assert */ } pm_read_short(midi, event); - remaining_length -= m->last_msg_length; - cur_packet_data += m->last_msg_length; - } else if (m->last_msg_length > remaining_length + 1) { + remaining_length -= cur_message_length; + cur_packet_data += cur_message_length; + } else if (info->last_msg_length > remaining_length + 1) { /* we have running status, but not enough data */ #ifdef DEBUG printf("PortMidi debug msg: not enough data in CoreMIDI packet"); @@ -230,427 +352,588 @@ process_packet(MIDIPacket *packet, PmEvent *event, /* since there's no more data, we're done */ return; } else { /* output message using running status */ - switch (m->last_msg_length) { + switch (info->last_msg_length) { case 1: - event->message = Pm_Message(m->last_command, 0, 0); + event->message = Pm_Message(info->last_command, 0, 0); break; case 2: - event->message = Pm_Message(m->last_command, + event->message = Pm_Message(info->last_command, cur_packet_data[0], 0); break; case 3: - event->message = Pm_Message(m->last_command, + event->message = Pm_Message(info->last_command, cur_packet_data[0], cur_packet_data[1]); break; default: /* last_msg_length is invalid -- internal PortMIDI error */ - assert(m->last_msg_length == 1); + assert(info->last_msg_length == 1); } pm_read_short(midi, event); - remaining_length -= (m->last_msg_length - 1); - cur_packet_data += (m->last_msg_length - 1); + remaining_length -= (info->last_msg_length - 1); + cur_packet_data += (info->last_msg_length - 1); } } } - /* called when MIDI packets are received */ -static void -readProc(const MIDIPacketList *newPackets, void *refCon, void *connRefCon) +static void read_callback(const MIDIPacketList *newPackets, PmInternal *midi) { - PmInternal *midi; - midi_macosxcm_type m; PmEvent event; MIDIPacket *packet; unsigned int packetIndex; uint32_t now; unsigned int status; - -#ifdef CM_DEBUG - printf("readProc: numPackets %d: ", newPackets->numPackets); -#endif - /* Retrieve the context for this connection */ - midi = (PmInternal *) connRefCon; - m = (midi_macosxcm_type) midi->descriptor; - assert(m); + coremidi_info_type info = (coremidi_info_type) midi->api_info; + assert(info); + + CM_DEBUG printf("read_callback: numPackets %d: ", newPackets->numPackets); /* synchronize time references every 100ms */ now = (*midi->time_proc)(midi->time_info); - if (m->first_message || m->sync_time + 100 /*ms*/ < now) { + if (midi->first_message || midi->sync_time + 100 /*ms*/ < now) { /* time to resync */ now = midi_synchronize(midi); - m->first_message = FALSE; + midi->first_message = FALSE; } packet = (MIDIPacket *) &newPackets->packet[0]; - /* printf("readproc packet status %x length %d\n", packet->data[0], - packet->length); */ + /* hardware devices get untimed messages and apply timestamps. We + * want to preserve them because they should be more accurate than + * applying the current time here. virtual devices just pass on the + * packet->timeStamp, which could be anything. PortMidi says the + * PortMidi timestamp is the time the message is received. We do not + * know if we are receiving from a device driver or a virtual device. + * PortMidi sends to virtual devices get a current timestamp, so we + * can treat them as the receive time. If the timestamp is zero, + * suggested by CoreMIDI as the value to use for immediate delivery, + * then we plug in `now` which is obtained above. If another + * application sends bogus non-zero timestamps, we will convert them + * to this port's reference time and pass them as event.timestamp. + * Receiver beware. + */ + CM_DEBUG printf("read_callback packet @ %lld ns (host %lld) " + "status %x length %d\n", + AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()), + AudioGetCurrentHostTime(), + packet->data[0], packet->length); for (packetIndex = 0; packetIndex < newPackets->numPackets; packetIndex++) { /* Set the timestamp and dispatch this message */ - event.timestamp = (PmTimestamp) /* explicit conversion */ ( - (AudioConvertHostTimeToNanos(packet->timeStamp) - m->delta) / + CM_DEBUG printf(" packet->timeStamp %lld ns %lld host\n", + packet->timeStamp, + AudioConvertHostTimeToNanos(packet->timeStamp)); + if (packet->timeStamp == 0) { + event.timestamp = now; + } else { + event.timestamp = (PmTimestamp) /* explicit conversion */ ( + (AudioConvertHostTimeToNanos(packet->timeStamp) - info->delta) / (UInt64) 1000000); + } status = packet->data[0]; /* process packet as sysex data if it begins with MIDI_SYSEX, or MIDI_EOX or non-status byte with no running status */ -#ifdef CM_DEBUG - printf(" %d", packet->length); -#endif + CM_DEBUG printf(" len %d stat %x\n", packet->length, status); if (status == MIDI_SYSEX || status == MIDI_EOX || - ((!(status & MIDI_STATUS_MASK)) && !m->last_command)) { - /* previously was: !(status & MIDI_STATUS_MASK)) { + ((!(status & MIDI_STATUS_MASK)) && !info->last_command)) { + /* previously was: !(status & MIDI_STATUS_MASK)) { * but this could mistake running status for sysex data */ /* reset running status data -cpr */ - m->last_command = 0; - m->last_msg_length = 0; + info->last_command = 0; + info->last_msg_length = 0; /* printf("sysex packet length: %d\n", packet->length); */ pm_read_bytes(midi, packet->data, packet->length, event.timestamp); } else { - process_packet(packet, &event, midi, m); + process_packet(packet, &event, midi, info); } packet = MIDIPacketNext(packet); } -#ifdef CM_DEBUG - printf("\n"); -#endif } -static PmError -midi_in_open(PmInternal *midi, void *driverInfo) +/* callback for real devices - redirects to read_callback */ +static void device_read_callback(const MIDIPacketList *newPackets, + void *refCon, void *connRefCon) +{ + read_callback(newPackets, (PmInternal *) connRefCon); +} + + +/* callback for virtual devices - redirects to read_callback */ +static void virtual_read_callback(const MIDIPacketList *newPackets, + void *refCon, void *connRefCon) +{ + /* this refCon is the device ID -- if there is a valid ID and + the pm_descriptors table has a non-null pointer to a PmInternal, + then then device is open and should receive this data */ + PmDeviceID id = (PmDeviceID) (size_t) refCon; + if (id >= 0 && id < pm_descriptor_len) { + if (pm_descriptors[id].pub.opened) { + /* check for close request (7 reset status bytes): */ + if (newPackets->numPackets == 1 && + newPackets->packet[0].length == 8 && + /* CoreMIDI declares packets with 4-byte alignment, so we + * should be safe to test for 8 0xFF's as 2 32-bit values: */ + *(SInt32 *) &newPackets->packet[0].data[0] == -1 && + *(SInt32 *) &newPackets->packet[0].data[4] == -1) { + CM_DEBUG printf("got close request packet\n"); + pm_descriptors[id].pub.opened = FALSE; + return; + } else { + read_callback(newPackets, pm_descriptors[id].pm_internal); + } + } + } +} + + +/* allocate and initialize our internal coremidi connection info */ +static coremidi_info_type create_macosxcm_info(int is_virtual, int is_input) +{ + coremidi_info_type info = (coremidi_info_type) + pm_alloc(sizeof(coremidi_info_node)); + if (!info) { + return NULL; + } + info->is_virtual = is_virtual; + info->delta = 0; + info->sysex_mode = FALSE; + info->sysex_word = 0; + info->sysex_byte_count = 0; + info->packet = NULL; + info->last_command = 0; + info->last_msg_length = 0; + info->min_next_time = 0; + info->isIACdevice = FALSE; + info->us_per_host_tick = 1000000.0 / AudioGetHostClockFrequency(); + info->host_ticks_per_byte = + (UInt64) (1000000.0 / (info->us_per_host_tick * MAX_BYTES_PER_S)); + info->packetList = (is_input ? NULL : + (MIDIPacketList *) info->packetBuffer); + return info; +} + + +static PmError midi_in_open(PmInternal *midi, void *driverInfo) { MIDIEndpointRef endpoint; - midi_macosxcm_type m; + coremidi_info_type info; OSStatus macHostError; + int is_virtual = pm_descriptors[midi->device_id].pub.is_virtual; - /* insure that we have a time_proc for timing */ - if (midi->time_proc == NULL) { - if (!Pt_Started()) - Pt_Start(1, 0, 0); - /* time_get does not take a parameter, so coerce */ - midi->time_proc = (PmTimeProcPtr) Pt_Time; - } - endpoint = (MIDIEndpointRef) (long) descriptors[midi->device_id].descriptor; - if (endpoint == NULL_REF) { - return pmInvalidDeviceId; + /* if this is an external device, descriptor is a MIDIEndpointRef. + * if this is a virtual device for this application, descriptor is NULL. + */ + if (!is_virtual) { + endpoint = (MIDIEndpointRef) (intptr_t) + pm_descriptors[midi->device_id].descriptor; + if (endpoint == NULL_REF) { + return pmInvalidDeviceId; + } } - m = (midi_macosxcm_type) pm_alloc(sizeof(midi_macosxcm_node)); /* create */ - midi->descriptor = m; - if (!m) { + info = create_macosxcm_info(is_virtual, TRUE); + midi->api_info = info; + if (!info) { return pmInsufficientMemory; } - m->error[0] = 0; - m->callback_error[0] = 0; - m->sync_time = 0; - m->delta = 0; - m->last_time = 0; - m->first_message = TRUE; - m->sysex_mode = FALSE; - m->sysex_word = 0; - m->sysex_byte_count = 0; - m->packetList = NULL; - m->packet = NULL; - m->last_command = 0; - m->last_msg_length = 0; - - macHostError = MIDIPortConnectSource(portIn, endpoint, midi); - if (macHostError != noErr) { - pm_hosterror = macHostError; - sprintf(pm_hosterror_text, - "Host error %ld: MIDIPortConnectSource() in midi_in_open()", - (long) macHostError); - midi->descriptor = NULL; - pm_free(m); - return pmHostError; + if (!is_virtual) { + macHostError = MIDIPortConnectSource(portIn, endpoint, midi); + if (macHostError != noErr) { + midi->api_info = NULL; + pm_free(info); + return check_hosterror(macHostError, + "MIDIPortConnectSource() in midi_in_open()"); + } } - return pmNoError; } -static PmError -midi_in_close(PmInternal *midi) +static PmError midi_in_close(PmInternal *midi) { MIDIEndpointRef endpoint; OSStatus macHostError; PmError err = pmNoError; - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; + coremidi_info_type info = (coremidi_info_type) midi->api_info; - if (!m) return pmBadPtr; + if (!info) return pmBadPtr; - endpoint = (MIDIEndpointRef) (long) descriptors[midi->device_id].descriptor; + endpoint = (MIDIEndpointRef) (intptr_t) + pm_descriptors[midi->device_id].descriptor; if (endpoint == NULL_REF) { - pm_hosterror = pmBadPtr; + return pmBadPtr; } - /* shut off the incoming messages before freeing data structures */ - macHostError = MIDIPortDisconnectSource(portIn, endpoint); - if (macHostError != noErr) { - pm_hosterror = macHostError; - sprintf(pm_hosterror_text, - "Host error %ld: MIDIPortDisconnectSource() in midi_in_close()", - (long) macHostError); - err = pmHostError; + if (!info->is_virtual) { + /* shut off the incoming messages before freeing data structures */ + macHostError = MIDIPortDisconnectSource(portIn, endpoint); + /* If the source closes, you get paramErr == -50 here. It seems + * possible to monitor changes like sources closing by getting + * notifications ALL changes, but the CoreMIDI documentation is + * really terrible overall, and it seems easier to just ignore + * this host error. + */ + if (macHostError != noErr && macHostError != -50) { + pm_hosterror = TRUE; + err = check_hosterror(macHostError, + "MIDIPortDisconnectSource() in midi_in_close()"); + } + } else { + /* make "close virtual port" message */ + SInt64 close_port_bytes = 0xFFFFFFFFFFFFFFFF; + /* memory requirements: packet count (4), timestamp (8), length (2), + * data (8). Total: 22, but we allocate plenty more: + */ + Byte packetBuffer[64]; + MIDIPacketList *plist = (MIDIPacketList *) packetBuffer; + MIDIPacket *packet = MIDIPacketListInit(plist); + MIDIPacketListAdd(plist, 64, packet, 0, 8, + (const Byte *) &close_port_bytes); + macHostError = MIDISend(portOut, endpoint, plist); + if (macHostError != noErr) { + err = check_hosterror(macHostError, "MIDISend() (PortMidi close " + "port packet) in midi_in_close()"); + } + /* when packet is delivered, callback thread will clear opened; + * we must wait for that before removing the input queues etc. + * Maybe this could use signals of some kind, but if signals use + * locks, locks can cause priority inversion problems, so we will + * just sleep as needed. On the MIDI timescale, inserting a 0.5ms + * latency should be OK, as the application has no business + * opening/closing devices during time-critical moments. + * + * We expect the MIDI thread to close the device quickly (<0.5ms), + * but we wait up to 50ms in case something terrible happens like + * getting paged out in the middle of deliving packets to this + * virtual device. If there is still no response, we time out and + * force the close without the MIDI thread (even this will probably + * succeed - the problem would be: this thread proceeds to delete + * the input queues, and the freed memory is reallocated and + * overwritten so that queues are no longer usable. Meanwhile, + * the MIDI thread has already begun to deliver packets, so the + * check for opened == TRUE passed, but MIDI thread does not insert + * into queue until queue is freed, reallocated and overwritten. + */ + for (int i = 0; i < 100; i++) { /* up to 50ms delay */ + if (!pm_descriptors[midi->device_id].pub.opened) { + break; + } + usleep(500); /* 0.5ms */ + } + pm_descriptors[midi->device_id].pub.opened = FALSE; /* force it */ } - - midi->descriptor = NULL; - pm_free(midi->descriptor); - + midi->api_info = NULL; + pm_free(info); return err; } -static PmError -midi_out_open(PmInternal *midi, void *driverInfo) +static PmError midi_out_open(PmInternal *midi, void *driverInfo) { - midi_macosxcm_type m; + coremidi_info_type info; + int is_virtual = pm_descriptors[midi->device_id].pub.is_virtual; - m = (midi_macosxcm_type) pm_alloc(sizeof(midi_macosxcm_node)); /* create */ - midi->descriptor = m; - if (!m) { + info = create_macosxcm_info(is_virtual, FALSE); + if (midi->device_id <= MAX_IAC_NUM) { + info->isIACdevice = isIAC[midi->device_id]; + CM_DEBUG printf("midi_out_open isIACdevice %d\n", info->isIACdevice); + } + midi->api_info = info; + if (!info) { return pmInsufficientMemory; } - m->error[0] = 0; - m->callback_error[0] = 0; - m->sync_time = 0; - m->delta = 0; - m->last_time = 0; - m->first_message = TRUE; - m->sysex_mode = FALSE; - m->sysex_word = 0; - m->sysex_byte_count = 0; - m->packetList = (MIDIPacketList *) m->packetBuffer; - m->packet = NULL; - m->last_command = 0; - m->last_msg_length = 0; - m->min_next_time = 0; - m->byte_count = 0; - m->us_per_host_tick = 1000000.0 / AudioGetHostClockFrequency(); - m->host_ticks_per_byte = (UInt64) (1000000.0 / - (m->us_per_host_tick * MAX_BYTES_PER_S)); return pmNoError; } -static PmError -midi_out_close(PmInternal *midi) +static PmError midi_out_close(PmInternal *midi) { - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; - if (!m) return pmBadPtr; - - midi->descriptor = NULL; - pm_free(midi->descriptor); - + coremidi_info_type info = (coremidi_info_type) midi->api_info; + if (!info) return pmBadPtr; + midi->api_info = NULL; + pm_free(info); return pmNoError; } -static PmError -midi_abort(PmInternal *midi) + +/* MIDIDestinationCreate apparently cannot create a virtual device + * without a callback and a "refCon" parameter, but when we create + * a virtual device, we do not want a PortMidi stream yet -- that + * should wait for the user to open the stream. So, for the refCon, + * use the PortMidi device ID. The callback will check if the + * device is opened within PortMidi, and if so, use the pm_descriptors + * table to locate the corresponding PmStream. + */ +static PmError midi_create_virtual(int is_input, const char *name, + void *device_info) { - PmError err = pmNoError; OSStatus macHostError; - MIDIEndpointRef endpoint = - (MIDIEndpointRef) (long) descriptors[midi->device_id].descriptor; - macHostError = MIDIFlushOutput(endpoint); + MIDIEndpointRef endpoint; + CFStringRef nameRef; + PmDeviceID id = pm_add_device("CoreMIDI", name, is_input, TRUE, NULL, + (is_input ? &pm_macosx_in_dictionary : + &pm_macosx_out_dictionary)); + if (id < 0) { /* error -- out of memory or name conflict? */ + return id; + } + + nameRef = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII); + if (is_input) { + macHostError = MIDIDestinationCreate(client, nameRef, + virtual_read_callback, (void *) (intptr_t) id, + &endpoint); + } else { + macHostError = MIDISourceCreate(client, nameRef, &endpoint); + } + CFRelease(nameRef); + if (macHostError != noErr) { - pm_hosterror = macHostError; - sprintf(pm_hosterror_text, - "Host error %ld: MIDIFlushOutput()", (long) macHostError); - err = pmHostError; + /* undo the device we just allocated */ + pm_undo_add_device(id); + return check_hosterror(macHostError, (is_input ? + "MIDIDestinationCreate() in midi_create_virtual()" : + "MIDISourceCreate() in midi_create_virtual()")); } - return err; + pm_descriptors[id].descriptor = (void *) (intptr_t) endpoint; + return id; } -static PmError -midi_write_flush(PmInternal *midi, PmTimestamp timestamp) +static PmError midi_delete_virtual(PmDeviceID id) { + MIDIEndpointRef endpoint; OSStatus macHostError; - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; - MIDIEndpointRef endpoint = - (MIDIEndpointRef) (long) descriptors[midi->device_id].descriptor; - assert(m); + PmError err = pmNoError; + + endpoint = (MIDIEndpointRef) (long) pm_descriptors[id].descriptor; + if (endpoint == NULL_REF) { + return pmBadPtr; + } + macHostError = MIDIEndpointDispose(endpoint); + return check_hosterror(macHostError, + "MIDIEndpointDispose() in midi_in_close()"); +} + + +static PmError midi_abort(PmInternal *midi) +{ + PmError err = pmNoError; + OSStatus macHostError; + MIDIEndpointRef endpoint = (MIDIEndpointRef) (intptr_t) + pm_descriptors[midi->device_id].descriptor; + macHostError = MIDIFlushOutput(endpoint); + return check_hosterror(macHostError, + "MIDIFlushOutput() in midi_abort()"); +} + + +static PmError midi_write_flush(PmInternal *midi, PmTimestamp timestamp) +{ + OSStatus macHostError = noErr; + coremidi_info_type info = (coremidi_info_type) midi->api_info; + MIDIEndpointRef endpoint = (MIDIEndpointRef) (intptr_t) + pm_descriptors[midi->device_id].descriptor; + assert(info); assert(endpoint); - if (m->packet != NULL) { + if (info->packet != NULL) { /* out of space, send the buffer and start refilling it */ - /* before we can send, maybe delay to limit data rate. OS X allows - * 15KB/s. */ - UInt64 now = AudioGetCurrentHostTime(); - if (now < m->min_next_time) { - usleep((useconds_t) - ((m->min_next_time - now) * m->us_per_host_tick)); + /* update min_next_time each flush to support rate limit */ + UInt64 host_now = AudioGetCurrentHostTime(); + if (host_now > info->min_next_time) + info->min_next_time = host_now; + if (info->is_virtual) { + macHostError = MIDIReceived(endpoint, info->packetList); + } else { + macHostError = MIDISend(portOut, endpoint, info->packetList); } - macHostError = MIDISend(portOut, endpoint, m->packetList); - m->packet = NULL; /* indicate no data in packetList now */ - m->min_next_time = now + m->byte_count * m->host_ticks_per_byte; - m->byte_count = 0; - if (macHostError != noErr) goto send_packet_error; + info->packet = NULL; /* indicate no data in packetList now */ } - return pmNoError; - -send_packet_error: - pm_hosterror = macHostError; - sprintf(pm_hosterror_text, - "Host error %ld: MIDISend() in midi_write()", - (long) macHostError); - return pmHostError; - + return check_hosterror(macHostError, (info->is_virtual ? + "MIDIReceived() in midi_write()" : + "MIDISend() in midi_write()")); } -static PmError -send_packet(PmInternal *midi, Byte *message, unsigned int messageLength, - MIDITimeStamp timestamp) +static PmError send_packet(PmInternal *midi, Byte *message, + unsigned int messageLength, MIDITimeStamp timestamp) { PmError err; - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; - assert(m); + coremidi_info_type info = (coremidi_info_type) midi->api_info; + assert(info); - /* printf("add %d to packet %p len %d\n", message[0], m->packet, messageLength); */ - m->packet = MIDIPacketListAdd(m->packetList, sizeof(m->packetBuffer), - m->packet, timestamp, messageLength, - message); - m->byte_count += messageLength; - if (m->packet == NULL) { + CM_DEBUG printf("add %d to packet %p len %d timestamp %lld @ %lld ns " + "(host %lld)\n", + message[0], info->packet, messageLength, timestamp, + AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()), + AudioGetCurrentHostTime()); + info->packet = MIDIPacketListAdd(info->packetList, + sizeof(info->packetBuffer), info->packet, + timestamp, messageLength, message); +#if defined(LIMIT_SEND_RATE) && (LIMIT_SEND_RATE != 0) + info->byte_count += messageLength; +#endif + if (info->packet == NULL) { /* out of space, send the buffer and start refilling it */ /* make midi->packet non-null to fool midi_write_flush into sending */ - m->packet = (MIDIPacket *) 4; + info->packet = (MIDIPacket *) 4; /* timestamp is 0 because midi_write_flush ignores timestamp since * timestamps are already in packets. The timestamp parameter is here * because other API's need it. midi_write_flush can be called * from system-independent code that must be cross-API. */ if ((err = midi_write_flush(midi, 0)) != pmNoError) return err; - m->packet = MIDIPacketListInit(m->packetList); - assert(m->packet); /* if this fails, it's a programming error */ - m->packet = MIDIPacketListAdd(m->packetList, sizeof(m->packetBuffer), - m->packet, timestamp, messageLength, - message); - assert(m->packet); /* can't run out of space on first message */ + info->packet = MIDIPacketListInit(info->packetList); + assert(info->packet); /* if this fails, it's a programming error */ + info->packet = MIDIPacketListAdd(info->packetList, + sizeof(info->packetBuffer), info->packet, + timestamp, messageLength, message); + assert(info->packet); /* can't run out of space on first message */ } return pmNoError; } -static PmError -midi_write_short(PmInternal *midi, PmEvent *event) +static PmError midi_write_short(PmInternal *midi, PmEvent *event) { PmTimestamp when = event->timestamp; PmMessage what = event->message; MIDITimeStamp timestamp; - UInt64 when_ns; - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; + coremidi_info_type info = (coremidi_info_type) midi->api_info; Byte message[4]; unsigned int messageLength; - if (m->packet == NULL) { - m->packet = MIDIPacketListInit(m->packetList); + if (info->packet == NULL) { + info->packet = MIDIPacketListInit(info->packetList); /* this can never fail, right? failure would indicate something unrecoverable */ - assert(m->packet); + assert(info->packet); } - /* compute timestamp */ - if (when == 0) when = midi->now; - /* if latency == 0, midi->now is not valid. We will just set it to zero */ - if (midi->latency == 0) when = 0; - when_ns = ((UInt64) (when + midi->latency) * (UInt64) 1000000) + m->delta; - timestamp = (MIDITimeStamp) AudioConvertNanosToHostTime(when_ns); + /* PortMidi specifies that incoming timestamps are the receive + * time. Devices attach their receive times, but virtual devices + * do not. Instead, they pass along whatever timestamp was sent to + * them. We do not know if we are connected to real or virtual + * device. To avoid wild timestamps on the receiving end, we + * consider 2 cases: PortMidi timestamp is zero or latency is + * zero. Both mean send immediately, so we attach the current time + * which will go out immediately and arrive with a sensible + * timestamp (not zero and not zero mapped to the client's local + * time). Otherwise, we assume the timestamp is reasonable. It + * might be slighly in the past, but we pass it along after + * translation to MIDITimeStamp units. + * + * Compute timestamp: use current time if timestamp is zero or + * latency is zero. Both mean no timing and send immediately. + */ + if (when == 0 || midi->latency == 0) { + timestamp = AudioGetCurrentHostTime(); + } else { /* translate PortMidi time + latency to CoreMIDI time */ + timestamp = ((UInt64) (when + midi->latency) * (UInt64) 1000000) + + info->delta; + timestamp = AudioConvertNanosToHostTime(timestamp); + } message[0] = Pm_MessageStatus(what); message[1] = Pm_MessageData1(what); message[2] = Pm_MessageData2(what); messageLength = midi_length(what); - - /* make sure we go foreward in time */ - if (timestamp < m->min_next_time) timestamp = m->min_next_time; - - #ifdef LIMIT_RATE - if (timestamp < m->last_time) - timestamp = m->last_time; - m->last_time = timestamp + messageLength * m->host_ticks_per_byte; - #endif +#ifdef LIMIT_RATE + /* Make sure we go forward in time. */ + if (timestamp < info->min_next_time) { + timestamp = info->min_next_time; + } + /* Note that if application is way behind and slowly catching up, then + * timestamps could be increasing faster than real time, and since + * timestamps are used to estimate data rate, our estimate could be + * low, causing CoreMIDI to drop packets. This seems very unlikely. + */ + if (info->isIACdevice || info->is_virtual) { + info->min_next_time = timestamp + messageLength * + info->host_ticks_per_byte; + } +#endif /* Add this message to the packet list */ return send_packet(midi, message, messageLength, timestamp); } -static PmError -midi_begin_sysex(PmInternal *midi, PmTimestamp when) +static PmError midi_begin_sysex(PmInternal *midi, PmTimestamp when) { UInt64 when_ns; - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; - assert(m); - m->sysex_byte_count = 0; + coremidi_info_type info = (coremidi_info_type) midi->api_info; + assert(info); + info->sysex_byte_count = 0; /* compute timestamp */ if (when == 0) when = midi->now; /* if latency == 0, midi->now is not valid. We will just set it to zero */ if (midi->latency == 0) when = 0; - when_ns = ((UInt64) (when + midi->latency) * (UInt64) 1000000) + m->delta; - m->sysex_timestamp = (MIDITimeStamp) AudioConvertNanosToHostTime(when_ns); + when_ns = ((UInt64) (when + midi->latency) * (UInt64) 1000000) + + info->delta; + info->sysex_timestamp = + (MIDITimeStamp) AudioConvertNanosToHostTime(when_ns); + UInt64 now; /* only make system time call when writing a virtual port */ + if (info->is_virtual && info->sysex_timestamp < + (now = AudioGetCurrentHostTime())) { + info->sysex_timestamp = now; + } - if (m->packet == NULL) { - m->packet = MIDIPacketListInit(m->packetList); + if (info->packet == NULL) { + info->packet = MIDIPacketListInit(info->packetList); /* this can never fail, right? failure would indicate something unrecoverable */ - assert(m->packet); + assert(info->packet); } return pmNoError; } -static PmError -midi_end_sysex(PmInternal *midi, PmTimestamp when) +static PmError midi_end_sysex(PmInternal *midi, PmTimestamp when) { PmError err; - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; - assert(m); + coremidi_info_type info = (coremidi_info_type) midi->api_info; + assert(info); +#ifdef LIMIT_RATE /* make sure we go foreward in time */ - if (m->sysex_timestamp < m->min_next_time) - m->sysex_timestamp = m->min_next_time; - - #ifdef LIMIT_RATE - if (m->sysex_timestamp < m->last_time) - m->sysex_timestamp = m->last_time; - m->last_time = m->sysex_timestamp + m->sysex_byte_count * - m->host_ticks_per_byte; - #endif + if (info->sysex_timestamp < info->min_next_time) + info->sysex_timestamp = info->min_next_time; + + if (info->isIACdevice) { + info->min_next_time = info->sysex_timestamp + info->sysex_byte_count * + info->host_ticks_per_byte; + } +#endif /* now send what's in the buffer */ - err = send_packet(midi, m->sysex_buffer, m->sysex_byte_count, - m->sysex_timestamp); - m->sysex_byte_count = 0; + err = send_packet(midi, info->sysex_buffer, info->sysex_byte_count, + info->sysex_timestamp); + info->sysex_byte_count = 0; if (err != pmNoError) { - m->packet = NULL; /* flush everything in the packet list */ - return err; + info->packet = NULL; /* flush everything in the packet list */ } - return pmNoError; + return err; } -static PmError -midi_write_byte(PmInternal *midi, unsigned char byte, PmTimestamp timestamp) +static PmError midi_write_byte(PmInternal *midi, unsigned char byte, + PmTimestamp timestamp) { - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; - assert(m); - if (m->sysex_byte_count >= SYSEX_BUFFER_SIZE) { + coremidi_info_type info = (coremidi_info_type) midi->api_info; + assert(info); + if (info->sysex_byte_count >= SYSEX_BUFFER_SIZE) { PmError err = midi_end_sysex(midi, timestamp); if (err != pmNoError) return err; } - m->sysex_buffer[m->sysex_byte_count++] = byte; + info->sysex_buffer[info->sysex_byte_count++] = byte; return pmNoError; } -static PmError -midi_write_realtime(PmInternal *midi, PmEvent *event) +static PmError midi_write_realtime(PmInternal *midi, PmEvent *event) { /* to send a realtime message during a sysex message, first flush all pending sysex bytes into packet list */ @@ -660,27 +943,10 @@ midi_write_realtime(PmInternal *midi, PmEvent *event) return midi_write_short(midi, event); } -static unsigned int midi_has_host_error(PmInternal *midi) -{ - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; - return (m->callback_error[0] != 0) || (m->error[0] != 0); -} - -static void midi_get_host_error(PmInternal *midi, char *msg, unsigned int len) +static unsigned int midi_check_host_error(PmInternal *midi) { - midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor; - msg[0] = 0; /* initialize to empty string */ - if (m) { /* make sure there is an open device to examine */ - if (m->error[0]) { - strncpy(msg, m->error, len); - m->error[0] = 0; /* clear the error */ - } else if (m->callback_error[0]) { - strncpy(msg, m->callback_error, len); - m->callback_error[0] = 0; /* clear the error */ - } - msg[len - 1] = 0; /* make sure string is terminated */ - } + return FALSE; } @@ -695,6 +961,7 @@ MIDITimeStamp timestamp_pm_to_cm(PmTimestamp timestamp) } } + PmTimestamp timestamp_cm_to_pm(MIDITimeStamp timestamp) { UInt64 nanos; @@ -708,179 +975,170 @@ PmTimestamp timestamp_cm_to_pm(MIDITimeStamp timestamp) ////////////////////////////////////// // Obtain the name of an endpoint without regard for whether it has connections. // The result should be released by the caller. -CFStringRef EndpointName(MIDIEndpointRef endpoint, bool isExternal) +CFStringRef EndpointName(MIDIEndpointRef endpoint, bool isExternal, int *isIAC) { - CFMutableStringRef result = CFStringCreateMutable(NULL, 0); - CFStringRef str; - - // begin with the endpoint's name - str = NULL; - MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &str); - if (str != NULL) { - CFStringAppend(result, str); - CFRelease(str); - } + CFMutableStringRef result = CFStringCreateMutable(NULL, 0); + CFStringRef str; + *isIAC = FALSE; - MIDIEntityRef entity = NULL_REF; - MIDIEndpointGetEntity(endpoint, &entity); - if (entity == NULL_REF) - // probably virtual - return result; - - if (CFStringGetLength(result) == 0) { - // endpoint name has zero length -- try the entity + // begin with the endpoint's name str = NULL; - MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &str); + MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &str); if (str != NULL) { - CFStringAppend(result, str); - CFRelease(str); - } - } - // now consider the device's name - MIDIDeviceRef device = NULL_REF; - MIDIEntityGetDevice(entity, &device); - if (device == NULL_REF) - return result; - - str = NULL; - MIDIObjectGetStringProperty(device, kMIDIPropertyName, &str); - if (CFStringGetLength(result) == 0) { - CFRelease(result); - return str; - } - if (str != NULL) { - // if an external device has only one entity, throw away - // the endpoint name and just use the device name - if (isExternal && MIDIDeviceGetNumberOfEntities(device) < 2) { - CFRelease(result); - return str; - } else { - if (CFStringGetLength(str) == 0) { + CFStringAppend(result, str); CFRelease(str); + } + MIDIEntityRef entity = NULL_REF; + MIDIEndpointGetEntity(endpoint, &entity); + if (entity == NULL_REF) { + // probably virtual return result; - } - // does the entity name already start with the device name? - // (some drivers do this though they shouldn't) - // if so, do not prepend - if (CFStringCompareWithOptions( result, /* endpoint name */ - str /* device name */, - CFRangeMake(0, CFStringGetLength(str)), 0) != kCFCompareEqualTo) { - // prepend the device name to the entity name - if (CFStringGetLength(result) > 0) - CFStringInsert(result, 0, CFSTR(" ")); - CFStringInsert(result, 0, str); - } - CFRelease(str); - } - } - return result; -} - + } + if (!isExternal) { /* detect IAC devices */ + //extern const CFStringRef kMIDIPropertyDriverOwner; + MIDIObjectGetStringProperty(entity, kMIDIPropertyDriverOwner, &str); + if (str != NULL) { + char s[32]; /* driver name may truncate, but that's OK */ + CFStringGetCString(str, s, 31, kCFStringEncodingUTF8); + s[31] = 0; /* make sure it is terminated just to be safe */ + CM_DEBUG printf("driver %s\n", s); + *isIAC = (strcmp(s, "com.apple.AppleMIDIIACDriver") == 0); + } + } -// Obtain the name of an endpoint, following connections. -// The result should be released by the caller. -static CFStringRef ConnectedEndpointName(MIDIEndpointRef endpoint) -{ - CFMutableStringRef result = CFStringCreateMutable(NULL, 0); - CFStringRef str; - OSStatus err; - long i; - - // Does the endpoint have connections? - CFDataRef connections = NULL; - long nConnected = 0; - bool anyStrings = false; - err = MIDIObjectGetDataProperty(endpoint, kMIDIPropertyConnectionUniqueID, &connections); - if (connections != NULL) { - // It has connections, follow them - // Concatenate the names of all connected devices - nConnected = CFDataGetLength(connections) / (int32_t) sizeof(MIDIUniqueID); - if (nConnected) { - const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); - for (i = 0; i < nConnected; ++i, ++pid) { - MIDIUniqueID id = EndianS32_BtoN(*pid); - MIDIObjectRef connObject; - MIDIObjectType connObjectType; - err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); - if (err == noErr) { - if (connObjectType == kMIDIObjectType_ExternalSource || - connObjectType == kMIDIObjectType_ExternalDestination) { - // Connected to an external device's endpoint (10.3 and later). - str = EndpointName((MIDIEndpointRef)(connObject), true); - } else { - // Connected to an external device (10.2) (or something else, catch-all) - str = NULL; - MIDIObjectGetStringProperty(connObject, kMIDIPropertyName, &str); - } - if (str != NULL) { - if (anyStrings) - CFStringAppend(result, CFSTR(", ")); - else anyStrings = true; + if (CFStringGetLength(result) == 0) { + // endpoint name has zero length -- try the entity + str = NULL; + MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &str); + if (str != NULL) { CFStringAppend(result, str); CFRelease(str); - } } - } } - CFRelease(connections); - } - if (anyStrings) - return result; + // now consider the device's name + MIDIDeviceRef device = NULL_REF; + MIDIEntityGetDevice(entity, &device); + if (device == NULL_REF) + return result; - // Here, either the endpoint had no connections, or we failed to obtain names for any of them. - return EndpointName(endpoint, false); + str = NULL; + MIDIObjectGetStringProperty(device, kMIDIPropertyName, &str); + if (CFStringGetLength(result) == 0) { + CFRelease(result); + return str; + } + if (str != NULL) { + // if an external device has only one entity, throw away + // the endpoint name and just use the device name + if (isExternal && MIDIDeviceGetNumberOfEntities(device) < 2) { + CFRelease(result); + return str; + } else { + if (CFStringGetLength(str) == 0) { + CFRelease(str); + return result; + } + // does the entity name already start with the device name? + // (some drivers do this though they shouldn't) + // if so, do not prepend + if (CFStringCompareWithOptions(result, /* endpoint name */ + str, /* device name */ + CFRangeMake(0, CFStringGetLength(str)), 0) != + kCFCompareEqualTo) { + // prepend the device name to the entity name + if (CFStringGetLength(result) > 0) + CFStringInsert(result, 0, CFSTR(" ")); + CFStringInsert(result, 0, str); + } + CFRelease(str); + } + } + return result; } -char* cm_get_full_endpoint_name(MIDIEndpointRef endpoint) +// Obtain the name of an endpoint, following connections. +// The result should be released by the caller. +static CFStringRef ConnectedEndpointName(MIDIEndpointRef endpoint, int *isIAC) { -#ifdef OLDCODE - MIDIEntityRef entity; - MIDIDeviceRef device; + CFMutableStringRef result = CFStringCreateMutable(NULL, 0); + CFStringRef str; + OSStatus err; + long i; + + // Does the endpoint have connections? + CFDataRef connections = NULL; + long nConnected = 0; + bool anyStrings = false; + err = MIDIObjectGetDataProperty(endpoint, kMIDIPropertyConnectionUniqueID, + &connections); + if (connections != NULL) { + // It has connections, follow them + // Concatenate the names of all connected devices + nConnected = CFDataGetLength(connections) / + (int32_t) sizeof(MIDIUniqueID); + if (nConnected) { + const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); + for (i = 0; i < nConnected; ++i, ++pid) { + MIDIUniqueID id = EndianS32_BtoN(*pid); + MIDIObjectRef connObject; + MIDIObjectType connObjectType; + err = MIDIObjectFindByUniqueID(id, &connObject, + &connObjectType); + if (err == noErr) { + if (connObjectType == kMIDIObjectType_ExternalSource || + connObjectType == kMIDIObjectType_ExternalDestination) { + // Connected to an external device's endpoint (>=10.3) + str = EndpointName((MIDIEndpointRef)(connObject), true, + isIAC); + } else { + // Connected to an external device (10.2) + // (or something else, catch-all) + str = NULL; + MIDIObjectGetStringProperty(connObject, + kMIDIPropertyName, &str); + } + if (str != NULL) { + if (anyStrings) + CFStringAppend(result, CFSTR(", ")); + else anyStrings = true; + CFStringAppend(result, str); + CFRelease(str); + } + } + } + } + CFRelease(connections); + } + if (anyStrings) + return result; // caller should release result - CFStringRef endpointName = NULL; - CFStringRef deviceName = NULL; -#endif - CFStringRef fullName = NULL; - CFStringEncoding defaultEncoding; - char* newName; + CFRelease(result); - /* get the default string encoding */ - defaultEncoding = CFStringGetSystemEncoding(); + // Here, either the endpoint had no connections, or we failed to + // obtain names for any of them. + return EndpointName(endpoint, false, isIAC); +} - fullName = ConnectedEndpointName(endpoint); - -#ifdef OLDCODE - /* get the entity and device info */ - MIDIEndpointGetEntity(endpoint, &entity); - MIDIEntityGetDevice(entity, &device); - /* create the nicely formated name */ - MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &endpointName); - MIDIObjectGetStringProperty(device, kMIDIPropertyName, &deviceName); - if (deviceName != NULL) { - fullName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@: %@"), - deviceName, endpointName); - } else { - fullName = endpointName; - } -#endif - /* copy the string into our buffer */ - newName = (char *) malloc(CFStringGetLength(fullName) + 1); - CFStringGetCString(fullName, newName, CFStringGetLength(fullName) + 1, - defaultEncoding); +char *cm_get_full_endpoint_name(MIDIEndpointRef endpoint, int *isIAC) +{ + /* Thanks to Dan Wilcox for fixes for Unicode handling */ + CFStringRef fullName = ConnectedEndpointName(endpoint, isIAC); + CFIndex utf16_len = CFStringGetLength(fullName) + 1; + CFIndex max_byte_len = CFStringGetMaximumSizeForEncoding( + utf16_len, kCFStringEncodingUTF8) + 1; + char* pmname = (char *) pm_alloc(CFStringGetLength(fullName) + 1); + + /* copy the string into our buffer; note that there may be some wasted + space, but the total waste is not large */ + CFStringGetCString(fullName, pmname, max_byte_len, kCFStringEncodingUTF8); /* clean up */ -#ifdef OLDCODE - if (endpointName) CFRelease(endpointName); - if (deviceName) CFRelease(deviceName); -#endif if (fullName) CFRelease(fullName); - - return newName; + return pmname; } - pm_fns_node pm_macosx_in_dictionary = { none_write_short, @@ -894,8 +1152,7 @@ pm_fns_node pm_macosx_in_dictionary = { midi_abort, midi_in_close, success_poll, - midi_has_host_error, - midi_get_host_error, + midi_check_host_error }; pm_fns_node pm_macosx_out_dictionary = { @@ -910,23 +1167,50 @@ pm_fns_node pm_macosx_out_dictionary = { midi_abort, midi_out_close, success_poll, - midi_has_host_error, - midi_get_host_error, + midi_check_host_error }; +/* We do nothing with callbacks, but generating the callbacks also + * updates CoreMIDI state. Callback may not be essential, but calling + * the CFRunLoopRunInMode is necessary. + */ +void cm_notify(const MIDINotification *msg, void *refCon) +{ + /* for debugging, trace change notifications: + const char *descr[] = { + "undefined (0)", + "kMIDIMsgSetupChanged", + "kMIDIMsgObjectAdded", + "kMIDIMsgObjectRemoved", + "kMIDIMsgPropertyChanged", + "kMIDIMsgThruConnectionsChanged", + "kMIDIMsgSerialPortOwnerChanged", + "kMIDIMsgIOError"}; + + printf("MIDI Notify, messageID %d (%s)\n", (int) msg->messageID, + descr[(int) msg->messageID]); + */ + return; +} + + PmError pm_macosxcm_init(void) { ItemCount numInputs, numOutputs, numDevices; MIDIEndpointRef endpoint; int i; - OSStatus macHostError; - char *error_text; + OSStatus macHostError = noErr; + const char *error_text; + + memset(isIAC, 0, sizeof(isIAC)); /* initialize all FALSE */ + + /* Register interface CoreMIDI with create_virtual fn */ + pm_add_interf("CoreMIDI", &midi_create_virtual, &midi_delete_virtual); + /* no check for error return because this always succeeds */ /* Determine the number of MIDI devices on the system */ numDevices = MIDIGetNumberOfDevices(); - numInputs = MIDIGetNumberOfSources(); - numOutputs = MIDIGetNumberOfDestinations(); /* Return prematurely if no devices exist on the system Note that this is not an error. There may be no devices. @@ -937,74 +1221,88 @@ PmError pm_macosxcm_init(void) return pmNoError; } - /* Initialize the client handle */ - macHostError = MIDIClientCreate(CFSTR("PortMidi"), NULL, NULL, &client); + if (client == NULL_REF) { + macHostError = MIDIClientCreate(CFSTR("PortMidi"), &cm_notify, NULL, + &client); + } else { /* see notes above on device scanning */ + for (int i = 0; i < 100; i++) { + // look for any changes before scanning for devices + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); + if (i % 5 == 0) Pt_Sleep(1); /* insert 20 delays */ + } + } if (macHostError != noErr) { - error_text = (char *)"MIDIClientCreate() in pm_macosxcm_init()"; + error_text = "MIDIClientCreate() in pm_macosxcm_init()"; goto error_return; } + numInputs = MIDIGetNumberOfSources(); + numOutputs = MIDIGetNumberOfDestinations(); /* Create the input port */ - macHostError = MIDIInputPortCreate(client, CFSTR("Input port"), readProc, - NULL, &portIn); + macHostError = MIDIInputPortCreate(client, CFSTR("Input port"), + device_read_callback, NULL, &portIn); if (macHostError != noErr) { - error_text = (char *)"MIDIInputPortCreate() in pm_macosxcm_init()"; + error_text = "MIDIInputPortCreate() in pm_macosxcm_init()"; goto error_return; } - + /* Create the output port */ macHostError = MIDIOutputPortCreate(client, CFSTR("Output port"), &portOut); if (macHostError != noErr) { - error_text = (char *)"MIDIOutputPortCreate() in pm_macosxcm_init()"; + error_text = "MIDIOutputPortCreate() in pm_macosxcm_init()"; goto error_return; } /* Iterate over the MIDI input devices */ for (i = 0; i < numInputs; i++) { + int isIACflag; endpoint = MIDIGetSource(i); if (endpoint == NULL_REF) { continue; } - /* set the first input we see to the default */ if (pm_default_input_device_id == -1) - pm_default_input_device_id = pm_descriptor_index; + pm_default_input_device_id = pm_descriptor_len; /* Register this device with PortMidi */ - pm_add_device((char *)"CoreMIDI", cm_get_full_endpoint_name(endpoint), - TRUE, (void *) (long) endpoint, &pm_macosx_in_dictionary); + pm_add_device("CoreMIDI", + cm_get_full_endpoint_name(endpoint, &isIACflag), TRUE, FALSE, + (void *) (intptr_t) endpoint, &pm_macosx_in_dictionary); } /* Iterate over the MIDI output devices */ for (i = 0; i < numOutputs; i++) { + int isIACflag; + PmDeviceID id; endpoint = MIDIGetDestination(i); if (endpoint == NULL_REF) { continue; } - /* set the first output we see to the default */ if (pm_default_output_device_id == -1) - pm_default_output_device_id = pm_descriptor_index; + pm_default_output_device_id = pm_descriptor_len; /* Register this device with PortMidi */ - pm_add_device((char *)"CoreMIDI", cm_get_full_endpoint_name(endpoint), - FALSE, (void *) (long) endpoint, - &pm_macosx_out_dictionary); + id = pm_add_device("CoreMIDI", + cm_get_full_endpoint_name(endpoint, &isIACflag), FALSE, FALSE, + (void *) (intptr_t) endpoint, &pm_macosx_out_dictionary); + /* if this is an IAC device, tuck that info away for write functions */ + if (isIACflag && id <= MAX_IAC_NUM) { + isIAC[id] = TRUE; + } } return pmNoError; error_return: - pm_hosterror = macHostError; - sprintf(pm_hosterror_text, "Host error %ld: %s\n", (long) macHostError, - error_text); pm_macosxcm_term(); /* clear out any opened ports */ - return pmHostError; + return check_hosterror(macHostError, error_text); } void pm_macosxcm_term(void) { - if (client != NULL_REF) MIDIClientDispose(client); + /* docs say do not explicitly dispose of client + if (client != NULL_REF) MIDIClientDispose(client); */ if (portIn != NULL_REF) MIDIPortDispose(portIn); if (portOut != NULL_REF) MIDIPortDispose(portOut); } diff --git a/3rdparty/portmidi/pm_mac/pmmacosxcm.h b/3rdparty/portmidi/pm_mac/pmmacosxcm.h index ea79902d40b..ab8b5edbcb7 100644 --- a/3rdparty/portmidi/pm_mac/pmmacosxcm.h +++ b/3rdparty/portmidi/pm_mac/pmmacosxcm.h @@ -3,4 +3,4 @@ PmError pm_macosxcm_init(void); void pm_macosxcm_term(void); -PmDeviceID find_default_device(char *path, int input, PmDeviceID id); +PmDeviceID find_default_device(const char *path, int input, PmDeviceID id); diff --git a/3rdparty/portmidi/pm_mac/readbinaryplist.c b/3rdparty/portmidi/pm_mac/readbinaryplist.c index 858dd029ec7..9564e700d0b 100644 --- a/3rdparty/portmidi/pm_mac/readbinaryplist.c +++ b/3rdparty/portmidi/pm_mac/readbinaryplist.c @@ -3,26 +3,28 @@ readbinaryplist.c -- Roger B. Dannenberg, Jun 2008 Based on ReadBinaryPList.m by Jens Ayton, 2007 -Note that this code is intended to read preference files and has an upper -bound on file size (currently 100MB) and assumes in some places that 32 bit -offsets are sufficient. +Note that this code is intended to read preference files and has an +upper bound on file size (currently 100MB) and assumes in some places +that 32 bit offsets are sufficient. Here are his comments: Reader for binary property list files (version 00). -This has been found to work on all 566 binary plists in my ~/Library/Preferences/ -and /Library/Preferences/ directories. This probably does not provide full -test coverage. It has also been found to provide different data to Apple's -implementation when presented with a key-value archive. This is because Apple's -implementation produces undocumented CFKeyArchiverUID objects. My implementation -produces dictionaries instead, matching the in-file representation used in XML -and OpenStep plists. See extract_uid(). - -Full disclosure: in implementing this software, I read one comment and one -struct defintion in CFLite, Apple's implementation, which is under the APSL -license. I also deduced the information about CFKeyArchiverUID from that code. -However, none of the implementation was copied. +This has been found to work on all 566 binary plists in my +~/Library/Preferences/ and /Library/Preferences/ directories. This +probably does not provide full test coverage. It has also been found +to provide different data to Apple's implementation when presented +with a key-value archive. This is because Apple's implementation +produces undocumented CFKeyArchiverUID objects. My implementation +produces dictionaries instead, matching the in-file representation +used in XML and OpenStep plists. See extract_uid(). + +Full disclosure: in implementing this software, I read one comment and +one struct defintion in CFLite, Apple's implementation, which is under +the APSL license. I also deduced the information about +CFKeyArchiverUID from that code. However, none of the implementation +was copied. Copyright (C) 2007 Jens Ayton @@ -33,16 +35,16 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ @@ -72,21 +74,19 @@ memory requested or calls longjmp, so callers don't have to check. */ #include <sys/types.h> -#include <sys/param.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <stdio.h> #include <sys/stat.h> #include "readbinaryplist.h" -#include "osxsupport.h" #include <Carbon/Carbon.h> #define NO 0 #define YES 1 #define BOOL int -//#define MAXPATHLEN 256 +#define MAX_PATH_LEN 256 /* there are 2 levels of error logging/printing: * BPLIST_LOG and BPLIST_LOG_VERBOSE @@ -99,22 +99,21 @@ memory requested or calls longjmp, so callers don't have to check. * parameters like printf but might be a no-op. */ -#define BPLIST_LOG_VERBOSE 0 -#define BPLIST_LOG 0 +/* #define BPLIST_LOG_VERBOSE 1 */ -#if BPLIST_LOG_VERBOSE +#if defined(BPLIST_LOG_VERBOSE) && (BPLIST_LOG_VERBOSE != 0) #ifndef BPLIST_LOG #define BPLIST_LOG 1 #endif #endif -#if BPLIST_LOG +#if defined(BPLIST_LOG) && (BPLIST_LOG != 0) #define bplist_log printf #else #define bplist_log(...) #endif -#if BPLIST_LOG_VERBOSE +#if defined(BPLIST_LOG_VERBOSE) && (BPLIST_LOG_VERBOSE != 0) #define bplist_log_verbose bplist_log #else #define bplist_log_verbose(...) @@ -156,7 +155,7 @@ static void *allocate(size_t size) return result; } -void bplist_free_data() +void bplist_free_data(void) { while (block_list) { void *next = *(void **)block_list; @@ -207,10 +206,12 @@ typedef struct bplist_info static value_ptr bplist_read_pldata(pldata_ptr data); -static value_ptr bplist_read_pref(char *filename, OSType folder_type); -static uint64_t read_sized_int(bplist_info_ptr bplist, uint64_t offset, uint8_t size); +static value_ptr bplist_read_pref(const char *filename, OSType folder_type); +static uint64_t read_sized_int(bplist_info_ptr bplist, uint64_t offset, + uint8_t size); static uint64_t read_offset(bplist_info_ptr bplist, uint64_t index); -static BOOL read_self_sized_int(bplist_info_ptr bplist, uint64_t offset, uint64_t *outValue, size_t *outSize); +static BOOL read_self_sized_int(bplist_info_ptr bplist, uint64_t offset, + uint64_t *outValue, size_t *outSize); static value_ptr extract_object(bplist_info_ptr bplist, uint64_t objectRef); static value_ptr extract_simple(bplist_info_ptr bplist, uint64_t offset); @@ -219,7 +220,8 @@ static value_ptr extract_real(bplist_info_ptr bplist, uint64_t offset); static value_ptr extract_date(bplist_info_ptr bplist, uint64_t offset); static value_ptr extract_data(bplist_info_ptr bplist, uint64_t offset); static value_ptr extract_ascii_string(bplist_info_ptr bplist, uint64_t offset); -static value_ptr extract_unicode_string(bplist_info_ptr bplist, uint64_t offset); +static value_ptr extract_unicode_string(bplist_info_ptr bplist, + uint64_t offset); static value_ptr extract_uid(bplist_info_ptr bplist, uint64_t offset); static value_ptr extract_array(bplist_info_ptr bplist, uint64_t offset); static value_ptr extract_dictionary(bplist_info_ptr bplist, uint64_t offset); @@ -236,15 +238,18 @@ void value_set_integer(value_ptr v, int64_t i) { v->tag = kTAG_INT; v->integer = i; } + void value_set_real(value_ptr v, double d) { v->tag = kTAG_REAL; v->real = d; } + // d is seconds since 1 January 2001 void value_set_date(value_ptr v, double d) { v->tag = kTAG_DATE; v->real = d; } + void value_set_ascii_string(value_ptr v, const uint8_t *s, size_t len) { v->tag = kTAG_ASCIISTRING; v->string = (char *) allocate(len + 1); @@ -252,6 +257,7 @@ void value_set_ascii_string(value_ptr v, const uint8_t *s, size_t len) { v->string[len] = 0; } + void value_set_unicode_string(value_ptr v, const uint8_t *s, size_t len) { v->tag = kTAG_UNICODESTRING; v->string = (char *) allocate(len + 1); @@ -276,8 +282,10 @@ void value_set_data(value_ptr v, const uint8_t *data, size_t len) { printf("value at %p gets data at %p\n", v, pldata); } + // caller releases ownership of array to value_ptr v -void value_set_array(value_ptr v, value_ptr *array, size_t length) { +void value_set_array(value_ptr v, value_ptr *array, size_t length) +{ array_ptr a = (array_ptr) allocate(sizeof(array_node)); a->array = array; a->length = length; @@ -285,8 +293,10 @@ void value_set_array(value_ptr v, value_ptr *array, size_t length) { v->array = a; } + // caller releases ownership of dict to value_ptr v -void value_set_dict(value_ptr v, dict_ptr dict) { +void value_set_dict(value_ptr v, dict_ptr dict) +{ v->tag = kTAG_DICTIONARY; v->dict = dict; } @@ -334,7 +344,7 @@ BOOL is_binary_plist(pldata_ptr data) } -value_ptr bplist_read_file(char *filename) +value_ptr bplist_read_file(const char *filename) { struct stat stbuf; pldata_node pldata; @@ -343,7 +353,7 @@ value_ptr bplist_read_file(char *filename) value_ptr value; int rslt = stat(filename, &stbuf); if (rslt) { - #if BPLIST_LOG + #if defined(BPLIST_LOG) && (BPLIST_LOG != 0) perror("in stat"); #endif bplist_log("Could not stat %s, error %d\n", filename, rslt); @@ -380,12 +390,11 @@ value_ptr bplist_read_file(char *filename) return value; } -// use old Carbon method on PPC -#ifdef OSX_PPC -value_ptr bplist_read_pref(char *filename, OSType folder_type) + +value_ptr bplist_read_pref(const char *filename, OSType folder_type) { FSRef prefdir; - char cstr[MAXPATHLEN]; + char cstr[MAX_PATH_LEN]; OSErr err = FSFindFolder(kOnAppropriateDisk, folder_type, FALSE, &prefdir); @@ -393,57 +402,23 @@ value_ptr bplist_read_pref(char *filename, OSType folder_type) bplist_log("Error finding preferences folder: %d\n", err); return NULL; } - err = FSRefMakePath(&prefdir, (UInt8 *) cstr, (UInt32) (MAXPATHLEN - 1)); + err = FSRefMakePath(&prefdir, (UInt8 *) cstr, (UInt32) (MAX_PATH_LEN - 1)); if (err) { bplist_log("Error making path name for preferences folder: %d\n", err); return NULL; } - strlcat(cstr, "/", MAXPATHLEN); - strlcat(cstr, filename, MAXPATHLEN); + strlcat(cstr, "/", MAX_PATH_LEN); + strlcat(cstr, filename, MAX_PATH_LEN); return bplist_read_file(cstr); } -#else -value_ptr bplist_read_pref(char *filename, OSType folder_type) -{ - char cstr[MAXPATHLEN]; - char *foundstr; - - memset(cstr, 0, MAXPATHLEN); - - // for later OS X, the user preferences folder (~/Library/Preferences) is not available directly from Cocoa, - // Apple documentation suggests just using POSIX APIs like so. - if (folder_type == kPreferencesFolderType) - { - strlcpy(cstr, getenv("HOME"), MAXPATHLEN); - strlcat(cstr, "/Library/Preferences", MAXPATHLEN); - } - else // the system preferences folder (~/Library/PreferencePanes) is accessible from Cocoa however - { - foundstr = FindPrefsDir(); - - if (!foundstr) { - bplist_log("Error finding preferences folder\n"); - return NULL; - } - - strlcat(cstr, foundstr, MAXPATHLEN); - free(foundstr); - foundstr = NULL; - } - - strlcat(cstr, "/", MAXPATHLEN); - strlcat(cstr, filename, MAXPATHLEN); - - return bplist_read_file(cstr); -} -#endif -value_ptr bplist_read_system_pref(char *filename) { + +value_ptr bplist_read_system_pref(const char *filename) { return bplist_read_pref(filename, kSystemPreferencesFolderType); } -value_ptr bplist_read_user_pref(char *filename) { +value_ptr bplist_read_user_pref(const char *filename) { return bplist_read_pref(filename, kPreferencesFolderType); } @@ -774,7 +749,7 @@ static value_ptr extract_date(bplist_info_ptr bplist, uint64_t offset) uint64_t bplist_get_a_size(bplist_info_ptr bplist, - uint64_t *offset_ptr, char *msg) + uint64_t *offset_ptr, const char *msg) { uint64_t size = bplist->data_bytes[*offset_ptr] & 0x0F; (*offset_ptr)++; @@ -814,7 +789,7 @@ static value_ptr extract_data(bplist_info_ptr bplist, uint64_t offset) assert(bplist->data_bytes != NULL && offset < bplist->length); - if ((size = bplist_get_a_size(bplist, &offset, (char *)"data")) == UINT64_MAX) + if ((size = bplist_get_a_size(bplist, &offset, "data")) == UINT64_MAX) return NULL; value = value_create(); @@ -831,7 +806,7 @@ static value_ptr extract_ascii_string(bplist_info_ptr bplist, uint64_t offset) assert(bplist->data_bytes != NULL && offset < bplist->length); - if ((size = bplist_get_a_size(bplist, &offset, (char *)"ascii string")) == + if ((size = bplist_get_a_size(bplist, &offset, "ascii string")) == UINT64_MAX) return NULL; @@ -850,7 +825,7 @@ static value_ptr extract_unicode_string(bplist_info_ptr bplist, uint64_t offset) assert(bplist->data_bytes != NULL && offset < bplist->length); - if ((size = bplist_get_a_size(bplist, &offset, (char *)"unicode string")) == + if ((size = bplist_get_a_size(bplist, &offset, "unicode string")) == UINT64_MAX) return NULL; @@ -911,7 +886,7 @@ static value_ptr extract_array(bplist_info_ptr bplist, uint64_t offset) assert(bplist->data_bytes != NULL && offset < bplist->length); - if ((count = bplist_get_a_size(bplist, &offset, (char *)"array")) == UINT64_MAX) + if ((count = bplist_get_a_size(bplist, &offset, "array")) == UINT64_MAX) return NULL; if (count > UINT64_MAX / bplist->object_ref_size - offset) { @@ -973,7 +948,7 @@ static value_ptr extract_dictionary(bplist_info_ptr bplist, uint64_t offset) assert(bplist->data_bytes != NULL && offset < bplist->length); - if ((count = bplist_get_a_size(bplist, &offset, (char *)"array")) == UINT64_MAX) + if ((count = bplist_get_a_size(bplist, &offset, "array")) == UINT64_MAX) return NULL; if (count > UINT64_MAX / (bplist->object_ref_size * 2) - offset) { @@ -1037,7 +1012,7 @@ char *value_get_asciistring(value_ptr v) } -value_ptr value_dict_lookup_using_string(value_ptr v, char *key) +value_ptr value_dict_lookup_using_string(value_ptr v, const char *key) { dict_ptr dict; if (v->tag != kTAG_DICTIONARY) return NULL; // not a dictionary @@ -1053,7 +1028,7 @@ value_ptr value_dict_lookup_using_string(value_ptr v, char *key) return NULL; /* not found */ } -value_ptr value_dict_lookup_using_path(value_ptr v, char *path) +value_ptr value_dict_lookup_using_path(value_ptr v, const char *path) { char key[MAX_KEY_SIZE]; while (*path) { /* more to the path */ diff --git a/3rdparty/portmidi/pm_mac/readbinaryplist.h b/3rdparty/portmidi/pm_mac/readbinaryplist.h index e82056a0b79..8b096d08e2e 100644 --- a/3rdparty/portmidi/pm_mac/readbinaryplist.h +++ b/3rdparty/portmidi/pm_mac/readbinaryplist.h @@ -71,16 +71,16 @@ typedef struct value_struct { } value_node, *value_ptr; -value_ptr bplist_read_file(char *filename); -value_ptr bplist_read_user_pref(char *filename); -value_ptr bplist_read_system_pref(char *filename); +value_ptr bplist_read_file(const char *filename); +value_ptr bplist_read_user_pref(const char *filename); +value_ptr bplist_read_system_pref(const char *filename); void bplist_free_data(void); /*************** functions for accessing values ****************/ char *value_get_asciistring(value_ptr v); -value_ptr value_dict_lookup_using_string(value_ptr v, char *key); -value_ptr value_dict_lookup_using_path(value_ptr v, char *path); +value_ptr value_dict_lookup_using_string(value_ptr v, const char *key); +value_ptr value_dict_lookup_using_path(value_ptr v, const char *path); /*************** functions for debugging ***************/ diff --git a/3rdparty/portmidi/pm_mingw/README-MINGW.txt b/3rdparty/portmidi/pm_mingw/README-MINGW.txt deleted file mode 100644 index e01a7fed441..00000000000 --- a/3rdparty/portmidi/pm_mingw/README-MINGW.txt +++ /dev/null @@ -1,11 +0,0 @@ -README-MINGW.txt -- note on MinGW and PortMidi - -Roger Dannenberg -20 Sep 2010 - -Fabian Rutte writes that CMake can build files for Code::Blocks -under MinGW. - -I would guess that a simple Unix Makefile output from CMake would -also work, but I haven't tested it. - diff --git a/3rdparty/portmidi/pm_mingw/eclipse/README.txt b/3rdparty/portmidi/pm_mingw/eclipse/README.txt deleted file mode 100644 index 2b58e13ab17..00000000000 --- a/3rdparty/portmidi/pm_mingw/eclipse/README.txt +++ /dev/null @@ -1,23 +0,0 @@ -These files, dot-cproject and dot-project, come from Philip Martin -(posted on Media_api mailing list on September 3, 2008). -He writes: "I do not have a makefile. I used Eclipse + CDT to build -PortMidi using MinGw. ... The two files .project and .cproject I -believe must be in the root of the portmidi tree to work with Eclipse. -... I have only compiled the relevant sources into one .dll here." - -The .project and .cproject files have been renamed to dot-project and -dot-cproject here to make them more visible. To use them, you will -need to rename them to .project and .cproject, and probably move them -to the portmidi tree root. - -At this time, no one is actively maintaining Eclipse or MinGw versions -of PortMidi, so these files may be out-of-date or have other problems. -Feel free to submit updates or discuss the possibility of maintaining -these or some equivalent files for MinGw. - -Update, 20 Sep 2010: CMake supports Code::Blocks in conjunction with -MinGW. - -Roger Dannenberg -18-Oct-2008 - diff --git a/3rdparty/portmidi/pm_mingw/eclipse/dot-cproject b/3rdparty/portmidi/pm_mingw/eclipse/dot-cproject deleted file mode 100644 index 06b47e3f567..00000000000 --- a/3rdparty/portmidi/pm_mingw/eclipse/dot-cproject +++ /dev/null @@ -1,710 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<?fileVersion 4.0.0?> - -<cproject> -<storageModule moduleId="org.eclipse.cdt.core.settings"> -<cconfiguration id="cdt.managedbuild.config.gnu.mingw.so.debug.1580321004"> -<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.mingw.so.debug.1580321004" moduleId="org.eclipse.cdt.core.settings" name="Debug"> -<externalSettings> -<externalSetting> -<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/PortMidi"/> -<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/PortMidi/Debug"/> -</externalSetting> -</externalSettings> -<extensions> -<extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/> -<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> -<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> -<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> -</extensions> -</storageModule> -<storageModule moduleId="cdtBuildSystem" version="4.0.0"> -<configuration artifactExtension="dll" artifactName="PortMidi" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.mingw.so.debug.1580321004" name="Debug" parent="cdt.managedbuild.config.gnu.mingw.so.debug"> -<folderInfo id="cdt.managedbuild.config.gnu.mingw.so.debug.1580321004." name="/" resourcePath=""> -<toolChain id="cdt.managedbuild.toolchain.gnu.mingw.so.debug.1545417885" name="MinGW GCC" superClass="cdt.managedbuild.toolchain.gnu.mingw.so.debug"> -<targetPlatform id="cdt.managedbuild.target.gnu.platform.mingw.so.debug.415542300" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.mingw.so.debug"/> -<builder buildPath="${workspace_loc:/PortMidi/Debug}" id="cdt.managedbuild.tool.gnu.builder.mingw.base.592172807" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="CDT Internal Builder" superClass="cdt.managedbuild.tool.gnu.builder.mingw.base"/> -<tool id="cdt.managedbuild.tool.gnu.assembler.mingw.so.debug.1889129808" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.mingw.so.debug"> -<option id="gnu.both.asm.option.flags.1498736889" name="Assembler flags" superClass="gnu.both.asm.option.flags"/> -<option id="gnu.both.asm.option.include.paths.1734867019" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath"> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/pm_common}""/> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/pm_win}""/> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/porttime}""/> -</option> -<option id="gnu.both.asm.option.warnings.nowarn.1657300607" name="Suppress warnings (-W)" superClass="gnu.both.asm.option.warnings.nowarn"/> -<option id="gnu.both.asm.option.version.1995252368" name="Announce version (-v)" superClass="gnu.both.asm.option.version"/> -<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1250436110" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> -</tool> -<tool id="cdt.managedbuild.tool.gnu.archiver.mingw.base.1211487028" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.mingw.base"/> -<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.so.debug.81091790" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.so.debug"> -<option id="gnu.cpp.compiler.mingw.so.debug.option.optimization.level.1750954034" name="Optimization Level" superClass="gnu.cpp.compiler.mingw.so.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/> -<option id="gnu.cpp.compiler.mingw.so.debug.option.debugging.level.1357163228" name="Debug Level" superClass="gnu.cpp.compiler.mingw.so.debug.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/> -</tool> -<tool id="cdt.managedbuild.tool.gnu.c.compiler.mingw.so.debug.428547337" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.mingw.so.debug"> -<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.mingw.so.debug.option.optimization.level.1361318269" name="Optimization Level" superClass="gnu.c.compiler.mingw.so.debug.option.optimization.level" valueType="enumerated"/> -<option id="gnu.c.compiler.mingw.so.debug.option.debugging.level.798971050" name="Debug Level" superClass="gnu.c.compiler.mingw.so.debug.option.debugging.level" value="gnu.c.debugging.level.max" valueType="enumerated"/> -<option id="gnu.c.compiler.option.preprocessor.nostdinc.635731758" name="Do not search system directories (-nostdinc)" superClass="gnu.c.compiler.option.preprocessor.nostdinc"/> -<option id="gnu.c.compiler.option.preprocessor.preprocess.1129104455" name="Preprocess only (-E)" superClass="gnu.c.compiler.option.preprocessor.preprocess"/> -<option id="gnu.c.compiler.option.preprocessor.def.symbols.924940285" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols"/> -<option id="gnu.c.compiler.option.preprocessor.undef.symbol.1996330931" name="Undefined symbols (-U)" superClass="gnu.c.compiler.option.preprocessor.undef.symbol" valueType="undefDefinedSymbols"> -<listOptionValue builtIn="false" value="_STDCALL_SUPPORTED"/> -</option> -<option id="gnu.c.compiler.option.include.paths.276080219" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath"> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/pm_common}""/> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/pm_win}""/> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/porttime}""/> -</option> -<option id="gnu.c.compiler.option.optimization.flags.1032442929" name="Other optimization flags" superClass="gnu.c.compiler.option.optimization.flags"/> -<option id="gnu.c.compiler.option.debugging.other.509079500" name="Other debugging flags" superClass="gnu.c.compiler.option.debugging.other"/> -<option id="gnu.c.compiler.option.debugging.gprof.708510440" name="Generate gprof information (-pg)" superClass="gnu.c.compiler.option.debugging.gprof"/> -<option id="gnu.c.compiler.option.debugging.prof.1379528770" name="Generate prof information (-p)" superClass="gnu.c.compiler.option.debugging.prof"/> -<option id="gnu.c.compiler.option.warnings.syntax.76950723" name="Check syntax only (-fsyntax-only)" superClass="gnu.c.compiler.option.warnings.syntax"/> -<option id="gnu.c.compiler.option.warnings.pedantic.503180272" name="Pedantic (-pedantic)" superClass="gnu.c.compiler.option.warnings.pedantic"/> -<option id="gnu.c.compiler.option.warnings.pedantic.error.332437973" name="Pedantic warnings as errors (-pedantic-errors)" superClass="gnu.c.compiler.option.warnings.pedantic.error"/> -<option id="gnu.c.compiler.option.warnings.nowarn.1830350073" name="Inhibit all warnings (-w)" superClass="gnu.c.compiler.option.warnings.nowarn"/> -<option id="gnu.c.compiler.option.warnings.allwarn.77655170" name="All warnings (-Wall)" superClass="gnu.c.compiler.option.warnings.allwarn"/> -<option id="gnu.c.compiler.option.warnings.toerrors.1707691615" name="Warnings as errors (-Werror)" superClass="gnu.c.compiler.option.warnings.toerrors"/> -<option id="gnu.c.compiler.option.misc.other.1929071594" name="Other flags" superClass="gnu.c.compiler.option.misc.other"/> -<option id="gnu.c.compiler.option.misc.verbose.1368165423" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose"/> -<option id="gnu.c.compiler.option.misc.ansi.1130235771" name="Support ANSI programs (-ansi)" superClass="gnu.c.compiler.option.misc.ansi"/> -<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.532732416" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> -</tool> -<tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.so.debug.2093989251" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.so.debug"> -<option defaultValue="true" id="gnu.c.link.mingw.so.debug.option.shared.210833175" name="Shared (-shared)" superClass="gnu.c.link.mingw.so.debug.option.shared" valueType="boolean"/> -<option id="gnu.c.link.option.nostart.1109377759" name="Do not use standard start files (-nostartfiles)" superClass="gnu.c.link.option.nostart"/> -<option id="gnu.c.link.option.nodeflibs.1969639513" name="Do not use default libraries (-nodefaultlibs)" superClass="gnu.c.link.option.nodeflibs"/> -<option id="gnu.c.link.option.nostdlibs.1939458836" name="No startup or default libs (-nostdlib)" superClass="gnu.c.link.option.nostdlibs"/> -<option id="gnu.c.link.option.strip.1926939147" name="Omit all symbol information (-s)" superClass="gnu.c.link.option.strip"/> -<option id="gnu.c.link.option.noshared.1390204753" name="No shared libraries (-static)" superClass="gnu.c.link.option.noshared"/> -<option id="gnu.c.link.option.libs.2043660134" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs"> -<listOptionValue builtIn="false" value="winmm"/> -</option> -<option id="gnu.c.link.option.paths.1702926265" name="Library search path (-L)" superClass="gnu.c.link.option.paths"/> -<option id="gnu.c.link.option.ldflags.1184725311" name="Linker flags" superClass="gnu.c.link.option.ldflags" value="-mwindows" valueType="string"/> -<option id="gnu.c.link.option.other.2085141015" name="Other options (-Xlinker [option])" superClass="gnu.c.link.option.other"/> -<option id="gnu.c.link.option.userobjs.1490648701" name="Other objects" superClass="gnu.c.link.option.userobjs"/> -<option id="gnu.c.link.option.soname.437120219" name="Shared object name (-Wl,-soname=)" superClass="gnu.c.link.option.soname" value="PortMidi.dll" valueType="string"/> -<option id="gnu.c.link.option.implname.205634723" name="Import Library name (-Wl,--out-implib=)" superClass="gnu.c.link.option.implname" value="libPortMidi_dll.a" valueType="string"/> -<option id="gnu.c.link.option.defname.571020719" name="DEF file name (-Wl,--output-def=)" superClass="gnu.c.link.option.defname" value="PortMidi_dll.def" valueType="string"/> -<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.916986463" superClass="cdt.managedbuild.tool.gnu.c.linker.input"> -<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> -<additionalInput kind="additionalinput" paths="$(LIBS)"/> -</inputType> -</tool> -<tool id="cdt.managedbuild.tool.gnu.cpp.linker.mingw.so.debug.1822206806" name="MinGW C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.mingw.so.debug"> -<option defaultValue="true" id="gnu.cpp.link.mingw.so.debug.option.shared.408251443" name="Shared (-shared)" superClass="gnu.cpp.link.mingw.so.debug.option.shared" valueType="boolean"/> -</tool> -</toolChain> -</folderInfo> -<sourceEntries> -<entry excluding="pm_cl/|pm_linux/|pm_mac/|pm_test/|porttime/ptlinux.c|porttime/ptmacosx_cf.c|porttime/ptmacosx_mach.c" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> -</sourceEntries> -</configuration> -</storageModule> -<storageModule moduleId="scannerConfiguration"> -<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="makefileGenerator"> -<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.so.release.413200248;cdt.managedbuild.config.gnu.mingw.so.release.413200248.;cdt.managedbuild.tool.gnu.c.compiler.mingw.so.release.343495978;cdt.managedbuild.tool.gnu.c.compiler.input.611335297"> -<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="makefileGenerator"> -<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -</scannerConfigBuildInfo> -<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.so.debug.1580321004;cdt.managedbuild.config.gnu.mingw.so.debug.1580321004.;cdt.managedbuild.tool.gnu.c.compiler.mingw.so.debug.428547337;cdt.managedbuild.tool.gnu.c.compiler.input.532732416"> -<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="makefileGenerator"> -<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -</scannerConfigBuildInfo> -</storageModule> -<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> -<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/> -</cconfiguration> -<cconfiguration id="cdt.managedbuild.config.gnu.mingw.so.release.413200248"> -<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.mingw.so.release.413200248" moduleId="org.eclipse.cdt.core.settings" name="Release"> -<externalSettings> -<externalSetting> -<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/PortMidi"/> -<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/PortMidi/Release"/> -</externalSetting> -</externalSettings> -<extensions> -<extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/> -<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> -<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> -<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> -</extensions> -</storageModule> -<storageModule moduleId="cdtBuildSystem" version="4.0.0"> -<configuration artifactExtension="dll" artifactName="PortMidi" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.mingw.so.release.413200248" name="Release" parent="cdt.managedbuild.config.gnu.mingw.so.release"> -<folderInfo id="cdt.managedbuild.config.gnu.mingw.so.release.413200248." name="/" resourcePath=""> -<toolChain id="cdt.managedbuild.toolchain.gnu.mingw.so.release.965704931" name="MinGW GCC" superClass="cdt.managedbuild.toolchain.gnu.mingw.so.release"> -<targetPlatform id="cdt.managedbuild.target.gnu.platform.mingw.so.release.1343771960" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.mingw.so.release"/> -<builder buildPath="${workspace_loc:/PortMidi/Release}" id="cdt.managedbuild.tool.gnu.builder.mingw.base.1650720234" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="CDT Internal Builder" superClass="cdt.managedbuild.tool.gnu.builder.mingw.base"/> -<tool id="cdt.managedbuild.tool.gnu.assembler.mingw.so.release.1392864745" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.mingw.so.release"> -<option id="gnu.both.asm.option.include.paths.591264871" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath"> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/pm_common}""/> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/pm_win}""/> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/porttime}""/> -</option> -<option id="gnu.both.asm.option.flags.1143807089" superClass="gnu.both.asm.option.flags"/> -<option id="gnu.both.asm.option.warnings.nowarn.1142377463" superClass="gnu.both.asm.option.warnings.nowarn"/> -<option id="gnu.both.asm.option.version.1007025248" superClass="gnu.both.asm.option.version"/> -<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1754592443" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> -</tool> -<tool id="cdt.managedbuild.tool.gnu.archiver.mingw.base.503109969" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.mingw.base"/> -<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.so.release.1693369280" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.so.release"> -<option id="gnu.cpp.compiler.mingw.so.release.option.optimization.level.1169326010" name="Optimization Level" superClass="gnu.cpp.compiler.mingw.so.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/> -<option id="gnu.cpp.compiler.mingw.so.release.option.debugging.level.1197288488" name="Debug Level" superClass="gnu.cpp.compiler.mingw.so.release.option.debugging.level" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> -</tool> -<tool id="cdt.managedbuild.tool.gnu.c.compiler.mingw.so.release.343495978" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.mingw.so.release"> -<option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.mingw.so.release.option.optimization.level.79718900" name="Optimization Level" superClass="gnu.c.compiler.mingw.so.release.option.optimization.level" valueType="enumerated"/> -<option id="gnu.c.compiler.mingw.so.release.option.debugging.level.778378875" name="Debug Level" superClass="gnu.c.compiler.mingw.so.release.option.debugging.level" value="gnu.c.debugging.level.none" valueType="enumerated"/> -<option id="gnu.c.compiler.option.include.paths.140256948" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath"> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/pm_common}""/> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/pm_win}""/> -<listOptionValue builtIn="false" value=""${workspace_loc:/PortMidi/porttime}""/> -</option> -<option id="gnu.c.compiler.option.preprocessor.def.symbols.960115196" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols"/> -<option id="gnu.c.compiler.option.preprocessor.undef.symbol.1891593123" name="Undefined symbols (-U)" superClass="gnu.c.compiler.option.preprocessor.undef.symbol" valueType="undefDefinedSymbols"> -<listOptionValue builtIn="false" value="_STDCALL_SUPPORTED"/> -</option> -<option id="gnu.c.compiler.option.preprocessor.nostdinc.824573539" name="Do not search system directories (-nostdinc)" superClass="gnu.c.compiler.option.preprocessor.nostdinc"/> -<option id="gnu.c.compiler.option.preprocessor.preprocess.2045908914" name="Preprocess only (-E)" superClass="gnu.c.compiler.option.preprocessor.preprocess"/> -<option id="gnu.c.compiler.option.optimization.flags.1668114371" name="Other optimization flags" superClass="gnu.c.compiler.option.optimization.flags"/> -<option id="gnu.c.compiler.option.debugging.other.26702882" name="Other debugging flags" superClass="gnu.c.compiler.option.debugging.other"/> -<option id="gnu.c.compiler.option.debugging.gprof.1849481872" name="Generate gprof information (-pg)" superClass="gnu.c.compiler.option.debugging.gprof"/> -<option id="gnu.c.compiler.option.debugging.prof.370891777" name="Generate prof information (-p)" superClass="gnu.c.compiler.option.debugging.prof"/> -<option id="gnu.c.compiler.option.warnings.syntax.814238128" name="Check syntax only (-fsyntax-only)" superClass="gnu.c.compiler.option.warnings.syntax"/> -<option id="gnu.c.compiler.option.warnings.pedantic.1130364543" name="Pedantic (-pedantic)" superClass="gnu.c.compiler.option.warnings.pedantic"/> -<option id="gnu.c.compiler.option.warnings.pedantic.error.1833423377" name="Pedantic warnings as errors (-pedantic-errors)" superClass="gnu.c.compiler.option.warnings.pedantic.error"/> -<option id="gnu.c.compiler.option.warnings.nowarn.842847161" name="Inhibit all warnings (-w)" superClass="gnu.c.compiler.option.warnings.nowarn"/> -<option id="gnu.c.compiler.option.warnings.allwarn.1245259653" name="All warnings (-Wall)" superClass="gnu.c.compiler.option.warnings.allwarn"/> -<option id="gnu.c.compiler.option.warnings.toerrors.329299856" name="Warnings as errors (-Werror)" superClass="gnu.c.compiler.option.warnings.toerrors"/> -<option id="gnu.c.compiler.option.misc.other.1436833008" name="Other flags" superClass="gnu.c.compiler.option.misc.other"/> -<option id="gnu.c.compiler.option.misc.verbose.1418051288" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose"/> -<option id="gnu.c.compiler.option.misc.ansi.592723919" name="Support ANSI programs (-ansi)" superClass="gnu.c.compiler.option.misc.ansi"/> -<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.611335297" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> -</tool> -<tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.so.release.556134685" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.so.release"> -<option defaultValue="true" id="gnu.c.link.mingw.so.release.option.shared.1619560956" name="Shared (-shared)" superClass="gnu.c.link.mingw.so.release.option.shared" valueType="boolean"/> -<option id="gnu.c.link.option.ldflags.1804407715" name="Linker flags" superClass="gnu.c.link.option.ldflags" value="-mwindows" valueType="string"/> -<option id="gnu.c.link.option.soname.621315524" name="Shared object name (-Wl,-soname=)" superClass="gnu.c.link.option.soname" value="PortMidi.dll" valueType="string"/> -<option id="gnu.c.link.option.implname.236027258" name="Import Library name (-Wl,--out-implib=)" superClass="gnu.c.link.option.implname" value="libPortMidi_dll.a" valueType="string"/> -<option id="gnu.c.link.option.defname.1144978768" name="DEF file name (-Wl,--output-def=)" superClass="gnu.c.link.option.defname" value="PortMidi_dll.def" valueType="string"/> -<option id="gnu.c.link.option.nostart.623404099" name="Do not use standard start files (-nostartfiles)" superClass="gnu.c.link.option.nostart"/> -<option id="gnu.c.link.option.nodeflibs.51119036" name="Do not use default libraries (-nodefaultlibs)" superClass="gnu.c.link.option.nodeflibs"/> -<option id="gnu.c.link.option.nostdlibs.2099774502" name="No startup or default libs (-nostdlib)" superClass="gnu.c.link.option.nostdlibs"/> -<option id="gnu.c.link.option.strip.1270839234" name="Omit all symbol information (-s)" superClass="gnu.c.link.option.strip"/> -<option id="gnu.c.link.option.noshared.715377715" name="No shared libraries (-static)" superClass="gnu.c.link.option.noshared"/> -<option id="gnu.c.link.option.libs.246748928" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs"> -<listOptionValue builtIn="false" value="winmm"/> -</option> -<option id="gnu.c.link.option.paths.1166408208" name="Library search path (-L)" superClass="gnu.c.link.option.paths"/> -<option id="gnu.c.link.option.other.1932058041" name="Other options (-Xlinker [option])" superClass="gnu.c.link.option.other"/> -<option id="gnu.c.link.option.userobjs.1397357824" name="Other objects" superClass="gnu.c.link.option.userobjs"/> -<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.363448189" superClass="cdt.managedbuild.tool.gnu.c.linker.input"> -<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> -<additionalInput kind="additionalinput" paths="$(LIBS)"/> -</inputType> -</tool> -<tool id="cdt.managedbuild.tool.gnu.cpp.linker.mingw.so.release.1088983873" name="MinGW C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.mingw.so.release"> -<option defaultValue="true" id="gnu.cpp.link.mingw.so.release.option.shared.2023092585" name="Shared (-shared)" superClass="gnu.cpp.link.mingw.so.release.option.shared" valueType="boolean"/> -</tool> -</toolChain> -</folderInfo> -<sourceEntries> -<entry excluding="pm_cl/|pm_linux/|pm_mac/|pm_test/|porttime/ptlinux.c|porttime/ptmacosx_cf.c|porttime/ptmacosx_mach.c" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> -</sourceEntries> -</configuration> -</storageModule> -<storageModule moduleId="scannerConfiguration"> -<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="makefileGenerator"> -<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.so.release.413200248;cdt.managedbuild.config.gnu.mingw.so.release.413200248.;cdt.managedbuild.tool.gnu.c.compiler.mingw.so.release.343495978;cdt.managedbuild.tool.gnu.c.compiler.input.611335297"> -<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="makefileGenerator"> -<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -</scannerConfigBuildInfo> -<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.so.debug.1580321004;cdt.managedbuild.config.gnu.mingw.so.debug.1580321004.;cdt.managedbuild.tool.gnu.c.compiler.mingw.so.debug.428547337;cdt.managedbuild.tool.gnu.c.compiler.input.532732416"> -<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="makefileGenerator"> -<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC"> -<buildOutputProvider> -<openAction enabled="true" filePath=""/> -<parser enabled="true"/> -</buildOutputProvider> -<scannerInfoProvider id="specsFile"> -<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> -<parser enabled="true"/> -</scannerInfoProvider> -</profile> -</scannerConfigBuildInfo> -</storageModule> -<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> -<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/> -</cconfiguration> -</storageModule> -<storageModule moduleId="cdtBuildSystem" version="4.0.0"> -<project id="PortMidi.cdt.managedbuild.target.gnu.mingw.so.812075522" name="Shared Library" projectType="cdt.managedbuild.target.gnu.mingw.so"/> -</storageModule> -</cproject> diff --git a/3rdparty/portmidi/pm_mingw/eclipse/dot-project b/3rdparty/portmidi/pm_mingw/eclipse/dot-project deleted file mode 100644 index 57b1a6ab1e0..00000000000 --- a/3rdparty/portmidi/pm_mingw/eclipse/dot-project +++ /dev/null @@ -1,69 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>PortMidi</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> - <triggers>clean,full,incremental,</triggers> - <arguments> - <dictionary> - <key>org.eclipse.cdt.make.core.contents</key> - <value>org.eclipse.cdt.make.core.activeConfigSettings</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.buildLocation</key> - <value>${workspace_loc:/PortMidi/Debug}</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key> - <value>true</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.enableCleanBuild</key> - <value>true</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.enableFullBuild</key> - <value>true</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.enableAutoBuild</key> - <value>false</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.append_environment</key> - <value>true</value> - </dictionary> - <dictionary> - <key>?name?</key> - <value></value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.stopOnError</key> - <value>true</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.buildArguments</key> - <value></value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.buildCommand</key> - <value>make</value> - </dictionary> - </arguments> - </buildCommand> - <buildCommand> - <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> - <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> - <nature>org.eclipse.cdt.core.cnature</nature> - </natures> -</projectDescription> diff --git a/3rdparty/portmidi/pm_mingw/msys/README-MSYS.txt b/3rdparty/portmidi/pm_mingw/msys/README-MSYS.txt deleted file mode 100644 index 6f3cd69daa7..00000000000 --- a/3rdparty/portmidi/pm_mingw/msys/README-MSYS.txt +++ /dev/null @@ -1,8 +0,0 @@ -Old code was removed from this directory because CMake provides an -up-to-date way to use MinGW. See portmidi/pm_mingw/README-MINGW.txt. - -Roger Dannenberg -20-Sep-2010 - - - diff --git a/3rdparty/portmidi/pm_python/README_PYTHON.txt b/3rdparty/portmidi/pm_python/README_PYTHON.txt deleted file mode 100644 index b592869f3b9..00000000000 --- a/3rdparty/portmidi/pm_python/README_PYTHON.txt +++ /dev/null @@ -1,34 +0,0 @@ -PyPortMidi v0.03 03/15/05 -Python wrappings for PortMidi -John Harrison -harrison@media.mit.edu - -Modified by Roger B. Dannenberg, Nov 2009 - -PyPortMidi ----------- - -PyPortMidi is a Python wrapper for PortMidi. PortMidi is a cross-platform -C library for realtime MIDI control. Using PyPortMidi, you can send and -receive MIDI data in realtime from Python. - -Besides using PyPortMidi to communicate to synthesizers and the -like, it is possible to use PyPortMidi as a way to send MIDI messages -between software packages on the same computer. For example, Using -PyPortMidi and MIDI-YOKE on a Windows machine, it is possible to send -realtime MIDI messages between programs on the same computer using -loopback virtual MIDI ports. (At this time, MIDI-YOKE does not appear -to run on Windows Vista.) - -PyPortMidi is cross-platform, but it will require some small -changes in the setup.py file for it to install correctly on Linux -machines. The changes should be pretty straightforward, and I am -anxious to work with a Linux user on the port. - -PyPortMidi works with Python 2.6 and Python 3.1, although the ports -are mostly separate because of various language incompatibilities. - -Please see README26.txt for information about the Python 2.6 version. - -See README31.txt for information about the Python 3.1 version. - diff --git a/3rdparty/portmidi/pm_python/pyportmidi/__init__.py b/3rdparty/portmidi/pm_python/pyportmidi/__init__.py deleted file mode 100644 index 0f3fc4b44cd..00000000000 --- a/3rdparty/portmidi/pm_python/pyportmidi/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ - -from .midi import * - diff --git a/3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.c b/3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.c deleted file mode 100644 index 7d700349e18..00000000000 --- a/3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.c +++ /dev/null @@ -1,5663 +0,0 @@ -/* Generated by Cython 0.12.1 on Sun Sep 26 13:30:09 2010 */ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "structmember.h" -#ifndef Py_PYTHON_H - #error Python headers needed to compile C extensions, please install development version of Python. -#else - -#ifndef PY_LONG_LONG - #define PY_LONG_LONG LONG_LONG -#endif -#ifndef DL_EXPORT - #define DL_EXPORT(t) t -#endif -#if PY_VERSION_HEX < 0x02040000 - #define METH_COEXIST 0 - #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type) - #define PyDict_Contains(d,o) PySequence_Contains(d,o) -#endif - -#if PY_VERSION_HEX < 0x02050000 - typedef int Py_ssize_t; - #define PY_SSIZE_T_MAX INT_MAX - #define PY_SSIZE_T_MIN INT_MIN - #define PY_FORMAT_SIZE_T "" - #define PyInt_FromSsize_t(z) PyInt_FromLong(z) - #define PyInt_AsSsize_t(o) PyInt_AsLong(o) - #define PyNumber_Index(o) PyNumber_Int(o) - #define PyIndex_Check(o) PyNumber_Check(o) - #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message) -#endif - -#if PY_VERSION_HEX < 0x02060000 - #define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) - #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) - #define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) - #define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, - #define PyType_Modified(t) - - typedef struct { - void *buf; - PyObject *obj; - Py_ssize_t len; - Py_ssize_t itemsize; - int readonly; - int ndim; - char *format; - Py_ssize_t *shape; - Py_ssize_t *strides; - Py_ssize_t *suboffsets; - void *internal; - } Py_buffer; - - #define PyBUF_SIMPLE 0 - #define PyBUF_WRITABLE 0x0001 - #define PyBUF_FORMAT 0x0004 - #define PyBUF_ND 0x0008 - #define PyBUF_STRIDES (0x0010 | PyBUF_ND) - #define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) - #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) - #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) - #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) - -#endif - -#if PY_MAJOR_VERSION < 3 - #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" -#else - #define __Pyx_BUILTIN_MODULE_NAME "builtins" -#endif - -#if PY_MAJOR_VERSION >= 3 - #define Py_TPFLAGS_CHECKTYPES 0 - #define Py_TPFLAGS_HAVE_INDEX 0 -#endif - -#if (PY_VERSION_HEX < 0x02060000) || (PY_MAJOR_VERSION >= 3) - #define Py_TPFLAGS_HAVE_NEWBUFFER 0 -#endif - -#if PY_MAJOR_VERSION >= 3 - #define PyBaseString_Type PyUnicode_Type - #define PyString_Type PyUnicode_Type - #define PyString_CheckExact PyUnicode_CheckExact -#else - #define PyBytes_Type PyString_Type - #define PyBytes_CheckExact PyString_CheckExact -#endif - -#if PY_MAJOR_VERSION >= 3 - #define PyInt_Type PyLong_Type - #define PyInt_Check(op) PyLong_Check(op) - #define PyInt_CheckExact(op) PyLong_CheckExact(op) - #define PyInt_FromString PyLong_FromString - #define PyInt_FromUnicode PyLong_FromUnicode - #define PyInt_FromLong PyLong_FromLong - #define PyInt_FromSize_t PyLong_FromSize_t - #define PyInt_FromSsize_t PyLong_FromSsize_t - #define PyInt_AsLong PyLong_AsLong - #define PyInt_AS_LONG PyLong_AS_LONG - #define PyInt_AsSsize_t PyLong_AsSsize_t - #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask - #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask - #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) -#else - #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) - -#endif - -#if PY_MAJOR_VERSION >= 3 - #define PyMethod_New(func, self, klass) PyInstanceMethod_New(func) -#endif - -#if !defined(WIN32) && !defined(MS_WINDOWS) - #ifndef __stdcall - #define __stdcall - #endif - #ifndef __cdecl - #define __cdecl - #endif - #ifndef __fastcall - #define __fastcall - #endif -#else - #define _USE_MATH_DEFINES -#endif - -#if PY_VERSION_HEX < 0x02050000 - #define __Pyx_GetAttrString(o,n) PyObject_GetAttrString((o),((char *)(n))) - #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),((char *)(n)),(a)) - #define __Pyx_DelAttrString(o,n) PyObject_DelAttrString((o),((char *)(n))) -#else - #define __Pyx_GetAttrString(o,n) PyObject_GetAttrString((o),(n)) - #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),(n),(a)) - #define __Pyx_DelAttrString(o,n) PyObject_DelAttrString((o),(n)) -#endif - -#if PY_VERSION_HEX < 0x02050000 - #define __Pyx_NAMESTR(n) ((char *)(n)) - #define __Pyx_DOCSTR(n) ((char *)(n)) -#else - #define __Pyx_NAMESTR(n) (n) - #define __Pyx_DOCSTR(n) (n) -#endif -#ifdef __cplusplus -#define __PYX_EXTERN_C extern "C" -#else -#define __PYX_EXTERN_C extern -#endif -#include <math.h> -#define __PYX_HAVE_API___pyportmidi -#include "portmidi.h" -#include "porttime.h" - -#ifndef CYTHON_INLINE - #if defined(__GNUC__) - #define CYTHON_INLINE __inline__ - #elif defined(_MSC_VER) - #define CYTHON_INLINE __inline - #else - #define CYTHON_INLINE - #endif -#endif - -typedef struct {PyObject **p; char *s; const long n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/ - - -/* Type Conversion Predeclarations */ - -#if PY_MAJOR_VERSION < 3 -#define __Pyx_PyBytes_FromString PyString_FromString -#define __Pyx_PyBytes_FromStringAndSize PyString_FromStringAndSize -#define __Pyx_PyBytes_AsString PyString_AsString -#else -#define __Pyx_PyBytes_FromString PyBytes_FromString -#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize -#define __Pyx_PyBytes_AsString PyBytes_AsString -#endif - -#define __Pyx_PyBytes_FromUString(s) __Pyx_PyBytes_FromString((char*)s) -#define __Pyx_PyBytes_AsUString(s) ((unsigned char*) __Pyx_PyBytes_AsString(s)) - -#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False)) -static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); -static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); - -#if !defined(T_PYSSIZET) -#if PY_VERSION_HEX < 0x02050000 -#define T_PYSSIZET T_INT -#elif !defined(T_LONGLONG) -#define T_PYSSIZET \ - ((sizeof(Py_ssize_t) == sizeof(int)) ? T_INT : \ - ((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : -1)) -#else -#define T_PYSSIZET \ - ((sizeof(Py_ssize_t) == sizeof(int)) ? T_INT : \ - ((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : \ - ((sizeof(Py_ssize_t) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1))) -#endif -#endif - - -#if !defined(T_ULONGLONG) -#define __Pyx_T_UNSIGNED_INT(x) \ - ((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \ - ((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \ - ((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \ - ((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : -1)))) -#else -#define __Pyx_T_UNSIGNED_INT(x) \ - ((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \ - ((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \ - ((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \ - ((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : \ - ((sizeof(x) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1))))) -#endif -#if !defined(T_LONGLONG) -#define __Pyx_T_SIGNED_INT(x) \ - ((sizeof(x) == sizeof(char)) ? T_BYTE : \ - ((sizeof(x) == sizeof(short)) ? T_SHORT : \ - ((sizeof(x) == sizeof(int)) ? T_INT : \ - ((sizeof(x) == sizeof(long)) ? T_LONG : -1)))) -#else -#define __Pyx_T_SIGNED_INT(x) \ - ((sizeof(x) == sizeof(char)) ? T_BYTE : \ - ((sizeof(x) == sizeof(short)) ? T_SHORT : \ - ((sizeof(x) == sizeof(int)) ? T_INT : \ - ((sizeof(x) == sizeof(long)) ? T_LONG : \ - ((sizeof(x) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1))))) -#endif - -#define __Pyx_T_FLOATING(x) \ - ((sizeof(x) == sizeof(float)) ? T_FLOAT : \ - ((sizeof(x) == sizeof(double)) ? T_DOUBLE : -1)) - -#if !defined(T_SIZET) -#if !defined(T_ULONGLONG) -#define T_SIZET \ - ((sizeof(size_t) == sizeof(unsigned int)) ? T_UINT : \ - ((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : -1)) -#else -#define T_SIZET \ - ((sizeof(size_t) == sizeof(unsigned int)) ? T_UINT : \ - ((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : \ - ((sizeof(size_t) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1))) -#endif -#endif - -static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); -static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*); - -#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) - - -#ifdef __GNUC__ -/* Test for GCC > 2.95 */ -#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#else /* __GNUC__ > 2 ... */ -#define likely(x) (x) -#define unlikely(x) (x) -#endif /* __GNUC__ > 2 ... */ -#else /* __GNUC__ */ -#define likely(x) (x) -#define unlikely(x) (x) -#endif /* __GNUC__ */ - -static PyObject *__pyx_m; -static PyObject *__pyx_b; -static PyObject *__pyx_empty_tuple; -static PyObject *__pyx_empty_bytes; -static int __pyx_lineno; -static int __pyx_clineno = 0; -static const char * __pyx_cfilenm= __FILE__; -static const char *__pyx_filename; -static const char **__pyx_f; - - -/* Type declarations */ - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":394 - * - * - * cdef class Input: # <<<<<<<<<<<<<< - * """ - * class Input: - */ - -struct __pyx_obj_11_pyportmidi_Input { - PyObject_HEAD - PmStream *midi; - int debug; - int i; -}; - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":201 - * return Pm_Channel(chan-1) - * - * cdef class Output: # <<<<<<<<<<<<<< - * """ - * class Output: - */ - -struct __pyx_obj_11_pyportmidi_Output { - PyObject_HEAD - int i; - PmStream *midi; - int debug; - int _aborted; -}; - -#ifndef CYTHON_REFNANNY - #define CYTHON_REFNANNY 0 -#endif - -#if CYTHON_REFNANNY - typedef struct { - void (*INCREF)(void*, PyObject*, int); - void (*DECREF)(void*, PyObject*, int); - void (*GOTREF)(void*, PyObject*, int); - void (*GIVEREF)(void*, PyObject*, int); - void* (*SetupContext)(const char*, int, const char*); - void (*FinishContext)(void**); - } __Pyx_RefNannyAPIStruct; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; - static __Pyx_RefNannyAPIStruct * __Pyx_RefNannyImportAPI(const char *modname) { - PyObject *m = NULL, *p = NULL; - void *r = NULL; - m = PyImport_ImportModule((char *)modname); - if (!m) goto end; - p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); - if (!p) goto end; - r = PyLong_AsVoidPtr(p); - end: - Py_XDECREF(p); - Py_XDECREF(m); - return (__Pyx_RefNannyAPIStruct *)r; - } - #define __Pyx_RefNannySetupContext(name) void *__pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) - #define __Pyx_RefNannyFinishContext() __Pyx_RefNanny->FinishContext(&__pyx_refnanny) - #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r);} } while(0) -#else - #define __Pyx_RefNannySetupContext(name) - #define __Pyx_RefNannyFinishContext() - #define __Pyx_INCREF(r) Py_INCREF(r) - #define __Pyx_DECREF(r) Py_DECREF(r) - #define __Pyx_GOTREF(r) - #define __Pyx_GIVEREF(r) - #define __Pyx_XDECREF(r) Py_XDECREF(r) -#endif /* CYTHON_REFNANNY */ -#define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);} } while(0) -#define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r);} } while(0) - -static void __Pyx_RaiseDoubleKeywordsError( - const char* func_name, PyObject* kw_name); /*proto*/ - -static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, - Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/ - -static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name); /*proto*/ - - -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { - PyObject *r; - if (!j) return NULL; - r = PyObject_GetItem(o, j); - Py_DECREF(j); - return r; -} - - -#define __Pyx_GetItemInt_List(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \ - __Pyx_GetItemInt_List_Fast(o, i, size <= sizeof(long)) : \ - __Pyx_GetItemInt_Generic(o, to_py_func(i))) - -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, int fits_long) { - if (likely(o != Py_None)) { - if (likely((0 <= i) & (i < PyList_GET_SIZE(o)))) { - PyObject *r = PyList_GET_ITEM(o, i); - Py_INCREF(r); - return r; - } - else if ((-PyList_GET_SIZE(o) <= i) & (i < 0)) { - PyObject *r = PyList_GET_ITEM(o, PyList_GET_SIZE(o) + i); - Py_INCREF(r); - return r; - } - } - return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i)); -} - -#define __Pyx_GetItemInt_Tuple(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \ - __Pyx_GetItemInt_Tuple_Fast(o, i, size <= sizeof(long)) : \ - __Pyx_GetItemInt_Generic(o, to_py_func(i))) - -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, int fits_long) { - if (likely(o != Py_None)) { - if (likely((0 <= i) & (i < PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, i); - Py_INCREF(r); - return r; - } - else if ((-PyTuple_GET_SIZE(o) <= i) & (i < 0)) { - PyObject *r = PyTuple_GET_ITEM(o, PyTuple_GET_SIZE(o) + i); - Py_INCREF(r); - return r; - } - } - return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i)); -} - - -#define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \ - __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \ - __Pyx_GetItemInt_Generic(o, to_py_func(i))) - -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) { - PyObject *r; - if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) { - r = PyList_GET_ITEM(o, i); - Py_INCREF(r); - } - else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) { - r = PyTuple_GET_ITEM(o, i); - Py_INCREF(r); - } - else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) { - r = PySequence_GetItem(o, i); - } - else { - r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i)); - } - return r; -} - -static CYTHON_INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) { - if (likely(PyList_CheckExact(L))) { - if (PyList_Append(L, x) < 0) return NULL; - Py_INCREF(Py_None); - return Py_None; /* this is just to have an accurate signature */ - } - else { - PyObject *r, *m; - m = __Pyx_GetAttrString(L, "append"); - if (!m) return NULL; - r = PyObject_CallFunctionObjArgs(m, x, NULL); - Py_DECREF(m); - return r; - } -} - -static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/ - -static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_PmDeviceID(PmDeviceID); - -static CYTHON_INLINE PmDeviceID __Pyx_PyInt_from_py_PmDeviceID(PyObject *); - -static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_PtTimestamp(PtTimestamp); - -static int __Pyx_Print(PyObject *, int); /*proto*/ -#if PY_MAJOR_VERSION >= 3 -static PyObject* __pyx_print = 0; -static PyObject* __pyx_print_kwargs = 0; -#endif - -static int __Pyx_PrintOne(PyObject *o); /*proto*/ - -static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/ - -static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ -static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ - -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ - -static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_PmMessage(PmMessage); - -static CYTHON_INLINE PmMessage __Pyx_PyInt_from_py_PmMessage(PyObject *); - -static CYTHON_INLINE PmTimestamp __Pyx_PyInt_from_py_PmTimestamp(PyObject *); - -static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_PmTimestamp(PmTimestamp); - -static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject *); - -static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject *); - -static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject *); - -static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject *); - -static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject *); - -static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject *); - -static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject *); - -static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject *); - -static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject *); - -static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject *); - -static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject *); - -static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject *); - -static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject *); - -static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject *); - -static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *); - -static void __Pyx_AddTraceback(const char *funcname); /*proto*/ - -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ -/* Module declarations from _pyportmidi */ - -static PyTypeObject *__pyx_ptype_11_pyportmidi_Output = 0; -static PyTypeObject *__pyx_ptype_11_pyportmidi_Input = 0; -#define __Pyx_MODULE_NAME "_pyportmidi" -int __pyx_module_is_main__pyportmidi = 0; - -/* Implementation of _pyportmidi */ -static PyObject *__pyx_builtin_Exception; -static PyObject *__pyx_builtin_IndexError; -static PyObject *__pyx_builtin_range; -static char __pyx_k_1[] = "Opening Midi Output"; -static char __pyx_k_2[] = "Unable to open Midi OutputDevice="; -static char __pyx_k_3[] = " err="; -static char __pyx_k_4[] = "Closing MIDI output stream and destroying instance"; -static char __pyx_k_5[] = "midi Output not open."; -static char __pyx_k_6[] = "midi Output aborted. Need to call Close after Abort."; -static char __pyx_k_7[] = "maximum list length is 1024"; -static char __pyx_k_8[] = " arguments in event list"; -static char __pyx_k_9[] = " : "; -static char __pyx_k_10[] = "writing to midi buffer"; -static char __pyx_k_11[] = "Writing to MIDI buffer"; -static char __pyx_k_12[] = "MIDI input opened."; -static char __pyx_k_13[] = "Closing MIDI input stream and destroying instance"; -static char __pyx_k_14[] = "midi Input not open."; -static char __pyx_k_15[] = "maximum buffer length is 1024"; -static char __pyx_k_16[] = "minimum buffer length is 1"; -static char __pyx_k_17[] = "0.07"; -static char __pyx_k_18[] = "FILT_CHANNEL_AFTERTOUCH"; -static char __pyx_k_19[] = "FILT_POLY_AFTERTOUCH"; -static char __pyx_k_20[] = "Initialize (line 132)"; -static char __pyx_k_21[] = "Terminate (line 139)"; -static char __pyx_k_22[] = "GetDeviceInfo (line 156)"; -static char __pyx_k_23[] = "Time (line 173)"; -static char __pyx_k_24[] = "GetErrorText (line 180)"; -static char __pyx_k_25[] = "Channel (line 187)"; -static char __pyx_k_26[] = "Output._check_open (line 248)"; -static char __pyx_k_27[] = "Output.Close (line 258)"; -static char __pyx_k_28[] = "Output.Abort (line 274)"; -static char __pyx_k_29[] = "Output.Write (line 293)"; -static char __pyx_k_30[] = "Output.WriteShort (line 333)"; -static char __pyx_k_31[] = "Output.WriteSysEx (line 356)"; -static char __pyx_k_32[] = "Input._check_open (line 422)"; -static char __pyx_k_33[] = "Input.Close (line 430)"; -static char __pyx_k_34[] = "Input.SetFilter (line 447)"; -static char __pyx_k_35[] = "Input.SetChannelMask (line 481)"; -static char __pyx_k_36[] = "Input.Poll (line 502)"; -static char __pyx_k_37[] = "Input.Read (line 514)"; -static char __pyx_k__B[] = "B"; -static char __pyx_k__i[] = "i"; -static char __pyx_k__msg[] = "msg"; -static char __pyx_k__Poll[] = "Poll"; -static char __pyx_k__Read[] = "Read"; -static char __pyx_k__TRUE[] = "TRUE"; -static char __pyx_k__Time[] = "Time"; -static char __pyx_k__midi[] = "midi"; -static char __pyx_k__name[] = "name"; -static char __pyx_k__when[] = "when"; -static char __pyx_k__Abort[] = "Abort"; -static char __pyx_k__Close[] = "Close"; -static char __pyx_k__FALSE[] = "FALSE"; -static char __pyx_k__Input[] = "Input"; -static char __pyx_k__Write[] = "Write"; -static char __pyx_k__array[] = "array"; -static char __pyx_k__data1[] = "data1"; -static char __pyx_k__data2[] = "data2"; -static char __pyx_k__debug[] = "debug"; -static char __pyx_k__input[] = "input"; -static char __pyx_k__range[] = "range"; -static char __pyx_k__Output[] = "Output"; -static char __pyx_k__interf[] = "interf"; -static char __pyx_k__opened[] = "opened"; -static char __pyx_k__output[] = "output"; -static char __pyx_k__status[] = "status"; -static char __pyx_k__Channel[] = "Channel"; -static char __pyx_k__FILT_F9[] = "FILT_F9"; -static char __pyx_k__FILT_FD[] = "FILT_FD"; -static char __pyx_k__latency[] = "latency"; -static char __pyx_k__message[] = "message"; -static char __pyx_k__FILT_MTC[] = "FILT_MTC"; -static char __pyx_k____main__[] = "__main__"; -static char __pyx_k____test__[] = "__test__"; -static char __pyx_k___aborted[] = "_aborted"; -static char __pyx_k__tostring[] = "tostring"; -static char __pyx_k__Exception[] = "Exception"; -static char __pyx_k__FILT_NOTE[] = "FILT_NOTE"; -static char __pyx_k__FILT_PLAY[] = "FILT_PLAY"; -static char __pyx_k__FILT_TICK[] = "FILT_TICK"; -static char __pyx_k__FILT_TUNE[] = "FILT_TUNE"; -static char __pyx_k__SetFilter[] = "SetFilter"; -static char __pyx_k__Terminate[] = "Terminate"; -static char __pyx_k__timestamp[] = "timestamp"; -static char __pyx_k__FILT_CLOCK[] = "FILT_CLOCK"; -static char __pyx_k__FILT_RESET[] = "FILT_RESET"; -static char __pyx_k__FILT_SYSEX[] = "FILT_SYSEX"; -static char __pyx_k__IndexError[] = "IndexError"; -static char __pyx_k__Initialize[] = "Initialize"; -static char __pyx_k__WriteShort[] = "WriteShort"; -static char __pyx_k__WriteSysEx[] = "WriteSysEx"; -static char __pyx_k__buffersize[] = "buffersize"; -static char __pyx_k__FILT_ACTIVE[] = "FILT_ACTIVE"; -static char __pyx_k__InputDevice[] = "InputDevice"; -static char __pyx_k____version__[] = "__version__"; -static char __pyx_k___check_open[] = "_check_open"; -static char __pyx_k__FILT_CONTROL[] = "FILT_CONTROL"; -static char __pyx_k__FILT_PROGRAM[] = "FILT_PROGRAM"; -static char __pyx_k__GetErrorText[] = "GetErrorText"; -static char __pyx_k__OutputDevice[] = "OutputDevice"; -static char __pyx_k__FILT_REALTIME[] = "FILT_REALTIME"; -static char __pyx_k__GetDeviceInfo[] = "GetDeviceInfo"; -static char __pyx_k__FILT_PITCHBEND[] = "FILT_PITCHBEND"; -static char __pyx_k__FILT_UNDEFINED[] = "FILT_UNDEFINED"; -static char __pyx_k__SetChannelMask[] = "SetChannelMask"; -static char __pyx_k__FILT_AFTERTOUCH[] = "FILT_AFTERTOUCH"; -static char __pyx_k__FILT_SONG_SELECT[] = "FILT_SONG_SELECT"; -static char __pyx_k__FILT_SONG_POSITION[] = "FILT_SONG_POSITION"; -static PyObject *__pyx_kp_s_1; -static PyObject *__pyx_kp_s_10; -static PyObject *__pyx_kp_s_11; -static PyObject *__pyx_kp_s_12; -static PyObject *__pyx_kp_s_13; -static PyObject *__pyx_kp_s_14; -static PyObject *__pyx_kp_s_15; -static PyObject *__pyx_kp_s_16; -static PyObject *__pyx_kp_s_17; -static PyObject *__pyx_n_s_18; -static PyObject *__pyx_n_s_19; -static PyObject *__pyx_kp_s_2; -static PyObject *__pyx_kp_u_20; -static PyObject *__pyx_kp_u_21; -static PyObject *__pyx_kp_u_22; -static PyObject *__pyx_kp_u_23; -static PyObject *__pyx_kp_u_24; -static PyObject *__pyx_kp_u_25; -static PyObject *__pyx_kp_u_26; -static PyObject *__pyx_kp_u_27; -static PyObject *__pyx_kp_u_28; -static PyObject *__pyx_kp_u_29; -static PyObject *__pyx_kp_s_3; -static PyObject *__pyx_kp_u_30; -static PyObject *__pyx_kp_u_31; -static PyObject *__pyx_kp_u_32; -static PyObject *__pyx_kp_u_33; -static PyObject *__pyx_kp_u_34; -static PyObject *__pyx_kp_u_35; -static PyObject *__pyx_kp_u_36; -static PyObject *__pyx_kp_u_37; -static PyObject *__pyx_kp_s_4; -static PyObject *__pyx_kp_s_5; -static PyObject *__pyx_kp_s_6; -static PyObject *__pyx_kp_s_7; -static PyObject *__pyx_kp_s_8; -static PyObject *__pyx_kp_s_9; -static PyObject *__pyx_n_s__Abort; -static PyObject *__pyx_n_s__B; -static PyObject *__pyx_n_s__Channel; -static PyObject *__pyx_n_s__Close; -static PyObject *__pyx_n_s__Exception; -static PyObject *__pyx_n_s__FALSE; -static PyObject *__pyx_n_s__FILT_ACTIVE; -static PyObject *__pyx_n_s__FILT_AFTERTOUCH; -static PyObject *__pyx_n_s__FILT_CLOCK; -static PyObject *__pyx_n_s__FILT_CONTROL; -static PyObject *__pyx_n_s__FILT_F9; -static PyObject *__pyx_n_s__FILT_FD; -static PyObject *__pyx_n_s__FILT_MTC; -static PyObject *__pyx_n_s__FILT_NOTE; -static PyObject *__pyx_n_s__FILT_PITCHBEND; -static PyObject *__pyx_n_s__FILT_PLAY; -static PyObject *__pyx_n_s__FILT_PROGRAM; -static PyObject *__pyx_n_s__FILT_REALTIME; -static PyObject *__pyx_n_s__FILT_RESET; -static PyObject *__pyx_n_s__FILT_SONG_POSITION; -static PyObject *__pyx_n_s__FILT_SONG_SELECT; -static PyObject *__pyx_n_s__FILT_SYSEX; -static PyObject *__pyx_n_s__FILT_TICK; -static PyObject *__pyx_n_s__FILT_TUNE; -static PyObject *__pyx_n_s__FILT_UNDEFINED; -static PyObject *__pyx_n_s__GetDeviceInfo; -static PyObject *__pyx_n_s__GetErrorText; -static PyObject *__pyx_n_s__IndexError; -static PyObject *__pyx_n_s__Initialize; -static PyObject *__pyx_n_s__Input; -static PyObject *__pyx_n_s__InputDevice; -static PyObject *__pyx_n_s__Output; -static PyObject *__pyx_n_s__OutputDevice; -static PyObject *__pyx_n_s__Poll; -static PyObject *__pyx_n_s__Read; -static PyObject *__pyx_n_s__SetChannelMask; -static PyObject *__pyx_n_s__SetFilter; -static PyObject *__pyx_n_s__TRUE; -static PyObject *__pyx_n_s__Terminate; -static PyObject *__pyx_n_s__Time; -static PyObject *__pyx_n_s__Write; -static PyObject *__pyx_n_s__WriteShort; -static PyObject *__pyx_n_s__WriteSysEx; -static PyObject *__pyx_n_s____main__; -static PyObject *__pyx_n_s____test__; -static PyObject *__pyx_n_s____version__; -static PyObject *__pyx_n_s___aborted; -static PyObject *__pyx_n_s___check_open; -static PyObject *__pyx_n_s__array; -static PyObject *__pyx_n_s__buffersize; -static PyObject *__pyx_n_s__data1; -static PyObject *__pyx_n_s__data2; -static PyObject *__pyx_n_s__debug; -static PyObject *__pyx_n_s__i; -static PyObject *__pyx_n_s__input; -static PyObject *__pyx_n_s__interf; -static PyObject *__pyx_n_s__latency; -static PyObject *__pyx_n_s__message; -static PyObject *__pyx_n_s__midi; -static PyObject *__pyx_n_s__msg; -static PyObject *__pyx_n_s__name; -static PyObject *__pyx_n_s__opened; -static PyObject *__pyx_n_s__output; -static PyObject *__pyx_n_s__range; -static PyObject *__pyx_n_s__status; -static PyObject *__pyx_n_s__timestamp; -static PyObject *__pyx_n_s__tostring; -static PyObject *__pyx_n_s__when; -static PyObject *__pyx_int_0; -static PyObject *__pyx_int_1; -static PyObject *__pyx_int_8; -static PyObject *__pyx_int_16; -static PyObject *__pyx_int_0x1; -static PyObject *__pyx_int_0x2; -static PyObject *__pyx_int_0x4; -static PyObject *__pyx_int_0x8; -static PyObject *__pyx_int_0x10; -static PyObject *__pyx_int_0x20; -static PyObject *__pyx_int_0x30; -static PyObject *__pyx_int_0x40; -static PyObject *__pyx_int_0x7F; -static PyObject *__pyx_int_0x80; -static PyObject *__pyx_int_0xFF; -static PyObject *__pyx_int_1024; -static PyObject *__pyx_int_4096; -static PyObject *__pyx_int_0x100; -static PyObject *__pyx_int_0x200; -static PyObject *__pyx_int_0x300; -static PyObject *__pyx_int_0x400; -static PyObject *__pyx_int_0x800; -static PyObject *__pyx_int_0x1000; -static PyObject *__pyx_int_0x2000; -static PyObject *__pyx_int_0x4000; -static PyObject *__pyx_int_0x8000; -static PyObject *__pyx_int_0xFF00; -static PyObject *__pyx_int_0x10000; -static PyObject *__pyx_int_0xFF0000; - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":132 - * TRUE=1 - * - * def Initialize(): # <<<<<<<<<<<<<< - * """ - * Initialize: call this first - */ - -static PyObject *__pyx_pf_11_pyportmidi_Initialize(PyObject *__pyx_self, PyObject *unused); /*proto*/ -static char __pyx_doc_11_pyportmidi_Initialize[] = "\nInitialize: call this first\n "; -static PyObject *__pyx_pf_11_pyportmidi_Initialize(PyObject *__pyx_self, PyObject *unused) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannySetupContext("Initialize"); - __pyx_self = __pyx_self; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":136 - * Initialize: call this first - * """ - * Pm_Initialize() # <<<<<<<<<<<<<< - * Pt_Start(1, NULL, NULL) # /[inserted by cython to avoid comment start]* equiv to TIME_START: start timer w/ ms accuracy *[inserted by cython to avoid comment closer]/ - * - */ - Pm_Initialize(); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":137 - * """ - * Pm_Initialize() - * Pt_Start(1, NULL, NULL) # /[inserted by cython to avoid comment start]* equiv to TIME_START: start timer w/ ms accuracy *[inserted by cython to avoid comment closer]/ # <<<<<<<<<<<<<< - * - * def Terminate(): - */ - Pt_Start(1, NULL, NULL); - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":139 - * Pt_Start(1, NULL, NULL) # /[inserted by cython to avoid comment start]* equiv to TIME_START: start timer w/ ms accuracy *[inserted by cython to avoid comment closer]/ - * - * def Terminate(): # <<<<<<<<<<<<<< - * """ - * Terminate: call this to clean up Midi streams when done. - */ - -static PyObject *__pyx_pf_11_pyportmidi_Terminate(PyObject *__pyx_self, PyObject *unused); /*proto*/ -static char __pyx_doc_11_pyportmidi_Terminate[] = "\nTerminate: call this to clean up Midi streams when done.\nIf you do not call this on Windows machines when you are\ndone with MIDI, your system may crash.\n "; -static PyObject *__pyx_pf_11_pyportmidi_Terminate(PyObject *__pyx_self, PyObject *unused) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannySetupContext("Terminate"); - __pyx_self = __pyx_self; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":145 - * done with MIDI, your system may crash. - * """ - * Pm_Terminate() # <<<<<<<<<<<<<< - * - * def GetDefaultInputDeviceID(): - */ - Pm_Terminate(); - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":147 - * Pm_Terminate() - * - * def GetDefaultInputDeviceID(): # <<<<<<<<<<<<<< - * return Pm_GetDefaultInputDeviceID() - * - */ - -static PyObject *__pyx_pf_11_pyportmidi_GetDefaultInputDeviceID(PyObject *__pyx_self, PyObject *unused); /*proto*/ -static PyObject *__pyx_pf_11_pyportmidi_GetDefaultInputDeviceID(PyObject *__pyx_self, PyObject *unused) { - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - __Pyx_RefNannySetupContext("GetDefaultInputDeviceID"); - __pyx_self = __pyx_self; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":148 - * - * def GetDefaultInputDeviceID(): - * return Pm_GetDefaultInputDeviceID() # <<<<<<<<<<<<<< - * - * def GetDefaultOutputDeviceID(): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyInt_to_py_PmDeviceID(Pm_GetDefaultInputDeviceID()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("_pyportmidi.GetDefaultInputDeviceID"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":150 - * return Pm_GetDefaultInputDeviceID() - * - * def GetDefaultOutputDeviceID(): # <<<<<<<<<<<<<< - * return Pm_GetDefaultOutputDeviceID() - * - */ - -static PyObject *__pyx_pf_11_pyportmidi_GetDefaultOutputDeviceID(PyObject *__pyx_self, PyObject *unused); /*proto*/ -static PyObject *__pyx_pf_11_pyportmidi_GetDefaultOutputDeviceID(PyObject *__pyx_self, PyObject *unused) { - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - __Pyx_RefNannySetupContext("GetDefaultOutputDeviceID"); - __pyx_self = __pyx_self; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":151 - * - * def GetDefaultOutputDeviceID(): - * return Pm_GetDefaultOutputDeviceID() # <<<<<<<<<<<<<< - * - * def CountDevices(): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyInt_to_py_PmDeviceID(Pm_GetDefaultOutputDeviceID()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("_pyportmidi.GetDefaultOutputDeviceID"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":153 - * return Pm_GetDefaultOutputDeviceID() - * - * def CountDevices(): # <<<<<<<<<<<<<< - * return Pm_CountDevices() - * - */ - -static PyObject *__pyx_pf_11_pyportmidi_CountDevices(PyObject *__pyx_self, PyObject *unused); /*proto*/ -static PyObject *__pyx_pf_11_pyportmidi_CountDevices(PyObject *__pyx_self, PyObject *unused) { - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - __Pyx_RefNannySetupContext("CountDevices"); - __pyx_self = __pyx_self; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":154 - * - * def CountDevices(): - * return Pm_CountDevices() # <<<<<<<<<<<<<< - * - * def GetDeviceInfo(i): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyInt_FromLong(Pm_CountDevices()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("_pyportmidi.CountDevices"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":156 - * return Pm_CountDevices() - * - * def GetDeviceInfo(i): # <<<<<<<<<<<<<< - * """ - * GetDeviceInfo(<device number>): returns 5 parameters - */ - -static PyObject *__pyx_pf_11_pyportmidi_GetDeviceInfo(PyObject *__pyx_self, PyObject *__pyx_v_i); /*proto*/ -static char __pyx_doc_11_pyportmidi_GetDeviceInfo[] = "\nGetDeviceInfo(<device number>): returns 5 parameters\n - underlying MIDI API\n - device name\n - TRUE iff input is available\n - TRUE iff output is available\n - TRUE iff device stream is already open\n "; -static PyObject *__pyx_pf_11_pyportmidi_GetDeviceInfo(PyObject *__pyx_self, PyObject *__pyx_v_i) { - PmDeviceInfo *__pyx_v_info; - PyObject *__pyx_r = NULL; - PmDeviceID __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - __Pyx_RefNannySetupContext("GetDeviceInfo"); - __pyx_self = __pyx_self; - __Pyx_INCREF(__pyx_v_i); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":168 - * - * # disregarding the constness from Pm_GetDeviceInfo, since pyrex doesn't do const. - * info = <PmDeviceInfo *>Pm_GetDeviceInfo(i) # <<<<<<<<<<<<<< - * - * if info <> NULL: return info.interf, info.name, info.input, info.output, info.opened - */ - __pyx_t_1 = __Pyx_PyInt_from_py_PmDeviceID(__pyx_v_i); if (unlikely((__pyx_t_1 == (PmDeviceID)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 168; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_info = ((PmDeviceInfo *)Pm_GetDeviceInfo(__pyx_t_1)); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":170 - * info = <PmDeviceInfo *>Pm_GetDeviceInfo(i) - * - * if info <> NULL: return info.interf, info.name, info.input, info.output, info.opened # <<<<<<<<<<<<<< - * else: return - * - */ - __pyx_t_2 = (__pyx_v_info != NULL); - if (__pyx_t_2) { - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_info->interf); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_3)); - __pyx_t_4 = __Pyx_PyBytes_FromString(__pyx_v_info->name); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_4)); - __pyx_t_5 = PyInt_FromLong(__pyx_v_info->input); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_6 = PyInt_FromLong(__pyx_v_info->output); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_7 = PyInt_FromLong(__pyx_v_info->opened); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_8 = PyTuple_New(5); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_8, 0, ((PyObject *)__pyx_t_3)); - __Pyx_GIVEREF(((PyObject *)__pyx_t_3)); - PyTuple_SET_ITEM(__pyx_t_8, 1, ((PyObject *)__pyx_t_4)); - __Pyx_GIVEREF(((PyObject *)__pyx_t_4)); - PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_t_5); - __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_8, 3, __pyx_t_6); - __Pyx_GIVEREF(__pyx_t_6); - PyTuple_SET_ITEM(__pyx_t_8, 4, __pyx_t_7); - __Pyx_GIVEREF(__pyx_t_7); - __pyx_t_3 = 0; - __pyx_t_4 = 0; - __pyx_t_5 = 0; - __pyx_t_6 = 0; - __pyx_t_7 = 0; - __pyx_r = __pyx_t_8; - __pyx_t_8 = 0; - goto __pyx_L0; - goto __pyx_L5; - } - /*else*/ { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":171 - * - * if info <> NULL: return info.interf, info.name, info.input, info.output, info.opened - * else: return # <<<<<<<<<<<<<< - * - * def Time(): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - } - __pyx_L5:; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_AddTraceback("_pyportmidi.GetDeviceInfo"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF(__pyx_v_i); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":173 - * else: return - * - * def Time(): # <<<<<<<<<<<<<< - * """ - * Time() returns the current time in ms - */ - -static PyObject *__pyx_pf_11_pyportmidi_Time(PyObject *__pyx_self, PyObject *unused); /*proto*/ -static char __pyx_doc_11_pyportmidi_Time[] = "\nTime() returns the current time in ms\nof the PortMidi timer\n "; -static PyObject *__pyx_pf_11_pyportmidi_Time(PyObject *__pyx_self, PyObject *unused) { - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - __Pyx_RefNannySetupContext("Time"); - __pyx_self = __pyx_self; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":178 - * of the PortMidi timer - * """ - * return Pt_Time() # <<<<<<<<<<<<<< - * - * def GetErrorText(err): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyInt_to_py_PtTimestamp(Pt_Time()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("_pyportmidi.Time"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":180 - * return Pt_Time() - * - * def GetErrorText(err): # <<<<<<<<<<<<<< - * """ - * GetErrorText(<err num>) returns human-readable error - */ - -static PyObject *__pyx_pf_11_pyportmidi_GetErrorText(PyObject *__pyx_self, PyObject *__pyx_v_err); /*proto*/ -static char __pyx_doc_11_pyportmidi_GetErrorText[] = "\nGetErrorText(<err num>) returns human-readable error\nmessages translated from error numbers\n "; -static PyObject *__pyx_pf_11_pyportmidi_GetErrorText(PyObject *__pyx_self, PyObject *__pyx_v_err) { - PyObject *__pyx_r = NULL; - PmError __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - __Pyx_RefNannySetupContext("GetErrorText"); - __pyx_self = __pyx_self; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":185 - * messages translated from error numbers - * """ - * return Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * - * def Channel(chan): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = ((PmError)PyInt_AsLong(__pyx_v_err)); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_2 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_t_1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - __pyx_r = ((PyObject *)__pyx_t_2); - __pyx_t_2 = 0; - goto __pyx_L0; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("_pyportmidi.GetErrorText"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":187 - * return Pm_GetErrorText(err) - * - * def Channel(chan): # <<<<<<<<<<<<<< - * """ - * Channel(<chan>) is used with ChannelMask on input MIDI streams. - */ - -static PyObject *__pyx_pf_11_pyportmidi_Channel(PyObject *__pyx_self, PyObject *__pyx_v_chan); /*proto*/ -static char __pyx_doc_11_pyportmidi_Channel[] = "\nChannel(<chan>) is used with ChannelMask on input MIDI streams.\nExample: to receive input on channels 1 and 10 on a MIDI\n stream called MidiIn:\nMidiIn.SetChannelMask(pypm.Channel(1) | pypm.Channel(10))\n\nnote: PyPortMidi Channel function has been altered from\n the original PortMidi c call to correct for what\n seems to be a bug --- i.e. channel filters were\n all numbered from 0 to 15 instead of 1 to 16.\n "; -static PyObject *__pyx_pf_11_pyportmidi_Channel(PyObject *__pyx_self, PyObject *__pyx_v_chan) { - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - __Pyx_RefNannySetupContext("Channel"); - __pyx_self = __pyx_self; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":199 - * all numbered from 0 to 15 instead of 1 to 16. - * """ - * return Pm_Channel(chan-1) # <<<<<<<<<<<<<< - * - * cdef class Output: - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyNumber_Subtract(__pyx_v_chan, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = PyInt_FromLong(Pm_Channel(__pyx_t_2)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("_pyportmidi.Channel"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":214 - * cdef int _aborted - * - * def __init__(self, OutputDevice, latency=0): # <<<<<<<<<<<<<< - * - * cdef PmError err - */ - -static int __pyx_pf_11_pyportmidi_6Output___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static int __pyx_pf_11_pyportmidi_6Output___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_OutputDevice = 0; - PyObject *__pyx_v_latency = 0; - PmError __pyx_v_err; - PmTimeProcPtr __pyx_v_PmPtr; - PyObject *__pyx_v_s; - int __pyx_r; - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_t_3; - long __pyx_t_4; - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__OutputDevice,&__pyx_n_s__latency,0}; - __Pyx_RefNannySetupContext("__init__"); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); - PyObject* values[2] = {0,0}; - values[1] = ((PyObject *)__pyx_int_0); - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__OutputDevice); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - if (kw_args > 1) { - PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__latency); - if (unlikely(value)) { values[1] = value; kw_args--; } - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_OutputDevice = values[0]; - __pyx_v_latency = values[1]; - } else { - __pyx_v_latency = ((PyObject *)__pyx_int_0); - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 2: __pyx_v_latency = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: __pyx_v_OutputDevice = PyTuple_GET_ITEM(__pyx_args, 0); - break; - default: goto __pyx_L5_argtuple_error; - } - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_L3_error:; - __Pyx_AddTraceback("_pyportmidi.Output.__init__"); - return -1; - __pyx_L4_argument_unpacking_done:; - __Pyx_INCREF((PyObject *)__pyx_v_self); - __Pyx_INCREF(__pyx_v_OutputDevice); - __Pyx_INCREF(__pyx_v_latency); - __pyx_v_s = Py_None; __Pyx_INCREF(Py_None); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":220 - * cdef PmTimeProcPtr PmPtr - * - * self.i = OutputDevice # <<<<<<<<<<<<<< - * self.debug = 0 - * self._aborted = 0 - */ - __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_OutputDevice); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->i = __pyx_t_1; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":221 - * - * self.i = OutputDevice - * self.debug = 0 # <<<<<<<<<<<<<< - * self._aborted = 0 - * - */ - ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->debug = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":222 - * self.i = OutputDevice - * self.debug = 0 - * self._aborted = 0 # <<<<<<<<<<<<<< - * - * if latency == 0: - */ - ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->_aborted = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":224 - * self._aborted = 0 - * - * if latency == 0: # <<<<<<<<<<<<<< - * PmPtr = NULL - * else: - */ - __pyx_t_2 = PyObject_RichCompare(__pyx_v_latency, __pyx_int_0, Py_EQ); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 224; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 224; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (__pyx_t_3) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":225 - * - * if latency == 0: - * PmPtr = NULL # <<<<<<<<<<<<<< - * else: - * PmPtr = <PmTimeProcPtr>&Pt_Time - */ - __pyx_v_PmPtr = NULL; - goto __pyx_L6; - } - /*else*/ { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":227 - * PmPtr = NULL - * else: - * PmPtr = <PmTimeProcPtr>&Pt_Time # <<<<<<<<<<<<<< - * if self.debug: print "Opening Midi Output" - * # Why is bufferSize 0 here? - */ - __pyx_v_PmPtr = ((PmTimestamp (*)(void *))(&Pt_Time)); - } - __pyx_L6:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":228 - * else: - * PmPtr = <PmTimeProcPtr>&Pt_Time - * if self.debug: print "Opening Midi Output" # <<<<<<<<<<<<<< - * # Why is bufferSize 0 here? - * err = Pm_OpenOutput(&(self.midi), self.i, NULL, 0, PmPtr, NULL, latency) - */ - __pyx_t_1 = ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->debug; - if (__pyx_t_1) { - if (__Pyx_PrintOne(((PyObject *)__pyx_kp_s_1)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 228; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L7; - } - __pyx_L7:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":230 - * if self.debug: print "Opening Midi Output" - * # Why is bufferSize 0 here? - * err = Pm_OpenOutput(&(self.midi), self.i, NULL, 0, PmPtr, NULL, latency) # <<<<<<<<<<<<<< - * if err < 0: - * s = Pm_GetErrorText(err) - */ - __pyx_t_4 = __Pyx_PyInt_AsLong(__pyx_v_latency); if (unlikely((__pyx_t_4 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 230; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_err = Pm_OpenOutput((&((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->midi), ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->i, NULL, 0, __pyx_v_PmPtr, NULL, __pyx_t_4); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":231 - * # Why is bufferSize 0 here? - * err = Pm_OpenOutput(&(self.midi), self.i, NULL, 0, PmPtr, NULL, latency) - * if err < 0: # <<<<<<<<<<<<<< - * s = Pm_GetErrorText(err) - * # Something's amiss here - if we try to throw an Exception - */ - __pyx_t_3 = (__pyx_v_err < 0); - if (__pyx_t_3) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":232 - * err = Pm_OpenOutput(&(self.midi), self.i, NULL, 0, PmPtr, NULL, latency) - * if err < 0: - * s = Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * # Something's amiss here - if we try to throw an Exception - * # here, we crash. - */ - __pyx_t_2 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_v_err)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - __Pyx_DECREF(__pyx_v_s); - __pyx_v_s = ((PyObject *)__pyx_t_2); - __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":235 - * # Something's amiss here - if we try to throw an Exception - * # here, we crash. - * if not err == -10000: # <<<<<<<<<<<<<< - * raise Exception,s - * else: - */ - __pyx_t_3 = (!(__pyx_v_err == -10000)); - if (__pyx_t_3) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":236 - * # here, we crash. - * if not err == -10000: - * raise Exception,s # <<<<<<<<<<<<<< - * else: - * print "Unable to open Midi OutputDevice=",OutputDevice," err=",s - */ - __Pyx_Raise(__pyx_builtin_Exception, __pyx_v_s, 0); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L9; - } - /*else*/ { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":238 - * raise Exception,s - * else: - * print "Unable to open Midi OutputDevice=",OutputDevice," err=",s # <<<<<<<<<<<<<< - * - * def __dealloc__(self): - */ - __pyx_t_2 = PyTuple_New(4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(((PyObject *)__pyx_kp_s_2)); - PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_2)); - __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_2)); - __Pyx_INCREF(__pyx_v_OutputDevice); - PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_OutputDevice); - __Pyx_GIVEREF(__pyx_v_OutputDevice); - __Pyx_INCREF(((PyObject *)__pyx_kp_s_3)); - PyTuple_SET_ITEM(__pyx_t_2, 2, ((PyObject *)__pyx_kp_s_3)); - __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_3)); - __Pyx_INCREF(__pyx_v_s); - PyTuple_SET_ITEM(__pyx_t_2, 3, __pyx_v_s); - __Pyx_GIVEREF(__pyx_v_s); - if (__Pyx_Print(__pyx_t_2, 1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - } - __pyx_L9:; - goto __pyx_L8; - } - __pyx_L8:; - - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("_pyportmidi.Output.__init__"); - __pyx_r = -1; - __pyx_L0:; - __Pyx_DECREF(__pyx_v_s); - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_DECREF(__pyx_v_OutputDevice); - __Pyx_DECREF(__pyx_v_latency); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":240 - * print "Unable to open Midi OutputDevice=",OutputDevice," err=",s - * - * def __dealloc__(self): # <<<<<<<<<<<<<< - * if self.debug: print "Closing MIDI output stream and destroying instance" - * #err = Pm_Abort(self.midi) - */ - -static void __pyx_pf_11_pyportmidi_6Output___dealloc__(PyObject *__pyx_v_self); /*proto*/ -static void __pyx_pf_11_pyportmidi_6Output___dealloc__(PyObject *__pyx_v_self) { - PyObject *__pyx_v_err; - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_t_3; - PmError __pyx_t_4; - __Pyx_RefNannySetupContext("__dealloc__"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - __pyx_v_err = Py_None; __Pyx_INCREF(Py_None); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":241 - * - * def __dealloc__(self): - * if self.debug: print "Closing MIDI output stream and destroying instance" # <<<<<<<<<<<<<< - * #err = Pm_Abort(self.midi) - * #if err < 0: raise Exception, Pm_GetErrorText(err) - */ - __pyx_t_1 = ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->debug; - if (__pyx_t_1) { - if (__Pyx_PrintOne(((PyObject *)__pyx_kp_s_4)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 241; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":244 - * #err = Pm_Abort(self.midi) - * #if err < 0: raise Exception, Pm_GetErrorText(err) - * err = Pm_Close(self.midi) # <<<<<<<<<<<<<< - * if err < 0: raise Exception, Pm_GetErrorText(err) - * - */ - __pyx_t_2 = PyInt_FromLong(Pm_Close(((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->midi)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 244; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_v_err); - __pyx_v_err = __pyx_t_2; - __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":245 - * #if err < 0: raise Exception, Pm_GetErrorText(err) - * err = Pm_Close(self.midi) - * if err < 0: raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_2 = PyObject_RichCompare(__pyx_v_err, __pyx_int_0, Py_LT); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (__pyx_t_3) { - __pyx_t_4 = ((PmError)PyInt_AsLong(__pyx_v_err)); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_2 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_t_4)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_2), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L6; - } - __pyx_L6:; - - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("_pyportmidi.Output.__dealloc__"); - __pyx_L0:; - __Pyx_DECREF(__pyx_v_err); - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_RefNannyFinishContext(); -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":248 - * - * - * def _check_open(self): # <<<<<<<<<<<<<< - * """ checks to see if the midi is open, and if not, raises an error. - * """ - */ - -static PyObject *__pyx_pf_11_pyportmidi_6Output__check_open(PyObject *__pyx_v_self, PyObject *unused); /*proto*/ -static char __pyx_doc_11_pyportmidi_6Output__check_open[] = " checks to see if the midi is open, and if not, raises an error.\n "; -static PyObject *__pyx_pf_11_pyportmidi_6Output__check_open(PyObject *__pyx_v_self, PyObject *unused) { - PyObject *__pyx_r = NULL; - int __pyx_t_1; - int __pyx_t_2; - __Pyx_RefNannySetupContext("_check_open"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":252 - * """ - * - * if self.midi == NULL: # <<<<<<<<<<<<<< - * raise Exception, "midi Output not open." - * - */ - __pyx_t_1 = (((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->midi == NULL); - if (__pyx_t_1) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":253 - * - * if self.midi == NULL: - * raise Exception, "midi Output not open." # <<<<<<<<<<<<<< - * - * if self._aborted: - */ - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_kp_s_5), 0); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":255 - * raise Exception, "midi Output not open." - * - * if self._aborted: # <<<<<<<<<<<<<< - * raise Exception, "midi Output aborted. Need to call Close after Abort." - * - */ - __pyx_t_2 = ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->_aborted; - if (__pyx_t_2) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":256 - * - * if self._aborted: - * raise Exception, "midi Output aborted. Need to call Close after Abort." # <<<<<<<<<<<<<< - * - * def Close(self): - */ - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_kp_s_6), 0); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L6; - } - __pyx_L6:; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_AddTraceback("_pyportmidi.Output._check_open"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":258 - * raise Exception, "midi Output aborted. Need to call Close after Abort." - * - * def Close(self): # <<<<<<<<<<<<<< - * """ - * Close() - */ - -static PyObject *__pyx_pf_11_pyportmidi_6Output_Close(PyObject *__pyx_v_self, PyObject *unused); /*proto*/ -static char __pyx_doc_11_pyportmidi_6Output_Close[] = "\nClose()\n closes a midi stream, flushing any pending buffers.\n (PortMidi attempts to close open streams when the application\n exits -- this is particularly difficult under Windows.)\n "; -static PyObject *__pyx_pf_11_pyportmidi_6Output_Close(PyObject *__pyx_v_self, PyObject *unused) { - PyObject *__pyx_v_err; - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - PmError __pyx_t_3; - __Pyx_RefNannySetupContext("Close"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - __pyx_v_err = Py_None; __Pyx_INCREF(Py_None); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":268 - * # return - * - * err = Pm_Close(self.midi) # <<<<<<<<<<<<<< - * if err < 0: - * raise Exception, Pm_GetErrorText(err) - */ - __pyx_t_1 = PyInt_FromLong(Pm_Close(((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->midi)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_v_err); - __pyx_v_err = __pyx_t_1; - __pyx_t_1 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":269 - * - * err = Pm_Close(self.midi) - * if err < 0: # <<<<<<<<<<<<<< - * raise Exception, Pm_GetErrorText(err) - * #self.midi = NULL - */ - __pyx_t_1 = PyObject_RichCompare(__pyx_v_err, __pyx_int_0, Py_LT); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_2) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":270 - * err = Pm_Close(self.midi) - * if err < 0: - * raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * #self.midi = NULL - * - */ - __pyx_t_3 = ((PmError)PyInt_AsLong(__pyx_v_err)); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_1 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_1), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("_pyportmidi.Output.Close"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF(__pyx_v_err); - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":274 - * - * - * def Abort(self): # <<<<<<<<<<<<<< - * """ - * Abort() terminates outgoing messages immediately - */ - -static PyObject *__pyx_pf_11_pyportmidi_6Output_Abort(PyObject *__pyx_v_self, PyObject *unused); /*proto*/ -static char __pyx_doc_11_pyportmidi_6Output_Abort[] = "\nAbort() terminates outgoing messages immediately\n The caller should immediately close the output port;\n this call may result in transmission of a partial midi message.\n There is no abort for Midi input because the user can simply\n ignore messages in the buffer and close an input device at\n any time.\n "; -static PyObject *__pyx_pf_11_pyportmidi_6Output_Abort(PyObject *__pyx_v_self, PyObject *unused) { - PyObject *__pyx_v_err; - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - PmError __pyx_t_3; - __Pyx_RefNannySetupContext("Abort"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - __pyx_v_err = Py_None; __Pyx_INCREF(Py_None); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":286 - * # return - * - * err = Pm_Abort(self.midi) # <<<<<<<<<<<<<< - * if err < 0: - * raise Exception, Pm_GetErrorText(err) - */ - __pyx_t_1 = PyInt_FromLong(Pm_Abort(((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->midi)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 286; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_v_err); - __pyx_v_err = __pyx_t_1; - __pyx_t_1 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":287 - * - * err = Pm_Abort(self.midi) - * if err < 0: # <<<<<<<<<<<<<< - * raise Exception, Pm_GetErrorText(err) - * - */ - __pyx_t_1 = PyObject_RichCompare(__pyx_v_err, __pyx_int_0, Py_LT); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_2) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":288 - * err = Pm_Abort(self.midi) - * if err < 0: - * raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * - * self._aborted = 1 - */ - __pyx_t_3 = ((PmError)PyInt_AsLong(__pyx_v_err)); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_1 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_1), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":290 - * raise Exception, Pm_GetErrorText(err) - * - * self._aborted = 1 # <<<<<<<<<<<<<< - * - * - */ - ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->_aborted = 1; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("_pyportmidi.Output.Abort"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF(__pyx_v_err); - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":293 - * - * - * def Write(self, data): # <<<<<<<<<<<<<< - * """ - * Write(data) - */ - -static PyObject *__pyx_pf_11_pyportmidi_6Output_Write(PyObject *__pyx_v_self, PyObject *__pyx_v_data); /*proto*/ -static char __pyx_doc_11_pyportmidi_6Output_Write[] = "\nWrite(data)\n output a series of MIDI information in the form of a list:\n Write([[[status <,data1><,data2><,data3>],timestamp],\n [[status <,data1><,data2><,data3>],timestamp],...])\n <data> fields are optional\n example: choose program change 1 at time 20000 and\n send note 65 with velocity 100 500 ms later.\n Write([[[0xc0,0,0],20000],[[0x90,60,100],20500]])\n notes:\n 1. timestamps will be ignored if latency = 0.\n 2. To get a note to play immediately, send MIDI info with\n timestamp read from function Time.\n 3. understanding optional data fields:\n Write([[[0xc0,0,0],20000]]) is equivalent to\n Write([[[0xc0],20000]])\n "; -static PyObject *__pyx_pf_11_pyportmidi_6Output_Write(PyObject *__pyx_v_self, PyObject *__pyx_v_data) { - PmEvent __pyx_v_buffer[1024]; - PmError __pyx_v_err; - int __pyx_v_i; - PyObject *__pyx_v_loop1; - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - Py_ssize_t __pyx_t_3; - int __pyx_t_4; - Py_ssize_t __pyx_t_5; - PyObject *__pyx_t_6 = NULL; - Py_ssize_t __pyx_t_7; - int __pyx_t_8; - PyObject *__pyx_t_9 = NULL; - PyObject *__pyx_t_10 = NULL; - PmMessage __pyx_t_11; - PmTimestamp __pyx_t_12; - __Pyx_RefNannySetupContext("Write"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - __Pyx_INCREF(__pyx_v_data); - __pyx_v_loop1 = Py_None; __Pyx_INCREF(Py_None); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":315 - * cdef int i - * - * self._check_open() # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___check_open); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":318 - * - * - * if len(data) > 1024: raise IndexError, 'maximum list length is 1024' # <<<<<<<<<<<<<< - * else: - * for loop1 in range(len(data)): - */ - __pyx_t_3 = PyObject_Length(__pyx_v_data); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_4 = (__pyx_t_3 > 1024); - if (__pyx_t_4) { - __Pyx_Raise(__pyx_builtin_IndexError, ((PyObject *)__pyx_kp_s_7), 0); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - /*else*/ { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":320 - * if len(data) > 1024: raise IndexError, 'maximum list length is 1024' - * else: - * for loop1 in range(len(data)): # <<<<<<<<<<<<<< - * if ((len(data[loop1][0]) > 4) | - * (len(data[loop1][0]) < 1)): - */ - __pyx_t_5 = PyObject_Length(__pyx_v_data); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_2 = PyInt_FromSsize_t(__pyx_t_5); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_2); - __pyx_t_2 = 0; - __pyx_t_2 = PyObject_Call(__pyx_builtin_range, __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (PyList_CheckExact(__pyx_t_2) || PyTuple_CheckExact(__pyx_t_2)) { - __pyx_t_3 = 0; __pyx_t_1 = __pyx_t_2; __Pyx_INCREF(__pyx_t_1); - } else { - __pyx_t_3 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - } - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - for (;;) { - if (likely(PyList_CheckExact(__pyx_t_1))) { - if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_1)) break; - __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_3); __Pyx_INCREF(__pyx_t_2); __pyx_t_3++; - } else if (likely(PyTuple_CheckExact(__pyx_t_1))) { - if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_1)) break; - __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_3); __Pyx_INCREF(__pyx_t_2); __pyx_t_3++; - } else { - __pyx_t_2 = PyIter_Next(__pyx_t_1); - if (!__pyx_t_2) { - if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - break; - } - __Pyx_GOTREF(__pyx_t_2); - } - __Pyx_DECREF(__pyx_v_loop1); - __pyx_v_loop1 = __pyx_t_2; - __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":321 - * else: - * for loop1 in range(len(data)): - * if ((len(data[loop1][0]) > 4) | # <<<<<<<<<<<<<< - * (len(data[loop1][0]) < 1)): - * raise IndexError, str(len(data[loop1][0]))+' arguments in event list' - */ - __pyx_t_2 = PyObject_GetItem(__pyx_v_data, __pyx_v_loop1); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_2, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_6) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_5 = PyObject_Length(__pyx_t_6); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":322 - * for loop1 in range(len(data)): - * if ((len(data[loop1][0]) > 4) | - * (len(data[loop1][0]) < 1)): # <<<<<<<<<<<<<< - * raise IndexError, str(len(data[loop1][0]))+' arguments in event list' - * buffer[loop1].message = 0 - */ - __pyx_t_6 = PyObject_GetItem(__pyx_v_data, __pyx_v_loop1); if (!__pyx_t_6) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 322; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_6, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 322; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __pyx_t_7 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_7 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 322; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_4 = ((__pyx_t_5 > 4) | (__pyx_t_7 < 1)); - if (__pyx_t_4) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":323 - * if ((len(data[loop1][0]) > 4) | - * (len(data[loop1][0]) < 1)): - * raise IndexError, str(len(data[loop1][0]))+' arguments in event list' # <<<<<<<<<<<<<< - * buffer[loop1].message = 0 - * for i in range(len(data[loop1][0])): - */ - __pyx_t_2 = PyObject_GetItem(__pyx_v_data, __pyx_v_loop1); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_2, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_6) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_7 = PyObject_Length(__pyx_t_6); if (unlikely(__pyx_t_7 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __pyx_t_6 = PyInt_FromSsize_t(__pyx_t_7); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_6); - __Pyx_GIVEREF(__pyx_t_6); - __pyx_t_6 = 0; - __pyx_t_6 = PyObject_Call(((PyObject *)((PyObject*)&PyString_Type)), __pyx_t_2, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyNumber_Add(__pyx_t_6, ((PyObject *)__pyx_kp_s_8)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_Raise(__pyx_builtin_IndexError, __pyx_t_2, 0); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L8; - } - __pyx_L8:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":324 - * (len(data[loop1][0]) < 1)): - * raise IndexError, str(len(data[loop1][0]))+' arguments in event list' - * buffer[loop1].message = 0 # <<<<<<<<<<<<<< - * for i in range(len(data[loop1][0])): - * buffer[loop1].message = buffer[loop1].message + ((data[loop1][0][i]&0xFF) << (8*i)) - */ - __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop1); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - (__pyx_v_buffer[__pyx_t_7]).message = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":325 - * raise IndexError, str(len(data[loop1][0]))+' arguments in event list' - * buffer[loop1].message = 0 - * for i in range(len(data[loop1][0])): # <<<<<<<<<<<<<< - * buffer[loop1].message = buffer[loop1].message + ((data[loop1][0][i]&0xFF) << (8*i)) - * buffer[loop1].timestamp = data[loop1][1] - */ - __pyx_t_2 = PyObject_GetItem(__pyx_v_data, __pyx_v_loop1); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_2, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_6) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_7 = PyObject_Length(__pyx_t_6); if (unlikely(__pyx_t_7 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) { - __pyx_v_i = __pyx_t_8; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":326 - * buffer[loop1].message = 0 - * for i in range(len(data[loop1][0])): - * buffer[loop1].message = buffer[loop1].message + ((data[loop1][0][i]&0xFF) << (8*i)) # <<<<<<<<<<<<<< - * buffer[loop1].timestamp = data[loop1][1] - * if self.debug: print loop1," : ",buffer[loop1].message," : ",buffer[loop1].timestamp - */ - __pyx_t_5 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop1); if (unlikely((__pyx_t_5 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_6 = __Pyx_PyInt_to_py_PmMessage((__pyx_v_buffer[__pyx_t_5]).message); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_2 = PyObject_GetItem(__pyx_v_data, __pyx_v_loop1); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_9 = __Pyx_GetItemInt(__pyx_t_2, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_9) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_9); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_9, __pyx_v_i, sizeof(int), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - __pyx_t_9 = PyNumber_And(__pyx_t_2, __pyx_int_0xFF); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_9); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyInt_FromLong((8 * __pyx_v_i)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_10 = PyNumber_Lshift(__pyx_t_9, __pyx_t_2); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_10); - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyNumber_Add(__pyx_t_6, __pyx_t_10); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __pyx_t_11 = __Pyx_PyInt_from_py_PmMessage(__pyx_t_2); if (unlikely((__pyx_t_11 == (PmMessage)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_5 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop1); if (unlikely((__pyx_t_5 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - (__pyx_v_buffer[__pyx_t_5]).message = __pyx_t_11; - } - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":327 - * for i in range(len(data[loop1][0])): - * buffer[loop1].message = buffer[loop1].message + ((data[loop1][0][i]&0xFF) << (8*i)) - * buffer[loop1].timestamp = data[loop1][1] # <<<<<<<<<<<<<< - * if self.debug: print loop1," : ",buffer[loop1].message," : ",buffer[loop1].timestamp - * if self.debug: print "writing to midi buffer" - */ - __pyx_t_2 = PyObject_GetItem(__pyx_v_data, __pyx_v_loop1); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_10 = __Pyx_GetItemInt(__pyx_t_2, 1, sizeof(long), PyInt_FromLong); if (!__pyx_t_10) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_10); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_12 = __Pyx_PyInt_from_py_PmTimestamp(__pyx_t_10); if (unlikely((__pyx_t_12 == (PmTimestamp)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __pyx_t_5 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop1); if (unlikely((__pyx_t_5 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - (__pyx_v_buffer[__pyx_t_5]).timestamp = __pyx_t_12; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":328 - * buffer[loop1].message = buffer[loop1].message + ((data[loop1][0][i]&0xFF) << (8*i)) - * buffer[loop1].timestamp = data[loop1][1] - * if self.debug: print loop1," : ",buffer[loop1].message," : ",buffer[loop1].timestamp # <<<<<<<<<<<<<< - * if self.debug: print "writing to midi buffer" - * err= Pm_Write(self.midi, buffer, len(data)) - */ - __pyx_t_8 = ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->debug; - if (__pyx_t_8) { - __pyx_t_5 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop1); if (unlikely((__pyx_t_5 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 328; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_10 = __Pyx_PyInt_to_py_PmMessage((__pyx_v_buffer[__pyx_t_5]).message); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 328; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_10); - __pyx_t_5 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop1); if (unlikely((__pyx_t_5 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 328; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_2 = __Pyx_PyInt_to_py_PmTimestamp((__pyx_v_buffer[__pyx_t_5]).timestamp); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 328; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_6 = PyTuple_New(5); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 328; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __Pyx_INCREF(__pyx_v_loop1); - PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_v_loop1); - __Pyx_GIVEREF(__pyx_v_loop1); - __Pyx_INCREF(((PyObject *)__pyx_kp_s_9)); - PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_kp_s_9)); - __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_9)); - PyTuple_SET_ITEM(__pyx_t_6, 2, __pyx_t_10); - __Pyx_GIVEREF(__pyx_t_10); - __Pyx_INCREF(((PyObject *)__pyx_kp_s_9)); - PyTuple_SET_ITEM(__pyx_t_6, 3, ((PyObject *)__pyx_kp_s_9)); - __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_9)); - PyTuple_SET_ITEM(__pyx_t_6, 4, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_2); - __pyx_t_10 = 0; - __pyx_t_2 = 0; - if (__Pyx_Print(__pyx_t_6, 1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 328; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - goto __pyx_L11; - } - __pyx_L11:; - } - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - } - __pyx_L5:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":329 - * buffer[loop1].timestamp = data[loop1][1] - * if self.debug: print loop1," : ",buffer[loop1].message," : ",buffer[loop1].timestamp - * if self.debug: print "writing to midi buffer" # <<<<<<<<<<<<<< - * err= Pm_Write(self.midi, buffer, len(data)) - * if err < 0: raise Exception, Pm_GetErrorText(err) - */ - __pyx_t_8 = ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->debug; - if (__pyx_t_8) { - if (__Pyx_PrintOne(((PyObject *)__pyx_kp_s_10)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L12; - } - __pyx_L12:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":330 - * if self.debug: print loop1," : ",buffer[loop1].message," : ",buffer[loop1].timestamp - * if self.debug: print "writing to midi buffer" - * err= Pm_Write(self.midi, buffer, len(data)) # <<<<<<<<<<<<<< - * if err < 0: raise Exception, Pm_GetErrorText(err) - * - */ - __pyx_t_3 = PyObject_Length(__pyx_v_data); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_err = Pm_Write(((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->midi, __pyx_v_buffer, __pyx_t_3); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":331 - * if self.debug: print "writing to midi buffer" - * err= Pm_Write(self.midi, buffer, len(data)) - * if err < 0: raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * - * def WriteShort(self, status, data1 = 0, data2 = 0): - */ - __pyx_t_4 = (__pyx_v_err < 0); - if (__pyx_t_4) { - __pyx_t_1 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_v_err)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_1), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L13; - } - __pyx_L13:; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_9); - __Pyx_XDECREF(__pyx_t_10); - __Pyx_AddTraceback("_pyportmidi.Output.Write"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF(__pyx_v_loop1); - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_DECREF(__pyx_v_data); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":333 - * if err < 0: raise Exception, Pm_GetErrorText(err) - * - * def WriteShort(self, status, data1 = 0, data2 = 0): # <<<<<<<<<<<<<< - * """ - * WriteShort(status <, data1><, data2>) - */ - -static PyObject *__pyx_pf_11_pyportmidi_6Output_WriteShort(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static char __pyx_doc_11_pyportmidi_6Output_WriteShort[] = "\nWriteShort(status <, data1><, data2>)\n output MIDI information of 3 bytes or less.\n data fields are optional\n status byte could be:\n 0xc0 = program change\n 0x90 = note on\n etc.\n data bytes are optional and assumed 0 if omitted\n example: note 65 on with velocity 100\n WriteShort(0x90,65,100)\n "; -static PyObject *__pyx_pf_11_pyportmidi_6Output_WriteShort(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_status = 0; - PyObject *__pyx_v_data1 = 0; - PyObject *__pyx_v_data2 = 0; - PmEvent __pyx_v_buffer[1]; - PmError __pyx_v_err; - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PmMessage __pyx_t_4; - int __pyx_t_5; - int __pyx_t_6; - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__status,&__pyx_n_s__data1,&__pyx_n_s__data2,0}; - __Pyx_RefNannySetupContext("WriteShort"); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); - PyObject* values[3] = {0,0,0}; - values[1] = ((PyObject *)__pyx_int_0); - values[2] = ((PyObject *)__pyx_int_0); - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__status); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - if (kw_args > 1) { - PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__data1); - if (unlikely(value)) { values[1] = value; kw_args--; } - } - case 2: - if (kw_args > 1) { - PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__data2); - if (unlikely(value)) { values[2] = value; kw_args--; } - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "WriteShort") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 333; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_status = values[0]; - __pyx_v_data1 = values[1]; - __pyx_v_data2 = values[2]; - } else { - __pyx_v_data1 = ((PyObject *)__pyx_int_0); - __pyx_v_data2 = ((PyObject *)__pyx_int_0); - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 3: __pyx_v_data2 = PyTuple_GET_ITEM(__pyx_args, 2); - case 2: __pyx_v_data1 = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: __pyx_v_status = PyTuple_GET_ITEM(__pyx_args, 0); - break; - default: goto __pyx_L5_argtuple_error; - } - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("WriteShort", 0, 1, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 333; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_L3_error:; - __Pyx_AddTraceback("_pyportmidi.Output.WriteShort"); - return NULL; - __pyx_L4_argument_unpacking_done:; - __Pyx_INCREF((PyObject *)__pyx_v_self); - __Pyx_INCREF(__pyx_v_status); - __Pyx_INCREF(__pyx_v_data1); - __Pyx_INCREF(__pyx_v_data2); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":348 - * cdef PmEvent buffer[1] - * cdef PmError err - * self._check_open() # <<<<<<<<<<<<<< - * - * buffer[0].timestamp = Pt_Time() - */ - __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___check_open); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":350 - * self._check_open() - * - * buffer[0].timestamp = Pt_Time() # <<<<<<<<<<<<<< - * buffer[0].message = ((((data2) << 16) & 0xFF0000) | (((data1) << 8) & 0xFF00) | ((status) & 0xFF)) - * if self.debug: print "Writing to MIDI buffer" - */ - (__pyx_v_buffer[0]).timestamp = Pt_Time(); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":351 - * - * buffer[0].timestamp = Pt_Time() - * buffer[0].message = ((((data2) << 16) & 0xFF0000) | (((data1) << 8) & 0xFF00) | ((status) & 0xFF)) # <<<<<<<<<<<<<< - * if self.debug: print "Writing to MIDI buffer" - * err = Pm_Write(self.midi, buffer, 1) # stream, buffer, length - */ - __pyx_t_2 = PyNumber_Lshift(__pyx_v_data2, __pyx_int_16); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_1 = PyNumber_And(__pyx_t_2, __pyx_int_0xFF0000); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyNumber_Lshift(__pyx_v_data1, __pyx_int_8); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyNumber_And(__pyx_t_2, __pyx_int_0xFF00); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyNumber_Or(__pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = PyNumber_And(__pyx_v_status, __pyx_int_0xFF); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_1 = PyNumber_Or(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_4 = __Pyx_PyInt_from_py_PmMessage(__pyx_t_1); if (unlikely((__pyx_t_4 == (PmMessage)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - (__pyx_v_buffer[0]).message = __pyx_t_4; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":352 - * buffer[0].timestamp = Pt_Time() - * buffer[0].message = ((((data2) << 16) & 0xFF0000) | (((data1) << 8) & 0xFF00) | ((status) & 0xFF)) - * if self.debug: print "Writing to MIDI buffer" # <<<<<<<<<<<<<< - * err = Pm_Write(self.midi, buffer, 1) # stream, buffer, length - * if err < 0 : raise Exception, Pm_GetErrorText(err) - */ - __pyx_t_5 = ((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->debug; - if (__pyx_t_5) { - if (__Pyx_PrintOne(((PyObject *)__pyx_kp_s_11)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L6; - } - __pyx_L6:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":353 - * buffer[0].message = ((((data2) << 16) & 0xFF0000) | (((data1) << 8) & 0xFF00) | ((status) & 0xFF)) - * if self.debug: print "Writing to MIDI buffer" - * err = Pm_Write(self.midi, buffer, 1) # stream, buffer, length # <<<<<<<<<<<<<< - * if err < 0 : raise Exception, Pm_GetErrorText(err) - * - */ - __pyx_v_err = Pm_Write(((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->midi, __pyx_v_buffer, 1); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":354 - * if self.debug: print "Writing to MIDI buffer" - * err = Pm_Write(self.midi, buffer, 1) # stream, buffer, length - * if err < 0 : raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * - * def WriteSysEx(self, when, msg): - */ - __pyx_t_6 = (__pyx_v_err < 0); - if (__pyx_t_6) { - __pyx_t_1 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_v_err)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_1), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L7; - } - __pyx_L7:; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("_pyportmidi.Output.WriteShort"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_DECREF(__pyx_v_status); - __Pyx_DECREF(__pyx_v_data1); - __Pyx_DECREF(__pyx_v_data2); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":356 - * if err < 0 : raise Exception, Pm_GetErrorText(err) - * - * def WriteSysEx(self, when, msg): # <<<<<<<<<<<<<< - * """ - * WriteSysEx(<timestamp>,<msg>) - */ - -static PyObject *__pyx_pf_11_pyportmidi_6Output_WriteSysEx(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static char __pyx_doc_11_pyportmidi_6Output_WriteSysEx[] = "\n WriteSysEx(<timestamp>,<msg>)\n writes a timestamped system-exclusive midi message.\n <msg> can be a *list* or a *string*\n example:\n (assuming y is an input MIDI stream)\n y.WriteSysEx(0,'\\xF0\\x7D\\x10\\x11\\x12\\x13\\xF7')\n is equivalent to\n y.WriteSysEx(pypm.Time,\n [0xF0, 0x7D, 0x10, 0x11, 0x12, 0x13, 0xF7])\n "; -static PyObject *__pyx_pf_11_pyportmidi_6Output_WriteSysEx(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_when = 0; - PyObject *__pyx_v_msg = 0; - PmError __pyx_v_err; - char *__pyx_v_cmsg; - PtTimestamp __pyx_v_CurTime; - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_t_3; - PyObject *__pyx_t_4 = NULL; - char *__pyx_t_5; - PmTimestamp __pyx_t_6; - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__when,&__pyx_n_s__msg,0}; - __Pyx_RefNannySetupContext("WriteSysEx"); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); - PyObject* values[2] = {0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__when); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__msg); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("WriteSysEx", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 356; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "WriteSysEx") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 356; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_when = values[0]; - __pyx_v_msg = values[1]; - } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { - goto __pyx_L5_argtuple_error; - } else { - __pyx_v_when = PyTuple_GET_ITEM(__pyx_args, 0); - __pyx_v_msg = PyTuple_GET_ITEM(__pyx_args, 1); - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("WriteSysEx", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 356; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_L3_error:; - __Pyx_AddTraceback("_pyportmidi.Output.WriteSysEx"); - return NULL; - __pyx_L4_argument_unpacking_done:; - __Pyx_INCREF((PyObject *)__pyx_v_self); - __Pyx_INCREF(__pyx_v_when); - __Pyx_INCREF(__pyx_v_msg); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":372 - * cdef PtTimestamp CurTime - * - * self._check_open() # <<<<<<<<<<<<<< - * - * if type(msg) is list: - */ - __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___check_open); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 372; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 372; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":374 - * self._check_open() - * - * if type(msg) is list: # <<<<<<<<<<<<<< - * msg = array.array('B',msg).tostring() # Markus Pfaff contribution - * cmsg = msg - */ - __pyx_t_3 = (((PyObject *)Py_TYPE(__pyx_v_msg)) == ((PyObject *)((PyObject*)&PyList_Type))); - if (__pyx_t_3) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":375 - * - * if type(msg) is list: - * msg = array.array('B',msg).tostring() # Markus Pfaff contribution # <<<<<<<<<<<<<< - * cmsg = msg - * - */ - __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__array); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 375; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__array); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 375; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 375; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(((PyObject *)__pyx_n_s__B)); - PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_n_s__B)); - __Pyx_GIVEREF(((PyObject *)__pyx_n_s__B)); - __Pyx_INCREF(__pyx_v_msg); - PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_msg); - __Pyx_GIVEREF(__pyx_v_msg); - __pyx_t_4 = PyObject_Call(__pyx_t_1, __pyx_t_2, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 375; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__tostring); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 375; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 375; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_v_msg); - __pyx_v_msg = __pyx_t_4; - __pyx_t_4 = 0; - goto __pyx_L6; - } - __pyx_L6:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":376 - * if type(msg) is list: - * msg = array.array('B',msg).tostring() # Markus Pfaff contribution - * cmsg = msg # <<<<<<<<<<<<<< - * - * CurTime = Pt_Time() - */ - __pyx_t_5 = __Pyx_PyBytes_AsString(__pyx_v_msg); if (unlikely((!__pyx_t_5) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 376; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_cmsg = __pyx_t_5; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":378 - * cmsg = msg - * - * CurTime = Pt_Time() # <<<<<<<<<<<<<< - * err = Pm_WriteSysEx(self.midi, when, <unsigned char *> cmsg) - * if err < 0 : raise Exception, Pm_GetErrorText(err) - */ - __pyx_v_CurTime = Pt_Time(); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":379 - * - * CurTime = Pt_Time() - * err = Pm_WriteSysEx(self.midi, when, <unsigned char *> cmsg) # <<<<<<<<<<<<<< - * if err < 0 : raise Exception, Pm_GetErrorText(err) - * while Pt_Time() == CurTime: # wait for SysEx to go thru or...my - */ - __pyx_t_6 = __Pyx_PyInt_from_py_PmTimestamp(__pyx_v_when); if (unlikely((__pyx_t_6 == (PmTimestamp)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 379; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_err = Pm_WriteSysEx(((struct __pyx_obj_11_pyportmidi_Output *)__pyx_v_self)->midi, __pyx_t_6, ((unsigned char *)__pyx_v_cmsg)); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":380 - * CurTime = Pt_Time() - * err = Pm_WriteSysEx(self.midi, when, <unsigned char *> cmsg) - * if err < 0 : raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * while Pt_Time() == CurTime: # wait for SysEx to go thru or...my - * pass # win32 machine crashes w/ multiple SysEx - */ - __pyx_t_3 = (__pyx_v_err < 0); - if (__pyx_t_3) { - __pyx_t_4 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_v_err)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_4)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_4), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L7; - } - __pyx_L7:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":381 - * err = Pm_WriteSysEx(self.midi, when, <unsigned char *> cmsg) - * if err < 0 : raise Exception, Pm_GetErrorText(err) - * while Pt_Time() == CurTime: # wait for SysEx to go thru or...my # <<<<<<<<<<<<<< - * pass # win32 machine crashes w/ multiple SysEx - * - */ - while (1) { - __pyx_t_3 = (Pt_Time() == __pyx_v_CurTime); - if (!__pyx_t_3) break; - } - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("_pyportmidi.Output.WriteSysEx"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_DECREF(__pyx_v_when); - __Pyx_DECREF(__pyx_v_msg); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":404 - * cdef int i - * - * def __init__(self, InputDevice, buffersize=4096): # <<<<<<<<<<<<<< - * cdef PmError err - * self.i = InputDevice - */ - -static int __pyx_pf_11_pyportmidi_5Input___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static int __pyx_pf_11_pyportmidi_5Input___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_InputDevice = 0; - PyObject *__pyx_v_buffersize = 0; - PmError __pyx_v_err; - int __pyx_r; - int __pyx_t_1; - long __pyx_t_2; - int __pyx_t_3; - PyObject *__pyx_t_4 = NULL; - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__InputDevice,&__pyx_n_s__buffersize,0}; - __Pyx_RefNannySetupContext("__init__"); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); - PyObject* values[2] = {0,0}; - values[1] = ((PyObject *)__pyx_int_4096); - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__InputDevice); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - if (kw_args > 1) { - PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__buffersize); - if (unlikely(value)) { values[1] = value; kw_args--; } - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_InputDevice = values[0]; - __pyx_v_buffersize = values[1]; - } else { - __pyx_v_buffersize = ((PyObject *)__pyx_int_4096); - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 2: __pyx_v_buffersize = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: __pyx_v_InputDevice = PyTuple_GET_ITEM(__pyx_args, 0); - break; - default: goto __pyx_L5_argtuple_error; - } - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_L3_error:; - __Pyx_AddTraceback("_pyportmidi.Input.__init__"); - return -1; - __pyx_L4_argument_unpacking_done:; - __Pyx_INCREF((PyObject *)__pyx_v_self); - __Pyx_INCREF(__pyx_v_InputDevice); - __Pyx_INCREF(__pyx_v_buffersize); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":406 - * def __init__(self, InputDevice, buffersize=4096): - * cdef PmError err - * self.i = InputDevice # <<<<<<<<<<<<<< - * self.debug = 0 - * err= Pm_OpenInput(&(self.midi),self.i,NULL,buffersize,&Pt_Time,NULL) - */ - __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_InputDevice); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 406; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - ((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->i = __pyx_t_1; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":407 - * cdef PmError err - * self.i = InputDevice - * self.debug = 0 # <<<<<<<<<<<<<< - * err= Pm_OpenInput(&(self.midi),self.i,NULL,buffersize,&Pt_Time,NULL) - * if err < 0: raise Exception, Pm_GetErrorText(err) - */ - ((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->debug = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":408 - * self.i = InputDevice - * self.debug = 0 - * err= Pm_OpenInput(&(self.midi),self.i,NULL,buffersize,&Pt_Time,NULL) # <<<<<<<<<<<<<< - * if err < 0: raise Exception, Pm_GetErrorText(err) - * if self.debug: print "MIDI input opened." - */ - __pyx_t_2 = __Pyx_PyInt_AsLong(__pyx_v_buffersize); if (unlikely((__pyx_t_2 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 408; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_err = Pm_OpenInput((&((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->midi), ((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->i, NULL, __pyx_t_2, (&Pt_Time), NULL); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":409 - * self.debug = 0 - * err= Pm_OpenInput(&(self.midi),self.i,NULL,buffersize,&Pt_Time,NULL) - * if err < 0: raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * if self.debug: print "MIDI input opened." - * - */ - __pyx_t_3 = (__pyx_v_err < 0); - if (__pyx_t_3) { - __pyx_t_4 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_v_err)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_4)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_4), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L6; - } - __pyx_L6:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":410 - * err= Pm_OpenInput(&(self.midi),self.i,NULL,buffersize,&Pt_Time,NULL) - * if err < 0: raise Exception, Pm_GetErrorText(err) - * if self.debug: print "MIDI input opened." # <<<<<<<<<<<<<< - * - * def __dealloc__(self): - */ - __pyx_t_1 = ((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->debug; - if (__pyx_t_1) { - if (__Pyx_PrintOne(((PyObject *)__pyx_kp_s_12)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 410; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L7; - } - __pyx_L7:; - - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("_pyportmidi.Input.__init__"); - __pyx_r = -1; - __pyx_L0:; - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_DECREF(__pyx_v_InputDevice); - __Pyx_DECREF(__pyx_v_buffersize); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":412 - * if self.debug: print "MIDI input opened." - * - * def __dealloc__(self): # <<<<<<<<<<<<<< - * cdef PmError err - * if self.debug: print "Closing MIDI input stream and destroying instance" - */ - -static void __pyx_pf_11_pyportmidi_5Input___dealloc__(PyObject *__pyx_v_self); /*proto*/ -static void __pyx_pf_11_pyportmidi_5Input___dealloc__(PyObject *__pyx_v_self) { - PmError __pyx_v_err; - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - __Pyx_RefNannySetupContext("__dealloc__"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":414 - * def __dealloc__(self): - * cdef PmError err - * if self.debug: print "Closing MIDI input stream and destroying instance" # <<<<<<<<<<<<<< - * - * err = Pm_Close(self.midi) - */ - __pyx_t_1 = ((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->debug; - if (__pyx_t_1) { - if (__Pyx_PrintOne(((PyObject *)__pyx_kp_s_13)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 414; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":416 - * if self.debug: print "Closing MIDI input stream and destroying instance" - * - * err = Pm_Close(self.midi) # <<<<<<<<<<<<<< - * if err < 0: - * raise Exception, Pm_GetErrorText(err) - */ - __pyx_v_err = Pm_Close(((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->midi); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":417 - * - * err = Pm_Close(self.midi) - * if err < 0: # <<<<<<<<<<<<<< - * raise Exception, Pm_GetErrorText(err) - * - */ - __pyx_t_2 = (__pyx_v_err < 0); - if (__pyx_t_2) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":418 - * err = Pm_Close(self.midi) - * if err < 0: - * raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_3 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_v_err)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_3)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_3), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L6; - } - __pyx_L6:; - - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("_pyportmidi.Input.__dealloc__"); - __pyx_L0:; - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_RefNannyFinishContext(); -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":422 - * - * - * def _check_open(self): # <<<<<<<<<<<<<< - * """ checks to see if the midi is open, and if not, raises an error. - * """ - */ - -static PyObject *__pyx_pf_11_pyportmidi_5Input__check_open(PyObject *__pyx_v_self, PyObject *unused); /*proto*/ -static char __pyx_doc_11_pyportmidi_5Input__check_open[] = " checks to see if the midi is open, and if not, raises an error.\n "; -static PyObject *__pyx_pf_11_pyportmidi_5Input__check_open(PyObject *__pyx_v_self, PyObject *unused) { - PyObject *__pyx_r = NULL; - int __pyx_t_1; - __Pyx_RefNannySetupContext("_check_open"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":426 - * """ - * - * if self.midi == NULL: # <<<<<<<<<<<<<< - * raise Exception, "midi Input not open." - * - */ - __pyx_t_1 = (((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->midi == NULL); - if (__pyx_t_1) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":427 - * - * if self.midi == NULL: - * raise Exception, "midi Input not open." # <<<<<<<<<<<<<< - * - * - */ - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_kp_s_14), 0); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 427; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_AddTraceback("_pyportmidi.Input._check_open"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":430 - * - * - * def Close(self): # <<<<<<<<<<<<<< - * """ - * Close() - */ - -static PyObject *__pyx_pf_11_pyportmidi_5Input_Close(PyObject *__pyx_v_self, PyObject *unused); /*proto*/ -static char __pyx_doc_11_pyportmidi_5Input_Close[] = "\nClose()\n closes a midi stream, flushing any pending buffers.\n (PortMidi attempts to close open streams when the application\n exits -- this is particularly difficult under Windows.)\n "; -static PyObject *__pyx_pf_11_pyportmidi_5Input_Close(PyObject *__pyx_v_self, PyObject *unused) { - PyObject *__pyx_v_err; - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - PmError __pyx_t_3; - __Pyx_RefNannySetupContext("Close"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - __pyx_v_err = Py_None; __Pyx_INCREF(Py_None); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":440 - * # return - * - * err = Pm_Close(self.midi) # <<<<<<<<<<<<<< - * if err < 0: - * raise Exception, Pm_GetErrorText(err) - */ - __pyx_t_1 = PyInt_FromLong(Pm_Close(((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->midi)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 440; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_v_err); - __pyx_v_err = __pyx_t_1; - __pyx_t_1 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":441 - * - * err = Pm_Close(self.midi) - * if err < 0: # <<<<<<<<<<<<<< - * raise Exception, Pm_GetErrorText(err) - * #self.midi = NULL - */ - __pyx_t_1 = PyObject_RichCompare(__pyx_v_err, __pyx_int_0, Py_LT); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 441; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 441; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_2) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":442 - * err = Pm_Close(self.midi) - * if err < 0: - * raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * #self.midi = NULL - * - */ - __pyx_t_3 = ((PmError)PyInt_AsLong(__pyx_v_err)); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 442; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_1 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 442; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_1), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 442; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("_pyportmidi.Input.Close"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF(__pyx_v_err); - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":447 - * - * - * def SetFilter(self, filters): # <<<<<<<<<<<<<< - * """ - * SetFilter(<filters>) sets filters on an open input stream - */ - -static PyObject *__pyx_pf_11_pyportmidi_5Input_SetFilter(PyObject *__pyx_v_self, PyObject *__pyx_v_filters); /*proto*/ -static char __pyx_doc_11_pyportmidi_5Input_SetFilter[] = "\n SetFilter(<filters>) sets filters on an open input stream\n to drop selected input types. By default, only active sensing\n messages are filtered. To prohibit, say, active sensing and\n sysex messages, call\n SetFilter(stream, FILT_ACTIVE | FILT_SYSEX);\n\n Filtering is useful when midi routing or midi thru functionality\n is being provided by the user application.\n For example, you may want to exclude timing messages\n (clock, MTC, start/stop/continue), while allowing note-related\n messages to pass. Or you may be using a sequencer or drum-machine\n for MIDI clock information but want to exclude any notes\n it may play.\n\n Note: SetFilter empties the buffer after setting the filter,\n just in case anything got through.\n "; -static PyObject *__pyx_pf_11_pyportmidi_5Input_SetFilter(PyObject *__pyx_v_self, PyObject *__pyx_v_filters) { - PmEvent __pyx_v_buffer[1]; - PmError __pyx_v_err; - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - long __pyx_t_3; - int __pyx_t_4; - __Pyx_RefNannySetupContext("SetFilter"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - __Pyx_INCREF(__pyx_v_filters); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":469 - * cdef PmError err - * - * self._check_open() # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___check_open); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":472 - * - * - * err = Pm_SetFilter(self.midi, filters) # <<<<<<<<<<<<<< - * - * if err < 0: raise Exception, Pm_GetErrorText(err) - */ - __pyx_t_3 = __Pyx_PyInt_AsLong(__pyx_v_filters); if (unlikely((__pyx_t_3 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 472; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_err = Pm_SetFilter(((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->midi, __pyx_t_3); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":474 - * err = Pm_SetFilter(self.midi, filters) - * - * if err < 0: raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * - * while(Pm_Poll(self.midi) != pmNoError): - */ - __pyx_t_4 = (__pyx_v_err < 0); - if (__pyx_t_4) { - __pyx_t_2 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_v_err)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 474; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_2), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 474; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":476 - * if err < 0: raise Exception, Pm_GetErrorText(err) - * - * while(Pm_Poll(self.midi) != pmNoError): # <<<<<<<<<<<<<< - * - * err = Pm_Read(self.midi,buffer,1) - */ - while (1) { - __pyx_t_4 = (Pm_Poll(((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->midi) != pmNoError); - if (!__pyx_t_4) break; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":478 - * while(Pm_Poll(self.midi) != pmNoError): - * - * err = Pm_Read(self.midi,buffer,1) # <<<<<<<<<<<<<< - * if err < 0: raise Exception, Pm_GetErrorText(err) - * - */ - __pyx_v_err = Pm_Read(((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->midi, __pyx_v_buffer, 1); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":479 - * - * err = Pm_Read(self.midi,buffer,1) - * if err < 0: raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * - * def SetChannelMask(self, mask): - */ - __pyx_t_4 = (__pyx_v_err < 0); - if (__pyx_t_4) { - __pyx_t_2 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_v_err)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 479; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_2), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 479; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L8; - } - __pyx_L8:; - } - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("_pyportmidi.Input.SetFilter"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_DECREF(__pyx_v_filters); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":481 - * if err < 0: raise Exception, Pm_GetErrorText(err) - * - * def SetChannelMask(self, mask): # <<<<<<<<<<<<<< - * """ - * SetChannelMask(<mask>) filters incoming messages based on channel. - */ - -static PyObject *__pyx_pf_11_pyportmidi_5Input_SetChannelMask(PyObject *__pyx_v_self, PyObject *__pyx_v_mask); /*proto*/ -static char __pyx_doc_11_pyportmidi_5Input_SetChannelMask[] = "\n SetChannelMask(<mask>) filters incoming messages based on channel.\n The mask is a 16-bit bitfield corresponding to appropriate channels\n Channel(<channel>) can assist in calling this function.\n i.e. to set receive only input on channel 1, call with\n SetChannelMask(Channel(1))\n Multiple channels should be OR'd together, like\n SetChannelMask(Channel(10) | Channel(11))\n note: PyPortMidi Channel function has been altered from\n the original PortMidi c call to correct for what\n seems to be a bug --- i.e. channel filters were\n all numbered from 0 to 15 instead of 1 to 16.\n "; -static PyObject *__pyx_pf_11_pyportmidi_5Input_SetChannelMask(PyObject *__pyx_v_self, PyObject *__pyx_v_mask) { - PmError __pyx_v_err; - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_t_3; - int __pyx_t_4; - __Pyx_RefNannySetupContext("SetChannelMask"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - __Pyx_INCREF(__pyx_v_mask); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":497 - * cdef PmError err - * - * self._check_open() # <<<<<<<<<<<<<< - * - * err = Pm_SetChannelMask(self.midi,mask) - */ - __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___check_open); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 497; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 497; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":499 - * self._check_open() - * - * err = Pm_SetChannelMask(self.midi,mask) # <<<<<<<<<<<<<< - * if err < 0: raise Exception, Pm_GetErrorText(err) - * - */ - __pyx_t_3 = __Pyx_PyInt_AsInt(__pyx_v_mask); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_err = Pm_SetChannelMask(((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->midi, __pyx_t_3); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":500 - * - * err = Pm_SetChannelMask(self.midi,mask) - * if err < 0: raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * - * def Poll(self): - */ - __pyx_t_4 = (__pyx_v_err < 0); - if (__pyx_t_4) { - __pyx_t_2 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_v_err)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_2), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("_pyportmidi.Input.SetChannelMask"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_DECREF(__pyx_v_mask); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":502 - * if err < 0: raise Exception, Pm_GetErrorText(err) - * - * def Poll(self): # <<<<<<<<<<<<<< - * """ - * Poll tests whether input is available, - */ - -static PyObject *__pyx_pf_11_pyportmidi_5Input_Poll(PyObject *__pyx_v_self, PyObject *unused); /*proto*/ -static char __pyx_doc_11_pyportmidi_5Input_Poll[] = "\n Poll tests whether input is available,\n returning TRUE, FALSE, or an error value.\n "; -static PyObject *__pyx_pf_11_pyportmidi_5Input_Poll(PyObject *__pyx_v_self, PyObject *unused) { - PmError __pyx_v_err; - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_t_3; - __Pyx_RefNannySetupContext("Poll"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":508 - * """ - * cdef PmError err - * self._check_open() # <<<<<<<<<<<<<< - * - * err = Pm_Poll(self.midi) - */ - __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___check_open); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 508; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 508; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":510 - * self._check_open() - * - * err = Pm_Poll(self.midi) # <<<<<<<<<<<<<< - * if err < 0: raise Exception, Pm_GetErrorText(err) - * return err - */ - __pyx_v_err = Pm_Poll(((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->midi); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":511 - * - * err = Pm_Poll(self.midi) - * if err < 0: raise Exception, Pm_GetErrorText(err) # <<<<<<<<<<<<<< - * return err - * - */ - __pyx_t_3 = (__pyx_v_err < 0); - if (__pyx_t_3) { - __pyx_t_2 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_v_err)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 511; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_2), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 511; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":512 - * err = Pm_Poll(self.midi) - * if err < 0: raise Exception, Pm_GetErrorText(err) - * return err # <<<<<<<<<<<<<< - * - * def Read(self,length): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = PyInt_FromLong(__pyx_v_err); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 512; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("_pyportmidi.Input.Poll"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":514 - * return err - * - * def Read(self,length): # <<<<<<<<<<<<<< - * """ - * Read(length): returns up to <length> midi events stored in - */ - -static PyObject *__pyx_pf_11_pyportmidi_5Input_Read(PyObject *__pyx_v_self, PyObject *__pyx_v_length); /*proto*/ -static char __pyx_doc_11_pyportmidi_5Input_Read[] = "\nRead(length): returns up to <length> midi events stored in\nthe buffer and returns them as a list:\n[[[status,data1,data2,data3],timestamp],\n [[status,data1,data2,data3],timestamp],...]\nexample: Read(50) returns all the events in the buffer,\n up to 50 events.\n "; -static PyObject *__pyx_pf_11_pyportmidi_5Input_Read(PyObject *__pyx_v_self, PyObject *__pyx_v_length) { - PmEvent __pyx_v_buffer[1024]; - PyObject *__pyx_v_x; - PyObject *__pyx_v_NumEvents; - PyObject *__pyx_v_loop; - PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_t_3; - long __pyx_t_4; - PmError __pyx_t_5; - Py_ssize_t __pyx_t_6; - Py_ssize_t __pyx_t_7; - PyObject *__pyx_t_8 = NULL; - PyObject *__pyx_t_9 = NULL; - PyObject *__pyx_t_10 = NULL; - PyObject *__pyx_t_11 = NULL; - __Pyx_RefNannySetupContext("Read"); - __Pyx_INCREF((PyObject *)__pyx_v_self); - __Pyx_INCREF(__pyx_v_length); - __pyx_v_x = Py_None; __Pyx_INCREF(Py_None); - __pyx_v_NumEvents = Py_None; __Pyx_INCREF(Py_None); - __pyx_v_loop = Py_None; __Pyx_INCREF(Py_None); - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":525 - * cdef PmEvent buffer[1024] - * - * self._check_open() # <<<<<<<<<<<<<< - * - * x = [] - */ - __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___check_open); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 525; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 525; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":527 - * self._check_open() - * - * x = [] # <<<<<<<<<<<<<< - * - * if length > 1024: raise IndexError, 'maximum buffer length is 1024' - */ - __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 527; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - __Pyx_DECREF(__pyx_v_x); - __pyx_v_x = ((PyObject *)__pyx_t_2); - __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":529 - * x = [] - * - * if length > 1024: raise IndexError, 'maximum buffer length is 1024' # <<<<<<<<<<<<<< - * if length < 1: raise IndexError, 'minimum buffer length is 1' - * NumEvents = Pm_Read(self.midi,buffer,length) - */ - __pyx_t_2 = PyObject_RichCompare(__pyx_v_length, __pyx_int_1024, Py_GT); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (__pyx_t_3) { - __Pyx_Raise(__pyx_builtin_IndexError, ((PyObject *)__pyx_kp_s_15), 0); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L5; - } - __pyx_L5:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":530 - * - * if length > 1024: raise IndexError, 'maximum buffer length is 1024' - * if length < 1: raise IndexError, 'minimum buffer length is 1' # <<<<<<<<<<<<<< - * NumEvents = Pm_Read(self.midi,buffer,length) - * if NumEvents < 0: raise Exception, Pm_GetErrorText(NumEvents) - */ - __pyx_t_2 = PyObject_RichCompare(__pyx_v_length, __pyx_int_1, Py_LT); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (__pyx_t_3) { - __Pyx_Raise(__pyx_builtin_IndexError, ((PyObject *)__pyx_kp_s_16), 0); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L6; - } - __pyx_L6:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":531 - * if length > 1024: raise IndexError, 'maximum buffer length is 1024' - * if length < 1: raise IndexError, 'minimum buffer length is 1' - * NumEvents = Pm_Read(self.midi,buffer,length) # <<<<<<<<<<<<<< - * if NumEvents < 0: raise Exception, Pm_GetErrorText(NumEvents) - * x=[] - */ - __pyx_t_4 = __Pyx_PyInt_AsLong(__pyx_v_length); if (unlikely((__pyx_t_4 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 531; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_2 = PyInt_FromLong(Pm_Read(((struct __pyx_obj_11_pyportmidi_Input *)__pyx_v_self)->midi, __pyx_v_buffer, __pyx_t_4)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 531; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_v_NumEvents); - __pyx_v_NumEvents = __pyx_t_2; - __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":532 - * if length < 1: raise IndexError, 'minimum buffer length is 1' - * NumEvents = Pm_Read(self.midi,buffer,length) - * if NumEvents < 0: raise Exception, Pm_GetErrorText(NumEvents) # <<<<<<<<<<<<<< - * x=[] - * if NumEvents >= 1: - */ - __pyx_t_2 = PyObject_RichCompare(__pyx_v_NumEvents, __pyx_int_0, Py_LT); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (__pyx_t_3) { - __pyx_t_5 = ((PmError)PyInt_AsLong(__pyx_v_NumEvents)); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_2 = __Pyx_PyBytes_FromString(Pm_GetErrorText(__pyx_t_5)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - __Pyx_Raise(__pyx_builtin_Exception, ((PyObject *)__pyx_t_2), 0); - __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 532; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L7; - } - __pyx_L7:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":533 - * NumEvents = Pm_Read(self.midi,buffer,length) - * if NumEvents < 0: raise Exception, Pm_GetErrorText(NumEvents) - * x=[] # <<<<<<<<<<<<<< - * if NumEvents >= 1: - * for loop in range(NumEvents): - */ - __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 533; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - __Pyx_DECREF(__pyx_v_x); - __pyx_v_x = ((PyObject *)__pyx_t_2); - __pyx_t_2 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":534 - * if NumEvents < 0: raise Exception, Pm_GetErrorText(NumEvents) - * x=[] - * if NumEvents >= 1: # <<<<<<<<<<<<<< - * for loop in range(NumEvents): - * x.append([[buffer[loop].message & 0xff, (buffer[loop].message >> 8) & 0xFF, (buffer[loop].message >> 16) & 0xFF, (buffer[loop].message >> 24) & 0xFF], buffer[loop].timestamp]) - */ - __pyx_t_2 = PyObject_RichCompare(__pyx_v_NumEvents, __pyx_int_1, Py_GE); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 534; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 534; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (__pyx_t_3) { - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":535 - * x=[] - * if NumEvents >= 1: - * for loop in range(NumEvents): # <<<<<<<<<<<<<< - * x.append([[buffer[loop].message & 0xff, (buffer[loop].message >> 8) & 0xFF, (buffer[loop].message >> 16) & 0xFF, (buffer[loop].message >> 24) & 0xFF], buffer[loop].timestamp]) - * return x - */ - __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 535; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_v_NumEvents); - PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_NumEvents); - __Pyx_GIVEREF(__pyx_v_NumEvents); - __pyx_t_1 = PyObject_Call(__pyx_builtin_range, __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 535; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (PyList_CheckExact(__pyx_t_1) || PyTuple_CheckExact(__pyx_t_1)) { - __pyx_t_6 = 0; __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); - } else { - __pyx_t_6 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 535; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - } - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - for (;;) { - if (likely(PyList_CheckExact(__pyx_t_2))) { - if (__pyx_t_6 >= PyList_GET_SIZE(__pyx_t_2)) break; - __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_6); __Pyx_INCREF(__pyx_t_1); __pyx_t_6++; - } else if (likely(PyTuple_CheckExact(__pyx_t_2))) { - if (__pyx_t_6 >= PyTuple_GET_SIZE(__pyx_t_2)) break; - __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_6); __Pyx_INCREF(__pyx_t_1); __pyx_t_6++; - } else { - __pyx_t_1 = PyIter_Next(__pyx_t_2); - if (!__pyx_t_1) { - if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 535; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - break; - } - __Pyx_GOTREF(__pyx_t_1); - } - __Pyx_DECREF(__pyx_v_loop); - __pyx_v_loop = __pyx_t_1; - __pyx_t_1 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":536 - * if NumEvents >= 1: - * for loop in range(NumEvents): - * x.append([[buffer[loop].message & 0xff, (buffer[loop].message >> 8) & 0xFF, (buffer[loop].message >> 16) & 0xFF, (buffer[loop].message >> 24) & 0xFF], buffer[loop].timestamp]) # <<<<<<<<<<<<<< - * return x - */ - __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_1 = __Pyx_PyInt_to_py_PmMessage(((__pyx_v_buffer[__pyx_t_7]).message & 0xff)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_8 = __Pyx_PyInt_to_py_PmMessage((((__pyx_v_buffer[__pyx_t_7]).message >> 8) & 0xFF)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_9 = __Pyx_PyInt_to_py_PmMessage((((__pyx_v_buffer[__pyx_t_7]).message >> 16) & 0xFF)); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_9); - __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_10 = __Pyx_PyInt_to_py_PmMessage((((__pyx_v_buffer[__pyx_t_7]).message >> 24) & 0xFF)); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_10); - __pyx_t_11 = PyList_New(4); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_11)); - PyList_SET_ITEM(__pyx_t_11, 0, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - PyList_SET_ITEM(__pyx_t_11, 1, __pyx_t_8); - __Pyx_GIVEREF(__pyx_t_8); - PyList_SET_ITEM(__pyx_t_11, 2, __pyx_t_9); - __Pyx_GIVEREF(__pyx_t_9); - PyList_SET_ITEM(__pyx_t_11, 3, __pyx_t_10); - __Pyx_GIVEREF(__pyx_t_10); - __pyx_t_1 = 0; - __pyx_t_8 = 0; - __pyx_t_9 = 0; - __pyx_t_10 = 0; - __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loop); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_10 = __Pyx_PyInt_to_py_PmTimestamp((__pyx_v_buffer[__pyx_t_7]).timestamp); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_10); - __pyx_t_9 = PyList_New(2); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_9)); - PyList_SET_ITEM(__pyx_t_9, 0, ((PyObject *)__pyx_t_11)); - __Pyx_GIVEREF(((PyObject *)__pyx_t_11)); - PyList_SET_ITEM(__pyx_t_9, 1, __pyx_t_10); - __Pyx_GIVEREF(__pyx_t_10); - __pyx_t_11 = 0; - __pyx_t_10 = 0; - __pyx_t_10 = __Pyx_PyObject_Append(__pyx_v_x, ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_10); - __Pyx_DECREF(((PyObject *)__pyx_t_9)); __pyx_t_9 = 0; - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - } - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - goto __pyx_L8; - } - __pyx_L8:; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":537 - * for loop in range(NumEvents): - * x.append([[buffer[loop].message & 0xff, (buffer[loop].message >> 8) & 0xFF, (buffer[loop].message >> 16) & 0xFF, (buffer[loop].message >> 24) & 0xFF], buffer[loop].timestamp]) - * return x # <<<<<<<<<<<<<< - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_x); - __pyx_r = __pyx_v_x; - goto __pyx_L0; - - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_XDECREF(__pyx_t_9); - __Pyx_XDECREF(__pyx_t_10); - __Pyx_XDECREF(__pyx_t_11); - __Pyx_AddTraceback("_pyportmidi.Input.Read"); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_DECREF(__pyx_v_x); - __Pyx_DECREF(__pyx_v_NumEvents); - __Pyx_DECREF(__pyx_v_loop); - __Pyx_DECREF((PyObject *)__pyx_v_self); - __Pyx_DECREF(__pyx_v_length); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_tp_new_11_pyportmidi_Output(PyTypeObject *t, PyObject *a, PyObject *k) { - PyObject *o = (*t->tp_alloc)(t, 0); - if (!o) return 0; - return o; -} - -static void __pyx_tp_dealloc_11_pyportmidi_Output(PyObject *o) { - { - PyObject *etype, *eval, *etb; - PyErr_Fetch(&etype, &eval, &etb); - ++Py_REFCNT(o); - __pyx_pf_11_pyportmidi_6Output___dealloc__(o); - if (PyErr_Occurred()) PyErr_WriteUnraisable(o); - --Py_REFCNT(o); - PyErr_Restore(etype, eval, etb); - } - (*Py_TYPE(o)->tp_free)(o); -} - -static struct PyMethodDef __pyx_methods_11_pyportmidi_Output[] = { - {__Pyx_NAMESTR("_check_open"), (PyCFunction)__pyx_pf_11_pyportmidi_6Output__check_open, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_6Output__check_open)}, - {__Pyx_NAMESTR("Close"), (PyCFunction)__pyx_pf_11_pyportmidi_6Output_Close, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_6Output_Close)}, - {__Pyx_NAMESTR("Abort"), (PyCFunction)__pyx_pf_11_pyportmidi_6Output_Abort, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_6Output_Abort)}, - {__Pyx_NAMESTR("Write"), (PyCFunction)__pyx_pf_11_pyportmidi_6Output_Write, METH_O, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_6Output_Write)}, - {__Pyx_NAMESTR("WriteShort"), (PyCFunction)__pyx_pf_11_pyportmidi_6Output_WriteShort, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_6Output_WriteShort)}, - {__Pyx_NAMESTR("WriteSysEx"), (PyCFunction)__pyx_pf_11_pyportmidi_6Output_WriteSysEx, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_6Output_WriteSysEx)}, - {0, 0, 0, 0} -}; - -static PyNumberMethods __pyx_tp_as_number_Output = { - 0, /*nb_add*/ - 0, /*nb_subtract*/ - 0, /*nb_multiply*/ - #if PY_MAJOR_VERSION < 3 - 0, /*nb_divide*/ - #endif - 0, /*nb_remainder*/ - 0, /*nb_divmod*/ - 0, /*nb_power*/ - 0, /*nb_negative*/ - 0, /*nb_positive*/ - 0, /*nb_absolute*/ - 0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ - #if PY_MAJOR_VERSION < 3 - 0, /*nb_coerce*/ - #endif - 0, /*nb_int*/ - #if PY_MAJOR_VERSION >= 3 - 0, /*reserved*/ - #else - 0, /*nb_long*/ - #endif - 0, /*nb_float*/ - #if PY_MAJOR_VERSION < 3 - 0, /*nb_oct*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*nb_hex*/ - #endif - 0, /*nb_inplace_add*/ - 0, /*nb_inplace_subtract*/ - 0, /*nb_inplace_multiply*/ - #if PY_MAJOR_VERSION < 3 - 0, /*nb_inplace_divide*/ - #endif - 0, /*nb_inplace_remainder*/ - 0, /*nb_inplace_power*/ - 0, /*nb_inplace_lshift*/ - 0, /*nb_inplace_rshift*/ - 0, /*nb_inplace_and*/ - 0, /*nb_inplace_xor*/ - 0, /*nb_inplace_or*/ - 0, /*nb_floor_divide*/ - 0, /*nb_true_divide*/ - 0, /*nb_inplace_floor_divide*/ - 0, /*nb_inplace_true_divide*/ - #if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & Py_TPFLAGS_HAVE_INDEX) - 0, /*nb_index*/ - #endif -}; - -static PySequenceMethods __pyx_tp_as_sequence_Output = { - 0, /*sq_length*/ - 0, /*sq_concat*/ - 0, /*sq_repeat*/ - 0, /*sq_item*/ - 0, /*sq_slice*/ - 0, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - 0, /*sq_contains*/ - 0, /*sq_inplace_concat*/ - 0, /*sq_inplace_repeat*/ -}; - -static PyMappingMethods __pyx_tp_as_mapping_Output = { - 0, /*mp_length*/ - 0, /*mp_subscript*/ - 0, /*mp_ass_subscript*/ -}; - -static PyBufferProcs __pyx_tp_as_buffer_Output = { - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getreadbuffer*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getwritebuffer*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getsegcount*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getcharbuffer*/ - #endif - #if PY_VERSION_HEX >= 0x02060000 - 0, /*bf_getbuffer*/ - #endif - #if PY_VERSION_HEX >= 0x02060000 - 0, /*bf_releasebuffer*/ - #endif -}; - -PyTypeObject __pyx_type_11_pyportmidi_Output = { - PyVarObject_HEAD_INIT(0, 0) - __Pyx_NAMESTR("_pyportmidi.Output"), /*tp_name*/ - sizeof(struct __pyx_obj_11_pyportmidi_Output), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - __pyx_tp_dealloc_11_pyportmidi_Output, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - &__pyx_tp_as_number_Output, /*tp_as_number*/ - &__pyx_tp_as_sequence_Output, /*tp_as_sequence*/ - &__pyx_tp_as_mapping_Output, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - &__pyx_tp_as_buffer_Output, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_NEWBUFFER, /*tp_flags*/ - __Pyx_DOCSTR("\nclass Output:\n define an output MIDI stream. Takes the form:\n x = pypm.Output(MidiOutputDevice, latency)\n latency is in ms.\n If latency = 0 then timestamps for output are ignored.\n "), /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - __pyx_methods_11_pyportmidi_Output, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - __pyx_pf_11_pyportmidi_6Output___init__, /*tp_init*/ - 0, /*tp_alloc*/ - __pyx_tp_new_11_pyportmidi_Output, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ - 0, /*tp_bases*/ - 0, /*tp_mro*/ - 0, /*tp_cache*/ - 0, /*tp_subclasses*/ - 0, /*tp_weaklist*/ - 0, /*tp_del*/ - #if PY_VERSION_HEX >= 0x02060000 - 0, /*tp_version_tag*/ - #endif -}; - -static PyObject *__pyx_tp_new_11_pyportmidi_Input(PyTypeObject *t, PyObject *a, PyObject *k) { - PyObject *o = (*t->tp_alloc)(t, 0); - if (!o) return 0; - return o; -} - -static void __pyx_tp_dealloc_11_pyportmidi_Input(PyObject *o) { - { - PyObject *etype, *eval, *etb; - PyErr_Fetch(&etype, &eval, &etb); - ++Py_REFCNT(o); - __pyx_pf_11_pyportmidi_5Input___dealloc__(o); - if (PyErr_Occurred()) PyErr_WriteUnraisable(o); - --Py_REFCNT(o); - PyErr_Restore(etype, eval, etb); - } - (*Py_TYPE(o)->tp_free)(o); -} - -static struct PyMethodDef __pyx_methods_11_pyportmidi_Input[] = { - {__Pyx_NAMESTR("_check_open"), (PyCFunction)__pyx_pf_11_pyportmidi_5Input__check_open, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_5Input__check_open)}, - {__Pyx_NAMESTR("Close"), (PyCFunction)__pyx_pf_11_pyportmidi_5Input_Close, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_5Input_Close)}, - {__Pyx_NAMESTR("SetFilter"), (PyCFunction)__pyx_pf_11_pyportmidi_5Input_SetFilter, METH_O, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_5Input_SetFilter)}, - {__Pyx_NAMESTR("SetChannelMask"), (PyCFunction)__pyx_pf_11_pyportmidi_5Input_SetChannelMask, METH_O, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_5Input_SetChannelMask)}, - {__Pyx_NAMESTR("Poll"), (PyCFunction)__pyx_pf_11_pyportmidi_5Input_Poll, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_5Input_Poll)}, - {__Pyx_NAMESTR("Read"), (PyCFunction)__pyx_pf_11_pyportmidi_5Input_Read, METH_O, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_5Input_Read)}, - {0, 0, 0, 0} -}; - -static PyNumberMethods __pyx_tp_as_number_Input = { - 0, /*nb_add*/ - 0, /*nb_subtract*/ - 0, /*nb_multiply*/ - #if PY_MAJOR_VERSION < 3 - 0, /*nb_divide*/ - #endif - 0, /*nb_remainder*/ - 0, /*nb_divmod*/ - 0, /*nb_power*/ - 0, /*nb_negative*/ - 0, /*nb_positive*/ - 0, /*nb_absolute*/ - 0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ - #if PY_MAJOR_VERSION < 3 - 0, /*nb_coerce*/ - #endif - 0, /*nb_int*/ - #if PY_MAJOR_VERSION >= 3 - 0, /*reserved*/ - #else - 0, /*nb_long*/ - #endif - 0, /*nb_float*/ - #if PY_MAJOR_VERSION < 3 - 0, /*nb_oct*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*nb_hex*/ - #endif - 0, /*nb_inplace_add*/ - 0, /*nb_inplace_subtract*/ - 0, /*nb_inplace_multiply*/ - #if PY_MAJOR_VERSION < 3 - 0, /*nb_inplace_divide*/ - #endif - 0, /*nb_inplace_remainder*/ - 0, /*nb_inplace_power*/ - 0, /*nb_inplace_lshift*/ - 0, /*nb_inplace_rshift*/ - 0, /*nb_inplace_and*/ - 0, /*nb_inplace_xor*/ - 0, /*nb_inplace_or*/ - 0, /*nb_floor_divide*/ - 0, /*nb_true_divide*/ - 0, /*nb_inplace_floor_divide*/ - 0, /*nb_inplace_true_divide*/ - #if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & Py_TPFLAGS_HAVE_INDEX) - 0, /*nb_index*/ - #endif -}; - -static PySequenceMethods __pyx_tp_as_sequence_Input = { - 0, /*sq_length*/ - 0, /*sq_concat*/ - 0, /*sq_repeat*/ - 0, /*sq_item*/ - 0, /*sq_slice*/ - 0, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - 0, /*sq_contains*/ - 0, /*sq_inplace_concat*/ - 0, /*sq_inplace_repeat*/ -}; - -static PyMappingMethods __pyx_tp_as_mapping_Input = { - 0, /*mp_length*/ - 0, /*mp_subscript*/ - 0, /*mp_ass_subscript*/ -}; - -static PyBufferProcs __pyx_tp_as_buffer_Input = { - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getreadbuffer*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getwritebuffer*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getsegcount*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getcharbuffer*/ - #endif - #if PY_VERSION_HEX >= 0x02060000 - 0, /*bf_getbuffer*/ - #endif - #if PY_VERSION_HEX >= 0x02060000 - 0, /*bf_releasebuffer*/ - #endif -}; - -PyTypeObject __pyx_type_11_pyportmidi_Input = { - PyVarObject_HEAD_INIT(0, 0) - __Pyx_NAMESTR("_pyportmidi.Input"), /*tp_name*/ - sizeof(struct __pyx_obj_11_pyportmidi_Input), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - __pyx_tp_dealloc_11_pyportmidi_Input, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - &__pyx_tp_as_number_Input, /*tp_as_number*/ - &__pyx_tp_as_sequence_Input, /*tp_as_sequence*/ - &__pyx_tp_as_mapping_Input, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - &__pyx_tp_as_buffer_Input, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_NEWBUFFER, /*tp_flags*/ - __Pyx_DOCSTR("\nclass Input:\n define an input MIDI stream. Takes the form:\n x = pypm.Input(MidiInputDevice)\n "), /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - __pyx_methods_11_pyportmidi_Input, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - __pyx_pf_11_pyportmidi_5Input___init__, /*tp_init*/ - 0, /*tp_alloc*/ - __pyx_tp_new_11_pyportmidi_Input, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ - 0, /*tp_bases*/ - 0, /*tp_mro*/ - 0, /*tp_cache*/ - 0, /*tp_subclasses*/ - 0, /*tp_weaklist*/ - 0, /*tp_del*/ - #if PY_VERSION_HEX >= 0x02060000 - 0, /*tp_version_tag*/ - #endif -}; - -static struct PyMethodDef __pyx_methods[] = { - {__Pyx_NAMESTR("Initialize"), (PyCFunction)__pyx_pf_11_pyportmidi_Initialize, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_Initialize)}, - {__Pyx_NAMESTR("Terminate"), (PyCFunction)__pyx_pf_11_pyportmidi_Terminate, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_Terminate)}, - {__Pyx_NAMESTR("GetDefaultInputDeviceID"), (PyCFunction)__pyx_pf_11_pyportmidi_GetDefaultInputDeviceID, METH_NOARGS, __Pyx_DOCSTR(0)}, - {__Pyx_NAMESTR("GetDefaultOutputDeviceID"), (PyCFunction)__pyx_pf_11_pyportmidi_GetDefaultOutputDeviceID, METH_NOARGS, __Pyx_DOCSTR(0)}, - {__Pyx_NAMESTR("CountDevices"), (PyCFunction)__pyx_pf_11_pyportmidi_CountDevices, METH_NOARGS, __Pyx_DOCSTR(0)}, - {__Pyx_NAMESTR("GetDeviceInfo"), (PyCFunction)__pyx_pf_11_pyportmidi_GetDeviceInfo, METH_O, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_GetDeviceInfo)}, - {__Pyx_NAMESTR("Time"), (PyCFunction)__pyx_pf_11_pyportmidi_Time, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_Time)}, - {__Pyx_NAMESTR("GetErrorText"), (PyCFunction)__pyx_pf_11_pyportmidi_GetErrorText, METH_O, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_GetErrorText)}, - {__Pyx_NAMESTR("Channel"), (PyCFunction)__pyx_pf_11_pyportmidi_Channel, METH_O, __Pyx_DOCSTR(__pyx_doc_11_pyportmidi_Channel)}, - {0, 0, 0, 0} -}; - -static void __pyx_init_filenames(void); /*proto*/ - -#if PY_MAJOR_VERSION >= 3 -static struct PyModuleDef __pyx_moduledef = { - PyModuleDef_HEAD_INIT, - __Pyx_NAMESTR("_pyportmidi"), - 0, /* m_doc */ - -1, /* m_size */ - __pyx_methods /* m_methods */, - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL /* m_free */ -}; -#endif - -static __Pyx_StringTabEntry __pyx_string_tab[] = { - {&__pyx_kp_s_1, __pyx_k_1, sizeof(__pyx_k_1), 0, 0, 1, 0}, - {&__pyx_kp_s_10, __pyx_k_10, sizeof(__pyx_k_10), 0, 0, 1, 0}, - {&__pyx_kp_s_11, __pyx_k_11, sizeof(__pyx_k_11), 0, 0, 1, 0}, - {&__pyx_kp_s_12, __pyx_k_12, sizeof(__pyx_k_12), 0, 0, 1, 0}, - {&__pyx_kp_s_13, __pyx_k_13, sizeof(__pyx_k_13), 0, 0, 1, 0}, - {&__pyx_kp_s_14, __pyx_k_14, sizeof(__pyx_k_14), 0, 0, 1, 0}, - {&__pyx_kp_s_15, __pyx_k_15, sizeof(__pyx_k_15), 0, 0, 1, 0}, - {&__pyx_kp_s_16, __pyx_k_16, sizeof(__pyx_k_16), 0, 0, 1, 0}, - {&__pyx_kp_s_17, __pyx_k_17, sizeof(__pyx_k_17), 0, 0, 1, 0}, - {&__pyx_n_s_18, __pyx_k_18, sizeof(__pyx_k_18), 0, 0, 1, 1}, - {&__pyx_n_s_19, __pyx_k_19, sizeof(__pyx_k_19), 0, 0, 1, 1}, - {&__pyx_kp_s_2, __pyx_k_2, sizeof(__pyx_k_2), 0, 0, 1, 0}, - {&__pyx_kp_u_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 1, 0, 0}, - {&__pyx_kp_u_21, __pyx_k_21, sizeof(__pyx_k_21), 0, 1, 0, 0}, - {&__pyx_kp_u_22, __pyx_k_22, sizeof(__pyx_k_22), 0, 1, 0, 0}, - {&__pyx_kp_u_23, __pyx_k_23, sizeof(__pyx_k_23), 0, 1, 0, 0}, - {&__pyx_kp_u_24, __pyx_k_24, sizeof(__pyx_k_24), 0, 1, 0, 0}, - {&__pyx_kp_u_25, __pyx_k_25, sizeof(__pyx_k_25), 0, 1, 0, 0}, - {&__pyx_kp_u_26, __pyx_k_26, sizeof(__pyx_k_26), 0, 1, 0, 0}, - {&__pyx_kp_u_27, __pyx_k_27, sizeof(__pyx_k_27), 0, 1, 0, 0}, - {&__pyx_kp_u_28, __pyx_k_28, sizeof(__pyx_k_28), 0, 1, 0, 0}, - {&__pyx_kp_u_29, __pyx_k_29, sizeof(__pyx_k_29), 0, 1, 0, 0}, - {&__pyx_kp_s_3, __pyx_k_3, sizeof(__pyx_k_3), 0, 0, 1, 0}, - {&__pyx_kp_u_30, __pyx_k_30, sizeof(__pyx_k_30), 0, 1, 0, 0}, - {&__pyx_kp_u_31, __pyx_k_31, sizeof(__pyx_k_31), 0, 1, 0, 0}, - {&__pyx_kp_u_32, __pyx_k_32, sizeof(__pyx_k_32), 0, 1, 0, 0}, - {&__pyx_kp_u_33, __pyx_k_33, sizeof(__pyx_k_33), 0, 1, 0, 0}, - {&__pyx_kp_u_34, __pyx_k_34, sizeof(__pyx_k_34), 0, 1, 0, 0}, - {&__pyx_kp_u_35, __pyx_k_35, sizeof(__pyx_k_35), 0, 1, 0, 0}, - {&__pyx_kp_u_36, __pyx_k_36, sizeof(__pyx_k_36), 0, 1, 0, 0}, - {&__pyx_kp_u_37, __pyx_k_37, sizeof(__pyx_k_37), 0, 1, 0, 0}, - {&__pyx_kp_s_4, __pyx_k_4, sizeof(__pyx_k_4), 0, 0, 1, 0}, - {&__pyx_kp_s_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 0, 1, 0}, - {&__pyx_kp_s_6, __pyx_k_6, sizeof(__pyx_k_6), 0, 0, 1, 0}, - {&__pyx_kp_s_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 0, 1, 0}, - {&__pyx_kp_s_8, __pyx_k_8, sizeof(__pyx_k_8), 0, 0, 1, 0}, - {&__pyx_kp_s_9, __pyx_k_9, sizeof(__pyx_k_9), 0, 0, 1, 0}, - {&__pyx_n_s__Abort, __pyx_k__Abort, sizeof(__pyx_k__Abort), 0, 0, 1, 1}, - {&__pyx_n_s__B, __pyx_k__B, sizeof(__pyx_k__B), 0, 0, 1, 1}, - {&__pyx_n_s__Channel, __pyx_k__Channel, sizeof(__pyx_k__Channel), 0, 0, 1, 1}, - {&__pyx_n_s__Close, __pyx_k__Close, sizeof(__pyx_k__Close), 0, 0, 1, 1}, - {&__pyx_n_s__Exception, __pyx_k__Exception, sizeof(__pyx_k__Exception), 0, 0, 1, 1}, - {&__pyx_n_s__FALSE, __pyx_k__FALSE, sizeof(__pyx_k__FALSE), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_ACTIVE, __pyx_k__FILT_ACTIVE, sizeof(__pyx_k__FILT_ACTIVE), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_AFTERTOUCH, __pyx_k__FILT_AFTERTOUCH, sizeof(__pyx_k__FILT_AFTERTOUCH), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_CLOCK, __pyx_k__FILT_CLOCK, sizeof(__pyx_k__FILT_CLOCK), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_CONTROL, __pyx_k__FILT_CONTROL, sizeof(__pyx_k__FILT_CONTROL), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_F9, __pyx_k__FILT_F9, sizeof(__pyx_k__FILT_F9), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_FD, __pyx_k__FILT_FD, sizeof(__pyx_k__FILT_FD), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_MTC, __pyx_k__FILT_MTC, sizeof(__pyx_k__FILT_MTC), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_NOTE, __pyx_k__FILT_NOTE, sizeof(__pyx_k__FILT_NOTE), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_PITCHBEND, __pyx_k__FILT_PITCHBEND, sizeof(__pyx_k__FILT_PITCHBEND), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_PLAY, __pyx_k__FILT_PLAY, sizeof(__pyx_k__FILT_PLAY), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_PROGRAM, __pyx_k__FILT_PROGRAM, sizeof(__pyx_k__FILT_PROGRAM), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_REALTIME, __pyx_k__FILT_REALTIME, sizeof(__pyx_k__FILT_REALTIME), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_RESET, __pyx_k__FILT_RESET, sizeof(__pyx_k__FILT_RESET), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_SONG_POSITION, __pyx_k__FILT_SONG_POSITION, sizeof(__pyx_k__FILT_SONG_POSITION), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_SONG_SELECT, __pyx_k__FILT_SONG_SELECT, sizeof(__pyx_k__FILT_SONG_SELECT), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_SYSEX, __pyx_k__FILT_SYSEX, sizeof(__pyx_k__FILT_SYSEX), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_TICK, __pyx_k__FILT_TICK, sizeof(__pyx_k__FILT_TICK), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_TUNE, __pyx_k__FILT_TUNE, sizeof(__pyx_k__FILT_TUNE), 0, 0, 1, 1}, - {&__pyx_n_s__FILT_UNDEFINED, __pyx_k__FILT_UNDEFINED, sizeof(__pyx_k__FILT_UNDEFINED), 0, 0, 1, 1}, - {&__pyx_n_s__GetDeviceInfo, __pyx_k__GetDeviceInfo, sizeof(__pyx_k__GetDeviceInfo), 0, 0, 1, 1}, - {&__pyx_n_s__GetErrorText, __pyx_k__GetErrorText, sizeof(__pyx_k__GetErrorText), 0, 0, 1, 1}, - {&__pyx_n_s__IndexError, __pyx_k__IndexError, sizeof(__pyx_k__IndexError), 0, 0, 1, 1}, - {&__pyx_n_s__Initialize, __pyx_k__Initialize, sizeof(__pyx_k__Initialize), 0, 0, 1, 1}, - {&__pyx_n_s__Input, __pyx_k__Input, sizeof(__pyx_k__Input), 0, 0, 1, 1}, - {&__pyx_n_s__InputDevice, __pyx_k__InputDevice, sizeof(__pyx_k__InputDevice), 0, 0, 1, 1}, - {&__pyx_n_s__Output, __pyx_k__Output, sizeof(__pyx_k__Output), 0, 0, 1, 1}, - {&__pyx_n_s__OutputDevice, __pyx_k__OutputDevice, sizeof(__pyx_k__OutputDevice), 0, 0, 1, 1}, - {&__pyx_n_s__Poll, __pyx_k__Poll, sizeof(__pyx_k__Poll), 0, 0, 1, 1}, - {&__pyx_n_s__Read, __pyx_k__Read, sizeof(__pyx_k__Read), 0, 0, 1, 1}, - {&__pyx_n_s__SetChannelMask, __pyx_k__SetChannelMask, sizeof(__pyx_k__SetChannelMask), 0, 0, 1, 1}, - {&__pyx_n_s__SetFilter, __pyx_k__SetFilter, sizeof(__pyx_k__SetFilter), 0, 0, 1, 1}, - {&__pyx_n_s__TRUE, __pyx_k__TRUE, sizeof(__pyx_k__TRUE), 0, 0, 1, 1}, - {&__pyx_n_s__Terminate, __pyx_k__Terminate, sizeof(__pyx_k__Terminate), 0, 0, 1, 1}, - {&__pyx_n_s__Time, __pyx_k__Time, sizeof(__pyx_k__Time), 0, 0, 1, 1}, - {&__pyx_n_s__Write, __pyx_k__Write, sizeof(__pyx_k__Write), 0, 0, 1, 1}, - {&__pyx_n_s__WriteShort, __pyx_k__WriteShort, sizeof(__pyx_k__WriteShort), 0, 0, 1, 1}, - {&__pyx_n_s__WriteSysEx, __pyx_k__WriteSysEx, sizeof(__pyx_k__WriteSysEx), 0, 0, 1, 1}, - {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1}, - {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1}, - {&__pyx_n_s____version__, __pyx_k____version__, sizeof(__pyx_k____version__), 0, 0, 1, 1}, - {&__pyx_n_s___aborted, __pyx_k___aborted, sizeof(__pyx_k___aborted), 0, 0, 1, 1}, - {&__pyx_n_s___check_open, __pyx_k___check_open, sizeof(__pyx_k___check_open), 0, 0, 1, 1}, - {&__pyx_n_s__array, __pyx_k__array, sizeof(__pyx_k__array), 0, 0, 1, 1}, - {&__pyx_n_s__buffersize, __pyx_k__buffersize, sizeof(__pyx_k__buffersize), 0, 0, 1, 1}, - {&__pyx_n_s__data1, __pyx_k__data1, sizeof(__pyx_k__data1), 0, 0, 1, 1}, - {&__pyx_n_s__data2, __pyx_k__data2, sizeof(__pyx_k__data2), 0, 0, 1, 1}, - {&__pyx_n_s__debug, __pyx_k__debug, sizeof(__pyx_k__debug), 0, 0, 1, 1}, - {&__pyx_n_s__i, __pyx_k__i, sizeof(__pyx_k__i), 0, 0, 1, 1}, - {&__pyx_n_s__input, __pyx_k__input, sizeof(__pyx_k__input), 0, 0, 1, 1}, - {&__pyx_n_s__interf, __pyx_k__interf, sizeof(__pyx_k__interf), 0, 0, 1, 1}, - {&__pyx_n_s__latency, __pyx_k__latency, sizeof(__pyx_k__latency), 0, 0, 1, 1}, - {&__pyx_n_s__message, __pyx_k__message, sizeof(__pyx_k__message), 0, 0, 1, 1}, - {&__pyx_n_s__midi, __pyx_k__midi, sizeof(__pyx_k__midi), 0, 0, 1, 1}, - {&__pyx_n_s__msg, __pyx_k__msg, sizeof(__pyx_k__msg), 0, 0, 1, 1}, - {&__pyx_n_s__name, __pyx_k__name, sizeof(__pyx_k__name), 0, 0, 1, 1}, - {&__pyx_n_s__opened, __pyx_k__opened, sizeof(__pyx_k__opened), 0, 0, 1, 1}, - {&__pyx_n_s__output, __pyx_k__output, sizeof(__pyx_k__output), 0, 0, 1, 1}, - {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1}, - {&__pyx_n_s__status, __pyx_k__status, sizeof(__pyx_k__status), 0, 0, 1, 1}, - {&__pyx_n_s__timestamp, __pyx_k__timestamp, sizeof(__pyx_k__timestamp), 0, 0, 1, 1}, - {&__pyx_n_s__tostring, __pyx_k__tostring, sizeof(__pyx_k__tostring), 0, 0, 1, 1}, - {&__pyx_n_s__when, __pyx_k__when, sizeof(__pyx_k__when), 0, 0, 1, 1}, - {0, 0, 0, 0, 0, 0, 0} -}; -static int __Pyx_InitCachedBuiltins(void) { - __pyx_builtin_Exception = __Pyx_GetName(__pyx_b, __pyx_n_s__Exception); if (!__pyx_builtin_Exception) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_builtin_IndexError = __Pyx_GetName(__pyx_b, __pyx_n_s__IndexError); if (!__pyx_builtin_IndexError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - return 0; - __pyx_L1_error:; - return -1; -} - -static int __Pyx_InitGlobals(void) { - if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_8 = PyInt_FromLong(8); if (unlikely(!__pyx_int_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_16 = PyInt_FromLong(16); if (unlikely(!__pyx_int_16)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x1 = PyInt_FromLong(0x1); if (unlikely(!__pyx_int_0x1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x2 = PyInt_FromLong(0x2); if (unlikely(!__pyx_int_0x2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x4 = PyInt_FromLong(0x4); if (unlikely(!__pyx_int_0x4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x8 = PyInt_FromLong(0x8); if (unlikely(!__pyx_int_0x8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x10 = PyInt_FromLong(0x10); if (unlikely(!__pyx_int_0x10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x20 = PyInt_FromLong(0x20); if (unlikely(!__pyx_int_0x20)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x30 = PyInt_FromLong(0x30); if (unlikely(!__pyx_int_0x30)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x40 = PyInt_FromLong(0x40); if (unlikely(!__pyx_int_0x40)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x7F = PyInt_FromLong(0x7F); if (unlikely(!__pyx_int_0x7F)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x80 = PyInt_FromLong(0x80); if (unlikely(!__pyx_int_0x80)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0xFF = PyInt_FromLong(0xFF); if (unlikely(!__pyx_int_0xFF)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_1024 = PyInt_FromLong(1024); if (unlikely(!__pyx_int_1024)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_4096 = PyInt_FromLong(4096); if (unlikely(!__pyx_int_4096)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x100 = PyInt_FromLong(0x100); if (unlikely(!__pyx_int_0x100)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x200 = PyInt_FromLong(0x200); if (unlikely(!__pyx_int_0x200)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x300 = PyInt_FromLong(0x300); if (unlikely(!__pyx_int_0x300)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x400 = PyInt_FromLong(0x400); if (unlikely(!__pyx_int_0x400)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x800 = PyInt_FromLong(0x800); if (unlikely(!__pyx_int_0x800)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x1000 = PyInt_FromLong(0x1000); if (unlikely(!__pyx_int_0x1000)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x2000 = PyInt_FromLong(0x2000); if (unlikely(!__pyx_int_0x2000)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x4000 = PyInt_FromLong(0x4000); if (unlikely(!__pyx_int_0x4000)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x8000 = PyInt_FromLong(0x8000); if (unlikely(!__pyx_int_0x8000)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0xFF00 = PyInt_FromLong(0xFF00); if (unlikely(!__pyx_int_0xFF00)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0x10000 = PyInt_FromLong(0x10000); if (unlikely(!__pyx_int_0x10000)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - __pyx_int_0xFF0000 = PyInt_FromLong(0xFF0000); if (unlikely(!__pyx_int_0xFF0000)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - return 0; - __pyx_L1_error:; - return -1; -} - -#if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC init_pyportmidi(void); /*proto*/ -PyMODINIT_FUNC init_pyportmidi(void) -#else -PyMODINIT_FUNC PyInit__pyportmidi(void); /*proto*/ -PyMODINIT_FUNC PyInit__pyportmidi(void) -#endif -{ - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - #if CYTHON_REFNANNY - void* __pyx_refnanny = NULL; - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); - if (!__Pyx_RefNanny) { - PyErr_Clear(); - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); - if (!__Pyx_RefNanny) - Py_FatalError("failed to import 'refnanny' module"); - } - __pyx_refnanny = __Pyx_RefNanny->SetupContext("PyMODINIT_FUNC PyInit__pyportmidi(void)", __LINE__, __FILE__); - #endif - __pyx_init_filenames(); - __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - #if PY_MAJOR_VERSION < 3 - __pyx_empty_bytes = PyString_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - #else - __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - #endif - /*--- Library function declarations ---*/ - /*--- Threads initialization code ---*/ - #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - #ifdef WITH_THREAD /* Python build with threading support? */ - PyEval_InitThreads(); - #endif - #endif - /*--- Module creation code ---*/ - #if PY_MAJOR_VERSION < 3 - __pyx_m = Py_InitModule4(__Pyx_NAMESTR("_pyportmidi"), __pyx_methods, 0, 0, PYTHON_API_VERSION); - #else - __pyx_m = PyModule_Create(&__pyx_moduledef); - #endif - if (!__pyx_m) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - #if PY_MAJOR_VERSION < 3 - Py_INCREF(__pyx_m); - #endif - __pyx_b = PyImport_AddModule(__Pyx_NAMESTR(__Pyx_BUILTIN_MODULE_NAME)); - if (!__pyx_b) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - if (__Pyx_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - /*--- Initialize various global constants etc. ---*/ - if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - if (__pyx_module_is_main__pyportmidi) { - if (__Pyx_SetAttrString(__pyx_m, "__name__", __pyx_n_s____main__) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - } - /*--- Builtin init code ---*/ - if (unlikely(__Pyx_InitCachedBuiltins() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /*--- Global init code ---*/ - /*--- Function export code ---*/ - /*--- Type init code ---*/ - if (PyType_Ready(&__pyx_type_11_pyportmidi_Output) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - if (__Pyx_SetAttrString(__pyx_m, "Output", (PyObject *)&__pyx_type_11_pyportmidi_Output) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_ptype_11_pyportmidi_Output = &__pyx_type_11_pyportmidi_Output; - if (PyType_Ready(&__pyx_type_11_pyportmidi_Input) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 394; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - if (__Pyx_SetAttrString(__pyx_m, "Input", (PyObject *)&__pyx_type_11_pyportmidi_Input) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 394; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_ptype_11_pyportmidi_Input = &__pyx_type_11_pyportmidi_Input; - /*--- Type import code ---*/ - /*--- Function import code ---*/ - /*--- Execution code ---*/ - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":7 - * # harrison@media.mit.edu - * # written in Pyrex - * __version__="0.07" # <<<<<<<<<<<<<< - * - * import array - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s____version__, ((PyObject *)__pyx_kp_s_17)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":9 - * __version__="0.07" - * - * import array # <<<<<<<<<<<<<< - * - * # CHANGES: - */ - __pyx_t_1 = __Pyx_Import(((PyObject *)__pyx_n_s__array), 0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__array, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":108 - * PtTimestamp Pt_Time() - * - * FILT_ACTIVE=0x1 # <<<<<<<<<<<<<< - * FILT_SYSEX=0x2 - * FILT_CLOCK=0x4 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_ACTIVE, __pyx_int_0x1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":109 - * - * FILT_ACTIVE=0x1 - * FILT_SYSEX=0x2 # <<<<<<<<<<<<<< - * FILT_CLOCK=0x4 - * FILT_PLAY=0x8 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_SYSEX, __pyx_int_0x2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":110 - * FILT_ACTIVE=0x1 - * FILT_SYSEX=0x2 - * FILT_CLOCK=0x4 # <<<<<<<<<<<<<< - * FILT_PLAY=0x8 - * FILT_F9=0x10 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_CLOCK, __pyx_int_0x4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":111 - * FILT_SYSEX=0x2 - * FILT_CLOCK=0x4 - * FILT_PLAY=0x8 # <<<<<<<<<<<<<< - * FILT_F9=0x10 - * FILT_TICK=0x10 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_PLAY, __pyx_int_0x8) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":112 - * FILT_CLOCK=0x4 - * FILT_PLAY=0x8 - * FILT_F9=0x10 # <<<<<<<<<<<<<< - * FILT_TICK=0x10 - * FILT_FD=0x20 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_F9, __pyx_int_0x10) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":113 - * FILT_PLAY=0x8 - * FILT_F9=0x10 - * FILT_TICK=0x10 # <<<<<<<<<<<<<< - * FILT_FD=0x20 - * FILT_UNDEFINED=0x30 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_TICK, __pyx_int_0x10) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":114 - * FILT_F9=0x10 - * FILT_TICK=0x10 - * FILT_FD=0x20 # <<<<<<<<<<<<<< - * FILT_UNDEFINED=0x30 - * FILT_RESET=0x40 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_FD, __pyx_int_0x20) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":115 - * FILT_TICK=0x10 - * FILT_FD=0x20 - * FILT_UNDEFINED=0x30 # <<<<<<<<<<<<<< - * FILT_RESET=0x40 - * FILT_REALTIME=0x7F - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_UNDEFINED, __pyx_int_0x30) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":116 - * FILT_FD=0x20 - * FILT_UNDEFINED=0x30 - * FILT_RESET=0x40 # <<<<<<<<<<<<<< - * FILT_REALTIME=0x7F - * FILT_NOTE=0x80 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_RESET, __pyx_int_0x40) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":117 - * FILT_UNDEFINED=0x30 - * FILT_RESET=0x40 - * FILT_REALTIME=0x7F # <<<<<<<<<<<<<< - * FILT_NOTE=0x80 - * FILT_CHANNEL_AFTERTOUCH=0x100 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_REALTIME, __pyx_int_0x7F) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":118 - * FILT_RESET=0x40 - * FILT_REALTIME=0x7F - * FILT_NOTE=0x80 # <<<<<<<<<<<<<< - * FILT_CHANNEL_AFTERTOUCH=0x100 - * FILT_POLY_AFTERTOUCH=0x200 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_NOTE, __pyx_int_0x80) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 118; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":119 - * FILT_REALTIME=0x7F - * FILT_NOTE=0x80 - * FILT_CHANNEL_AFTERTOUCH=0x100 # <<<<<<<<<<<<<< - * FILT_POLY_AFTERTOUCH=0x200 - * FILT_AFTERTOUCH=0x300 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_18, __pyx_int_0x100) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":120 - * FILT_NOTE=0x80 - * FILT_CHANNEL_AFTERTOUCH=0x100 - * FILT_POLY_AFTERTOUCH=0x200 # <<<<<<<<<<<<<< - * FILT_AFTERTOUCH=0x300 - * FILT_PROGRAM=0x400 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_19, __pyx_int_0x200) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":121 - * FILT_CHANNEL_AFTERTOUCH=0x100 - * FILT_POLY_AFTERTOUCH=0x200 - * FILT_AFTERTOUCH=0x300 # <<<<<<<<<<<<<< - * FILT_PROGRAM=0x400 - * FILT_CONTROL=0x800 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_AFTERTOUCH, __pyx_int_0x300) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 121; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":122 - * FILT_POLY_AFTERTOUCH=0x200 - * FILT_AFTERTOUCH=0x300 - * FILT_PROGRAM=0x400 # <<<<<<<<<<<<<< - * FILT_CONTROL=0x800 - * FILT_PITCHBEND=0x1000 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_PROGRAM, __pyx_int_0x400) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":123 - * FILT_AFTERTOUCH=0x300 - * FILT_PROGRAM=0x400 - * FILT_CONTROL=0x800 # <<<<<<<<<<<<<< - * FILT_PITCHBEND=0x1000 - * FILT_MTC=0x2000 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_CONTROL, __pyx_int_0x800) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":124 - * FILT_PROGRAM=0x400 - * FILT_CONTROL=0x800 - * FILT_PITCHBEND=0x1000 # <<<<<<<<<<<<<< - * FILT_MTC=0x2000 - * FILT_SONG_POSITION=0x4000 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_PITCHBEND, __pyx_int_0x1000) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 124; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":125 - * FILT_CONTROL=0x800 - * FILT_PITCHBEND=0x1000 - * FILT_MTC=0x2000 # <<<<<<<<<<<<<< - * FILT_SONG_POSITION=0x4000 - * FILT_SONG_SELECT=0x8000 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_MTC, __pyx_int_0x2000) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 125; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":126 - * FILT_PITCHBEND=0x1000 - * FILT_MTC=0x2000 - * FILT_SONG_POSITION=0x4000 # <<<<<<<<<<<<<< - * FILT_SONG_SELECT=0x8000 - * FILT_TUNE=0x10000 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_SONG_POSITION, __pyx_int_0x4000) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":127 - * FILT_MTC=0x2000 - * FILT_SONG_POSITION=0x4000 - * FILT_SONG_SELECT=0x8000 # <<<<<<<<<<<<<< - * FILT_TUNE=0x10000 - * FALSE=0 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_SONG_SELECT, __pyx_int_0x8000) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":128 - * FILT_SONG_POSITION=0x4000 - * FILT_SONG_SELECT=0x8000 - * FILT_TUNE=0x10000 # <<<<<<<<<<<<<< - * FALSE=0 - * TRUE=1 - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FILT_TUNE, __pyx_int_0x10000) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":129 - * FILT_SONG_SELECT=0x8000 - * FILT_TUNE=0x10000 - * FALSE=0 # <<<<<<<<<<<<<< - * TRUE=1 - * - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__FALSE, __pyx_int_0) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":130 - * FILT_TUNE=0x10000 - * FALSE=0 - * TRUE=1 # <<<<<<<<<<<<<< - * - * def Initialize(): - */ - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__TRUE, __pyx_int_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - - /* "/Users/rene/dev/portmedia/portmedia/portmidi/trunk/pm_python/pyportmidi/_pyportmidi.pyx":1 - * # pyPortMidi # <<<<<<<<<<<<<< - * # Python bindings for PortMidi - * # John Harrison - */ - __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Initialize); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_GetAttrString(__pyx_t_2, "__doc__"); - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_20), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Terminate); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_21), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__GetDeviceInfo); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_GetAttrString(__pyx_t_2, "__doc__"); - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_22), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Time); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_23), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__GetErrorText); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_GetAttrString(__pyx_t_2, "__doc__"); - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_24), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Channel); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_25), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Output); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s___check_open); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_26), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Output); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__Close); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_27), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Output); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__Abort); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_28), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Output); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__Write); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_29), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Output); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__WriteShort); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_30), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Output); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__WriteSysEx); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_31), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Input); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s___check_open); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_32), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Input); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__Close); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_33), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Input); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__SetFilter); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_34), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Input); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__SetChannelMask); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_35), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Input); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__Poll); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_36), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyObject_GetAttr(__pyx_m, __pyx_n_s__Input); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__Read); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_GetAttrString(__pyx_t_3, "__doc__"); - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_kp_u_37), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_1)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - if (__pyx_m) { - __Pyx_AddTraceback("init _pyportmidi"); - Py_DECREF(__pyx_m); __pyx_m = 0; - } else if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_ImportError, "init _pyportmidi"); - } - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - #if PY_MAJOR_VERSION < 3 - return; - #else - return __pyx_m; - #endif -} - -static const char *__pyx_filenames[] = { - "_pyportmidi.pyx", -}; - -/* Runtime support code */ - -static void __pyx_init_filenames(void) { - __pyx_f = __pyx_filenames; -} - -static void __Pyx_RaiseDoubleKeywordsError( - const char* func_name, - PyObject* kw_name) -{ - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION >= 3 - "%s() got multiple values for keyword argument '%U'", func_name, kw_name); - #else - "%s() got multiple values for keyword argument '%s'", func_name, - PyString_AS_STRING(kw_name)); - #endif -} - -static void __Pyx_RaiseArgtupleInvalid( - const char* func_name, - int exact, - Py_ssize_t num_min, - Py_ssize_t num_max, - Py_ssize_t num_found) -{ - Py_ssize_t num_expected; - const char *number, *more_or_less; - - if (num_found < num_min) { - num_expected = num_min; - more_or_less = "at least"; - } else { - num_expected = num_max; - more_or_less = "at most"; - } - if (exact) { - more_or_less = "exactly"; - } - number = (num_expected == 1) ? "" : "s"; - PyErr_Format(PyExc_TypeError, - #if PY_VERSION_HEX < 0x02050000 - "%s() takes %s %d positional argument%s (%d given)", - #else - "%s() takes %s %zd positional argument%s (%zd given)", - #endif - func_name, more_or_less, num_expected, number, num_found); -} - -static int __Pyx_ParseOptionalKeywords( - PyObject *kwds, - PyObject **argnames[], - PyObject *kwds2, - PyObject *values[], - Py_ssize_t num_pos_args, - const char* function_name) -{ - PyObject *key = 0, *value = 0; - Py_ssize_t pos = 0; - PyObject*** name; - PyObject*** first_kw_arg = argnames + num_pos_args; - - while (PyDict_Next(kwds, &pos, &key, &value)) { - name = first_kw_arg; - while (*name && (**name != key)) name++; - if (*name) { - values[name-argnames] = value; - } else { - #if PY_MAJOR_VERSION < 3 - if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) { - #else - if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) { - #endif - goto invalid_keyword_type; - } else { - for (name = first_kw_arg; *name; name++) { - #if PY_MAJOR_VERSION >= 3 - if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) && - PyUnicode_Compare(**name, key) == 0) break; - #else - if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) && - _PyString_Eq(**name, key)) break; - #endif - } - if (*name) { - values[name-argnames] = value; - } else { - /* unexpected keyword found */ - for (name=argnames; name != first_kw_arg; name++) { - if (**name == key) goto arg_passed_twice; - #if PY_MAJOR_VERSION >= 3 - if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) && - PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice; - #else - if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) && - _PyString_Eq(**name, key)) goto arg_passed_twice; - #endif - } - if (kwds2) { - if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; - } else { - goto invalid_keyword; - } - } - } - } - } - return 0; -arg_passed_twice: - __Pyx_RaiseDoubleKeywordsError(function_name, **name); - goto bad; -invalid_keyword_type: - PyErr_Format(PyExc_TypeError, - "%s() keywords must be strings", function_name); - goto bad; -invalid_keyword: - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION < 3 - "%s() got an unexpected keyword argument '%s'", - function_name, PyString_AsString(key)); - #else - "%s() got an unexpected keyword argument '%U'", - function_name, key); - #endif -bad: - return -1; -} - - -static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) { - PyObject *__import__ = 0; - PyObject *empty_list = 0; - PyObject *module = 0; - PyObject *global_dict = 0; - PyObject *empty_dict = 0; - PyObject *list; - __import__ = __Pyx_GetAttrString(__pyx_b, "__import__"); - if (!__import__) - goto bad; - if (from_list) - list = from_list; - else { - empty_list = PyList_New(0); - if (!empty_list) - goto bad; - list = empty_list; - } - global_dict = PyModule_GetDict(__pyx_m); - if (!global_dict) - goto bad; - empty_dict = PyDict_New(); - if (!empty_dict) - goto bad; - module = PyObject_CallFunctionObjArgs(__import__, - name, global_dict, empty_dict, list, NULL); -bad: - Py_XDECREF(empty_list); - Py_XDECREF(__import__); - Py_XDECREF(empty_dict); - return module; -} - -static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_PmDeviceID(PmDeviceID val) { - const PmDeviceID neg_one = (PmDeviceID)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(PmDeviceID) < sizeof(long)) { - return PyInt_FromLong((long)val); - } else if (sizeof(PmDeviceID) == sizeof(long)) { - if (is_unsigned) - return PyLong_FromUnsignedLong((unsigned long)val); - else - return PyInt_FromLong((long)val); - } else { /* (sizeof(PmDeviceID) > sizeof(long)) */ - if (is_unsigned) - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val); - else - return PyLong_FromLongLong((PY_LONG_LONG)val); - } -} - -static CYTHON_INLINE PmDeviceID __Pyx_PyInt_from_py_PmDeviceID(PyObject* x) { - const PmDeviceID neg_one = (PmDeviceID)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(PmDeviceID) == sizeof(char)) { - if (is_unsigned) - return (PmDeviceID)__Pyx_PyInt_AsUnsignedChar(x); - else - return (PmDeviceID)__Pyx_PyInt_AsSignedChar(x); - } else if (sizeof(PmDeviceID) == sizeof(short)) { - if (is_unsigned) - return (PmDeviceID)__Pyx_PyInt_AsUnsignedShort(x); - else - return (PmDeviceID)__Pyx_PyInt_AsSignedShort(x); - } else if (sizeof(PmDeviceID) == sizeof(int)) { - if (is_unsigned) - return (PmDeviceID)__Pyx_PyInt_AsUnsignedInt(x); - else - return (PmDeviceID)__Pyx_PyInt_AsSignedInt(x); - } else if (sizeof(PmDeviceID) == sizeof(long)) { - if (is_unsigned) - return (PmDeviceID)__Pyx_PyInt_AsUnsignedLong(x); - else - return (PmDeviceID)__Pyx_PyInt_AsSignedLong(x); - } else if (sizeof(PmDeviceID) == sizeof(PY_LONG_LONG)) { - if (is_unsigned) - return (PmDeviceID)__Pyx_PyInt_AsUnsignedLongLong(x); - else - return (PmDeviceID)__Pyx_PyInt_AsSignedLongLong(x); -#if 0 - } else if (sizeof(PmDeviceID) > sizeof(short) && - sizeof(PmDeviceID) < sizeof(int)) { /* __int32 ILP64 ? */ - if (is_unsigned) - return (PmDeviceID)__Pyx_PyInt_AsUnsignedInt(x); - else - return (PmDeviceID)__Pyx_PyInt_AsSignedInt(x); -#endif - } - PyErr_SetString(PyExc_TypeError, "PmDeviceID"); - return (PmDeviceID)-1; -} - -static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_PtTimestamp(PtTimestamp val) { - const PtTimestamp neg_one = (PtTimestamp)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(PtTimestamp) < sizeof(long)) { - return PyInt_FromLong((long)val); - } else if (sizeof(PtTimestamp) == sizeof(long)) { - if (is_unsigned) - return PyLong_FromUnsignedLong((unsigned long)val); - else - return PyInt_FromLong((long)val); - } else { /* (sizeof(PtTimestamp) > sizeof(long)) */ - if (is_unsigned) - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val); - else - return PyLong_FromLongLong((PY_LONG_LONG)val); - } -} - -#if PY_MAJOR_VERSION < 3 -static PyObject *__Pyx_GetStdout(void) { - PyObject *f = PySys_GetObject((char *)"stdout"); - if (!f) { - PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout"); - } - return f; -} - -static int __Pyx_Print(PyObject *arg_tuple, int newline) { - PyObject *f; - PyObject* v; - int i; - - if (!(f = __Pyx_GetStdout())) - return -1; - for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) { - if (PyFile_SoftSpace(f, 1)) { - if (PyFile_WriteString(" ", f) < 0) - return -1; - } - v = PyTuple_GET_ITEM(arg_tuple, i); - if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) - return -1; - if (PyString_Check(v)) { - char *s = PyString_AsString(v); - Py_ssize_t len = PyString_Size(v); - if (len > 0 && - isspace(Py_CHARMASK(s[len-1])) && - s[len-1] != ' ') - PyFile_SoftSpace(f, 0); - } - } - if (newline) { - if (PyFile_WriteString("\n", f) < 0) - return -1; - PyFile_SoftSpace(f, 0); - } - return 0; -} - -#else /* Python 3 has a print function */ - -static int __Pyx_Print(PyObject *arg_tuple, int newline) { - PyObject* kwargs = 0; - PyObject* result = 0; - PyObject* end_string; - if (!__pyx_print) { - __pyx_print = __Pyx_GetAttrString(__pyx_b, "print"); - if (!__pyx_print) - return -1; - } - if (!newline) { - if (!__pyx_print_kwargs) { - __pyx_print_kwargs = PyDict_New(); - if (!__pyx_print_kwargs) - return -1; - end_string = PyUnicode_FromStringAndSize(" ", 1); - if (!end_string) - return -1; - if (PyDict_SetItemString(__pyx_print_kwargs, "end", end_string) < 0) { - Py_DECREF(end_string); - return -1; - } - Py_DECREF(end_string); - } - kwargs = __pyx_print_kwargs; - } - result = PyObject_Call(__pyx_print, arg_tuple, kwargs); - if (!result) - return -1; - Py_DECREF(result); - return 0; -} - -#endif - -#if PY_MAJOR_VERSION < 3 - -static int __Pyx_PrintOne(PyObject *o) { - PyObject *f; - if (!(f = __Pyx_GetStdout())) - return -1; - if (PyFile_SoftSpace(f, 0)) { - if (PyFile_WriteString(" ", f) < 0) - return -1; - } - if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0) - return -1; - if (PyFile_WriteString("\n", f) < 0) - return -1; - return 0; - /* the line below is just to avoid compiler - * compiler warnings about unused functions */ - return __Pyx_Print(NULL, 0); -} - -#else /* Python 3 has a print function */ - -static int __Pyx_PrintOne(PyObject *o) { - int res; - PyObject* arg_tuple = PyTuple_New(1); - if (unlikely(!arg_tuple)) - return -1; - Py_INCREF(o); - PyTuple_SET_ITEM(arg_tuple, 0, o); - res = __Pyx_Print(arg_tuple, 1); - Py_DECREF(arg_tuple); - return res; -} - -#endif - -static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) { - PyObject *result; - result = PyObject_GetAttr(dict, name); - if (!result) - PyErr_SetObject(PyExc_NameError, name); - return result; -} - -static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) { - PyObject *tmp_type, *tmp_value, *tmp_tb; - PyThreadState *tstate = PyThreadState_GET(); - - tmp_type = tstate->curexc_type; - tmp_value = tstate->curexc_value; - tmp_tb = tstate->curexc_traceback; - tstate->curexc_type = type; - tstate->curexc_value = value; - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); -} - -static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) { - PyThreadState *tstate = PyThreadState_GET(); - *type = tstate->curexc_type; - *value = tstate->curexc_value; - *tb = tstate->curexc_traceback; - - tstate->curexc_type = 0; - tstate->curexc_value = 0; - tstate->curexc_traceback = 0; -} - - -#if PY_MAJOR_VERSION < 3 -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { - Py_XINCREF(type); - Py_XINCREF(value); - Py_XINCREF(tb); - /* First, check the traceback argument, replacing None with NULL. */ - if (tb == Py_None) { - Py_DECREF(tb); - tb = 0; - } - else if (tb != NULL && !PyTraceBack_Check(tb)) { - PyErr_SetString(PyExc_TypeError, - "raise: arg 3 must be a traceback or None"); - goto raise_error; - } - /* Next, replace a missing value with None */ - if (value == NULL) { - value = Py_None; - Py_INCREF(value); - } - #if PY_VERSION_HEX < 0x02050000 - if (!PyClass_Check(type)) - #else - if (!PyType_Check(type)) - #endif - { - /* Raising an instance. The value should be a dummy. */ - if (value != Py_None) { - PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); - goto raise_error; - } - /* Normalize to raise <class>, <instance> */ - Py_DECREF(value); - value = type; - #if PY_VERSION_HEX < 0x02050000 - if (PyInstance_Check(type)) { - type = (PyObject*) ((PyInstanceObject*)type)->in_class; - Py_INCREF(type); - } - else { - type = 0; - PyErr_SetString(PyExc_TypeError, - "raise: exception must be an old-style class or instance"); - goto raise_error; - } - #else - type = (PyObject*) Py_TYPE(type); - Py_INCREF(type); - if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { - PyErr_SetString(PyExc_TypeError, - "raise: exception class must be a subclass of BaseException"); - goto raise_error; - } - #endif - } - - __Pyx_ErrRestore(type, value, tb); - return; -raise_error: - Py_XDECREF(value); - Py_XDECREF(type); - Py_XDECREF(tb); - return; -} - -#else /* Python 3+ */ - -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { - if (tb == Py_None) { - tb = 0; - } else if (tb && !PyTraceBack_Check(tb)) { - PyErr_SetString(PyExc_TypeError, - "raise: arg 3 must be a traceback or None"); - goto bad; - } - if (value == Py_None) - value = 0; - - if (PyExceptionInstance_Check(type)) { - if (value) { - PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); - goto bad; - } - value = type; - type = (PyObject*) Py_TYPE(value); - } else if (!PyExceptionClass_Check(type)) { - PyErr_SetString(PyExc_TypeError, - "raise: exception class must be a subclass of BaseException"); - goto bad; - } - - PyErr_SetObject(type, value); - - if (tb) { - PyThreadState *tstate = PyThreadState_GET(); - PyObject* tmp_tb = tstate->curexc_traceback; - if (tb != tmp_tb) { - Py_INCREF(tb); - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_tb); - } - } - -bad: - return; -} -#endif - -static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_PmMessage(PmMessage val) { - const PmMessage neg_one = (PmMessage)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(PmMessage) < sizeof(long)) { - return PyInt_FromLong((long)val); - } else if (sizeof(PmMessage) == sizeof(long)) { - if (is_unsigned) - return PyLong_FromUnsignedLong((unsigned long)val); - else - return PyInt_FromLong((long)val); - } else { /* (sizeof(PmMessage) > sizeof(long)) */ - if (is_unsigned) - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val); - else - return PyLong_FromLongLong((PY_LONG_LONG)val); - } -} - -static CYTHON_INLINE PmMessage __Pyx_PyInt_from_py_PmMessage(PyObject* x) { - const PmMessage neg_one = (PmMessage)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(PmMessage) == sizeof(char)) { - if (is_unsigned) - return (PmMessage)__Pyx_PyInt_AsUnsignedChar(x); - else - return (PmMessage)__Pyx_PyInt_AsSignedChar(x); - } else if (sizeof(PmMessage) == sizeof(short)) { - if (is_unsigned) - return (PmMessage)__Pyx_PyInt_AsUnsignedShort(x); - else - return (PmMessage)__Pyx_PyInt_AsSignedShort(x); - } else if (sizeof(PmMessage) == sizeof(int)) { - if (is_unsigned) - return (PmMessage)__Pyx_PyInt_AsUnsignedInt(x); - else - return (PmMessage)__Pyx_PyInt_AsSignedInt(x); - } else if (sizeof(PmMessage) == sizeof(long)) { - if (is_unsigned) - return (PmMessage)__Pyx_PyInt_AsUnsignedLong(x); - else - return (PmMessage)__Pyx_PyInt_AsSignedLong(x); - } else if (sizeof(PmMessage) == sizeof(PY_LONG_LONG)) { - if (is_unsigned) - return (PmMessage)__Pyx_PyInt_AsUnsignedLongLong(x); - else - return (PmMessage)__Pyx_PyInt_AsSignedLongLong(x); -#if 0 - } else if (sizeof(PmMessage) > sizeof(short) && - sizeof(PmMessage) < sizeof(int)) { /* __int32 ILP64 ? */ - if (is_unsigned) - return (PmMessage)__Pyx_PyInt_AsUnsignedInt(x); - else - return (PmMessage)__Pyx_PyInt_AsSignedInt(x); -#endif - } - PyErr_SetString(PyExc_TypeError, "PmMessage"); - return (PmMessage)-1; -} - -static CYTHON_INLINE PmTimestamp __Pyx_PyInt_from_py_PmTimestamp(PyObject* x) { - const PmTimestamp neg_one = (PmTimestamp)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(PmTimestamp) == sizeof(char)) { - if (is_unsigned) - return (PmTimestamp)__Pyx_PyInt_AsUnsignedChar(x); - else - return (PmTimestamp)__Pyx_PyInt_AsSignedChar(x); - } else if (sizeof(PmTimestamp) == sizeof(short)) { - if (is_unsigned) - return (PmTimestamp)__Pyx_PyInt_AsUnsignedShort(x); - else - return (PmTimestamp)__Pyx_PyInt_AsSignedShort(x); - } else if (sizeof(PmTimestamp) == sizeof(int)) { - if (is_unsigned) - return (PmTimestamp)__Pyx_PyInt_AsUnsignedInt(x); - else - return (PmTimestamp)__Pyx_PyInt_AsSignedInt(x); - } else if (sizeof(PmTimestamp) == sizeof(long)) { - if (is_unsigned) - return (PmTimestamp)__Pyx_PyInt_AsUnsignedLong(x); - else - return (PmTimestamp)__Pyx_PyInt_AsSignedLong(x); - } else if (sizeof(PmTimestamp) == sizeof(PY_LONG_LONG)) { - if (is_unsigned) - return (PmTimestamp)__Pyx_PyInt_AsUnsignedLongLong(x); - else - return (PmTimestamp)__Pyx_PyInt_AsSignedLongLong(x); -#if 0 - } else if (sizeof(PmTimestamp) > sizeof(short) && - sizeof(PmTimestamp) < sizeof(int)) { /* __int32 ILP64 ? */ - if (is_unsigned) - return (PmTimestamp)__Pyx_PyInt_AsUnsignedInt(x); - else - return (PmTimestamp)__Pyx_PyInt_AsSignedInt(x); -#endif - } - PyErr_SetString(PyExc_TypeError, "PmTimestamp"); - return (PmTimestamp)-1; -} - -static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_PmTimestamp(PmTimestamp val) { - const PmTimestamp neg_one = (PmTimestamp)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(PmTimestamp) < sizeof(long)) { - return PyInt_FromLong((long)val); - } else if (sizeof(PmTimestamp) == sizeof(long)) { - if (is_unsigned) - return PyLong_FromUnsignedLong((unsigned long)val); - else - return PyInt_FromLong((long)val); - } else { /* (sizeof(PmTimestamp) > sizeof(long)) */ - if (is_unsigned) - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val); - else - return PyLong_FromLongLong((PY_LONG_LONG)val); - } -} - -static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject* x) { - const unsigned char neg_one = (unsigned char)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(unsigned char) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(unsigned char)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to unsigned char" : - "value too large to convert to unsigned char"); - } - return (unsigned char)-1; - } - return (unsigned char)val; - } - return (unsigned char)__Pyx_PyInt_AsUnsignedLong(x); -} - -static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject* x) { - const unsigned short neg_one = (unsigned short)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(unsigned short) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(unsigned short)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to unsigned short" : - "value too large to convert to unsigned short"); - } - return (unsigned short)-1; - } - return (unsigned short)val; - } - return (unsigned short)__Pyx_PyInt_AsUnsignedLong(x); -} - -static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject* x) { - const unsigned int neg_one = (unsigned int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(unsigned int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(unsigned int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to unsigned int" : - "value too large to convert to unsigned int"); - } - return (unsigned int)-1; - } - return (unsigned int)val; - } - return (unsigned int)__Pyx_PyInt_AsUnsignedLong(x); -} - -static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject* x) { - const char neg_one = (char)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(char) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(char)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to char" : - "value too large to convert to char"); - } - return (char)-1; - } - return (char)val; - } - return (char)__Pyx_PyInt_AsLong(x); -} - -static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject* x) { - const short neg_one = (short)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(short) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(short)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to short" : - "value too large to convert to short"); - } - return (short)-1; - } - return (short)val; - } - return (short)__Pyx_PyInt_AsLong(x); -} - -static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject* x) { - const int neg_one = (int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to int" : - "value too large to convert to int"); - } - return (int)-1; - } - return (int)val; - } - return (int)__Pyx_PyInt_AsLong(x); -} - -static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject* x) { - const signed char neg_one = (signed char)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(signed char) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(signed char)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to signed char" : - "value too large to convert to signed char"); - } - return (signed char)-1; - } - return (signed char)val; - } - return (signed char)__Pyx_PyInt_AsSignedLong(x); -} - -static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject* x) { - const signed short neg_one = (signed short)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(signed short) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(signed short)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to signed short" : - "value too large to convert to signed short"); - } - return (signed short)-1; - } - return (signed short)val; - } - return (signed short)__Pyx_PyInt_AsSignedLong(x); -} - -static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject* x) { - const signed int neg_one = (signed int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(signed int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(signed int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to signed int" : - "value too large to convert to signed int"); - } - return (signed int)-1; - } - return (signed int)val; - } - return (signed int)__Pyx_PyInt_AsSignedLong(x); -} - -static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject* x) { - const unsigned long neg_one = (unsigned long)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned long"); - return (unsigned long)-1; - } - return (unsigned long)val; - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned long"); - return (unsigned long)-1; - } - return PyLong_AsUnsignedLong(x); - } else { - return PyLong_AsLong(x); - } - } else { - unsigned long val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (unsigned long)-1; - val = __Pyx_PyInt_AsUnsignedLong(tmp); - Py_DECREF(tmp); - return val; - } -} - -static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject* x) { - const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned PY_LONG_LONG"); - return (unsigned PY_LONG_LONG)-1; - } - return (unsigned PY_LONG_LONG)val; - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned PY_LONG_LONG"); - return (unsigned PY_LONG_LONG)-1; - } - return PyLong_AsUnsignedLongLong(x); - } else { - return PyLong_AsLongLong(x); - } - } else { - unsigned PY_LONG_LONG val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (unsigned PY_LONG_LONG)-1; - val = __Pyx_PyInt_AsUnsignedLongLong(tmp); - Py_DECREF(tmp); - return val; - } -} - -static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject* x) { - const long neg_one = (long)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to long"); - return (long)-1; - } - return (long)val; - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to long"); - return (long)-1; - } - return PyLong_AsUnsignedLong(x); - } else { - return PyLong_AsLong(x); - } - } else { - long val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (long)-1; - val = __Pyx_PyInt_AsLong(tmp); - Py_DECREF(tmp); - return val; - } -} - -static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject* x) { - const PY_LONG_LONG neg_one = (PY_LONG_LONG)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to PY_LONG_LONG"); - return (PY_LONG_LONG)-1; - } - return (PY_LONG_LONG)val; - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to PY_LONG_LONG"); - return (PY_LONG_LONG)-1; - } - return PyLong_AsUnsignedLongLong(x); - } else { - return PyLong_AsLongLong(x); - } - } else { - PY_LONG_LONG val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (PY_LONG_LONG)-1; - val = __Pyx_PyInt_AsLongLong(tmp); - Py_DECREF(tmp); - return val; - } -} - -static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject* x) { - const signed long neg_one = (signed long)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed long"); - return (signed long)-1; - } - return (signed long)val; - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed long"); - return (signed long)-1; - } - return PyLong_AsUnsignedLong(x); - } else { - return PyLong_AsLong(x); - } - } else { - signed long val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (signed long)-1; - val = __Pyx_PyInt_AsSignedLong(tmp); - Py_DECREF(tmp); - return val; - } -} - -static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject* x) { - const signed PY_LONG_LONG neg_one = (signed PY_LONG_LONG)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed PY_LONG_LONG"); - return (signed PY_LONG_LONG)-1; - } - return (signed PY_LONG_LONG)val; - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed PY_LONG_LONG"); - return (signed PY_LONG_LONG)-1; - } - return PyLong_AsUnsignedLongLong(x); - } else { - return PyLong_AsLongLong(x); - } - } else { - signed PY_LONG_LONG val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (signed PY_LONG_LONG)-1; - val = __Pyx_PyInt_AsSignedLongLong(tmp); - Py_DECREF(tmp); - return val; - } -} - -#include "compile.h" -#include "frameobject.h" -#include "traceback.h" - -static void __Pyx_AddTraceback(const char *funcname) { - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; - PyObject *py_globals = 0; - PyCodeObject *py_code = 0; - PyFrameObject *py_frame = 0; - - #if PY_MAJOR_VERSION < 3 - py_srcfile = PyString_FromString(__pyx_filename); - #else - py_srcfile = PyUnicode_FromString(__pyx_filename); - #endif - if (!py_srcfile) goto bad; - if (__pyx_clineno) { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno); - #else - py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno); - #endif - } - else { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromString(funcname); - #else - py_funcname = PyUnicode_FromString(funcname); - #endif - } - if (!py_funcname) goto bad; - py_globals = PyModule_GetDict(__pyx_m); - if (!py_globals) goto bad; - py_code = PyCode_New( - 0, /*int argcount,*/ - #if PY_MAJOR_VERSION >= 3 - 0, /*int kwonlyargcount,*/ - #endif - 0, /*int nlocals,*/ - 0, /*int stacksize,*/ - 0, /*int flags,*/ - __pyx_empty_bytes, /*PyObject *code,*/ - __pyx_empty_tuple, /*PyObject *consts,*/ - __pyx_empty_tuple, /*PyObject *names,*/ - __pyx_empty_tuple, /*PyObject *varnames,*/ - __pyx_empty_tuple, /*PyObject *freevars,*/ - __pyx_empty_tuple, /*PyObject *cellvars,*/ - py_srcfile, /*PyObject *filename,*/ - py_funcname, /*PyObject *name,*/ - __pyx_lineno, /*int firstlineno,*/ - __pyx_empty_bytes /*PyObject *lnotab*/ - ); - if (!py_code) goto bad; - py_frame = PyFrame_New( - PyThreadState_GET(), /*PyThreadState *tstate,*/ - py_code, /*PyCodeObject *code,*/ - py_globals, /*PyObject *globals,*/ - 0 /*PyObject *locals*/ - ); - if (!py_frame) goto bad; - py_frame->f_lineno = __pyx_lineno; - PyTraceBack_Here(py_frame); -bad: - Py_XDECREF(py_srcfile); - Py_XDECREF(py_funcname); - Py_XDECREF(py_code); - Py_XDECREF(py_frame); -} - -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { - while (t->p) { - #if PY_MAJOR_VERSION < 3 - if (t->is_unicode) { - *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); - } else if (t->intern) { - *t->p = PyString_InternFromString(t->s); - } else { - *t->p = PyString_FromStringAndSize(t->s, t->n - 1); - } - #else /* Python 3+ has unicode identifiers */ - if (t->is_unicode | t->is_str) { - if (t->intern) { - *t->p = PyUnicode_InternFromString(t->s); - } else if (t->encoding) { - *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); - } else { - *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); - } - } else { - *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); - } - #endif - if (!*t->p) - return -1; - ++t; - } - return 0; -} - -/* Type Conversion Functions */ - -static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { - if (x == Py_True) return 1; - else if ((x == Py_False) | (x == Py_None)) return 0; - else return PyObject_IsTrue(x); -} - -static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) { - PyNumberMethods *m; - const char *name = NULL; - PyObject *res = NULL; -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check(x) || PyLong_Check(x)) -#else - if (PyLong_Check(x)) -#endif - return Py_INCREF(x), x; - m = Py_TYPE(x)->tp_as_number; -#if PY_VERSION_HEX < 0x03000000 - if (m && m->nb_int) { - name = "int"; - res = PyNumber_Int(x); - } - else if (m && m->nb_long) { - name = "long"; - res = PyNumber_Long(x); - } -#else - if (m && m->nb_int) { - name = "int"; - res = PyNumber_Long(x); - } -#endif - if (res) { -#if PY_VERSION_HEX < 0x03000000 - if (!PyInt_Check(res) && !PyLong_Check(res)) { -#else - if (!PyLong_Check(res)) { -#endif - PyErr_Format(PyExc_TypeError, - "__%s__ returned non-%s (type %.200s)", - name, name, Py_TYPE(res)->tp_name); - Py_DECREF(res); - return NULL; - } - } - else if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "an integer is required"); - } - return res; -} - -static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { - Py_ssize_t ival; - PyObject* x = PyNumber_Index(b); - if (!x) return -1; - ival = PyInt_AsSsize_t(x); - Py_DECREF(x); - return ival; -} - -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { -#if PY_VERSION_HEX < 0x02050000 - if (ival <= LONG_MAX) - return PyInt_FromLong((long)ival); - else { - unsigned char *bytes = (unsigned char *) &ival; - int one = 1; int little = (int)*(unsigned char*)&one; - return _PyLong_FromByteArray(bytes, sizeof(size_t), little, 0); - } -#else - return PyInt_FromSize_t(ival); -#endif -} - -static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) { - unsigned PY_LONG_LONG val = __Pyx_PyInt_AsUnsignedLongLong(x); - if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) { - return (size_t)-1; - } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) { - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to size_t"); - return (size_t)-1; - } - return (size_t)val; -} - - -#endif /* Py_PYTHON_H */ diff --git a/3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.pyx b/3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.pyx deleted file mode 100644 index e43bd2b28b4..00000000000 --- a/3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.pyx +++ /dev/null @@ -1,537 +0,0 @@ -# pyPortMidi -# Python bindings for PortMidi -# John Harrison -# http://sound.media.mit.edu/~harrison -# harrison@media.mit.edu -# written in Pyrex -__version__="0.07" - -import array - -# CHANGES: - -# 0.0.5: (June 1st, 2009) -# Output no longer calls abort when it deallocates. -# Added abort and close methods. -# Need to call Abort() explicityly if you want that to happen. - - -# -# 0.0.3: (March 15, 2005) -# changed everything from tuples to lists -# return 4 values for PmRead instead of 3 (for SysEx) -# minor fixes for flexibility and error checking -# flushed out DistUtils package and added Mac and Linux compile support -# Markus Pfaff: added ability for WriteSysEx to accept lists as well -# as strings - -# 0.0.2: -# fixed pointer to function calls to avoid necessity of pyport library - -# 0.0.1: -# initial release - -cdef extern from "portmidi.h": - ctypedef enum PmError: - pmNoError = 0, - pmHostError = -10000, - pmInvalidDeviceId, #/* out of range or output device when input is requested or vice versa */ - pmInsufficientMemory, - pmBufferTooSmall, - pmBufferOverflow, - pmBadPtr, - pmBadData, #/* illegal midi data, e.g. missing EOX */ - pmInternalError, - pmBufferMaxSize, #/* buffer is already as large as it can be */ - PmError Pm_Initialize() - PmError Pm_Terminate() - ctypedef void PortMidiStream - ctypedef PortMidiStream PmStream # CHECK THIS! - ctypedef int PmDeviceID - int Pm_HasHostError( PortMidiStream * stream ) - char *Pm_GetErrorText( PmError errnum ) - Pm_GetHostErrorText(char * msg, unsigned int len) - ctypedef struct PmDeviceInfo: - int structVersion - char *interf #/* underlying MIDI API, e.g. MMSystem or DirectX */ - char *name #/* device name, e.g. USB MidiSport 1x1 */ - int input #/* true iff input is available */ - int output #/* true iff output is available */ - int opened #/* used by generic PortMidi code to do error checking on arguments */ - int Pm_CountDevices() - PmDeviceID Pm_GetDefaultInputDeviceID() - PmDeviceID Pm_GetDefaultOutputDeviceID() - ctypedef long PmTimestamp - ctypedef PmTimestamp (*PmTimeProcPtr)(void *time_info) - #PmBefore is not defined... - PmDeviceInfo* Pm_GetDeviceInfo( PmDeviceID id ) - PmError Pm_OpenInput( PortMidiStream** stream, - PmDeviceID inputDevice, - void *inputDriverInfo, - long bufferSize, - long (*PmPtr) (), # long = PtTimestamp - void *time_info ) - PmError Pm_OpenOutput( PortMidiStream** stream, - PmDeviceID outputDevice, - void *outputDriverInfo, - long bufferSize, - #long (*PmPtr) (), # long = PtTimestamp - PmTimeProcPtr time_proc, # long = PtTimestamp - void *time_info, - long latency ) - PmError Pm_SetFilter( PortMidiStream* stream, long filters ) - PmError Pm_Abort( PortMidiStream* stream ) - PmError Pm_Close( PortMidiStream* stream ) - ctypedef long PmMessage - ctypedef struct PmEvent: - PmMessage message - PmTimestamp timestamp - PmError Pm_Read( PortMidiStream *stream, PmEvent *buffer, long length ) - PmError Pm_Poll( PortMidiStream *stream) - int Pm_Channel(int channel) - PmError Pm_SetChannelMask(PortMidiStream *stream, int mask) - PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, long length ) - PmError Pm_WriteSysEx( PortMidiStream *stream, PmTimestamp when, unsigned char *msg) - -cdef extern from "porttime.h": - ctypedef enum PtError: - ptNoError = 0, - ptHostError = -10000, - ptAlreadyStarted, - ptAlreadyStopped, - ptInsufficientMemory - ctypedef long PtTimestamp - ctypedef void (* PtCallback)( PtTimestamp timestamp, void *userData ) - PtError Pt_Start(int resolution, PtCallback *callback, void *userData) - PtTimestamp Pt_Time() - -FILT_ACTIVE=0x1 -FILT_SYSEX=0x2 -FILT_CLOCK=0x4 -FILT_PLAY=0x8 -FILT_F9=0x10 -FILT_TICK=0x10 -FILT_FD=0x20 -FILT_UNDEFINED=0x30 -FILT_RESET=0x40 -FILT_REALTIME=0x7F -FILT_NOTE=0x80 -FILT_CHANNEL_AFTERTOUCH=0x100 -FILT_POLY_AFTERTOUCH=0x200 -FILT_AFTERTOUCH=0x300 -FILT_PROGRAM=0x400 -FILT_CONTROL=0x800 -FILT_PITCHBEND=0x1000 -FILT_MTC=0x2000 -FILT_SONG_POSITION=0x4000 -FILT_SONG_SELECT=0x8000 -FILT_TUNE=0x10000 -FALSE=0 -TRUE=1 - -def Initialize(): - """ -Initialize: call this first - """ - Pm_Initialize() - Pt_Start(1, NULL, NULL) # /* equiv to TIME_START: start timer w/ ms accuracy */ - -def Terminate(): - """ -Terminate: call this to clean up Midi streams when done. -If you do not call this on Windows machines when you are -done with MIDI, your system may crash. - """ - Pm_Terminate() - -def GetDefaultInputDeviceID(): - return Pm_GetDefaultInputDeviceID() - -def GetDefaultOutputDeviceID(): - return Pm_GetDefaultOutputDeviceID() - -def CountDevices(): - return Pm_CountDevices() - -def GetDeviceInfo(i): - """ -GetDeviceInfo(<device number>): returns 5 parameters - - underlying MIDI API - - device name - - TRUE iff input is available - - TRUE iff output is available - - TRUE iff device stream is already open - """ - cdef PmDeviceInfo *info - - # disregarding the constness from Pm_GetDeviceInfo, since pyrex doesn't do const. - info = <PmDeviceInfo *>Pm_GetDeviceInfo(i) - - if info <> NULL: return info.interf, info.name, info.input, info.output, info.opened - else: return - -def Time(): - """ -Time() returns the current time in ms -of the PortMidi timer - """ - return Pt_Time() - -def GetErrorText(err): - """ -GetErrorText(<err num>) returns human-readable error -messages translated from error numbers - """ - return Pm_GetErrorText(err) - -def Channel(chan): - """ -Channel(<chan>) is used with ChannelMask on input MIDI streams. -Example: to receive input on channels 1 and 10 on a MIDI - stream called MidiIn: -MidiIn.SetChannelMask(pypm.Channel(1) | pypm.Channel(10)) - -note: PyPortMidi Channel function has been altered from - the original PortMidi c call to correct for what - seems to be a bug --- i.e. channel filters were - all numbered from 0 to 15 instead of 1 to 16. - """ - return Pm_Channel(chan-1) - -cdef class Output: - """ -class Output: - define an output MIDI stream. Takes the form: - x = pypm.Output(MidiOutputDevice, latency) - latency is in ms. - If latency = 0 then timestamps for output are ignored. - """ - cdef int i - cdef PmStream *midi - cdef int debug - cdef int _aborted - - def __init__(self, OutputDevice, latency=0): - - cdef PmError err - #cdef PtTimestamp (*PmPtr) () - cdef PmTimeProcPtr PmPtr - - self.i = OutputDevice - self.debug = 0 - self._aborted = 0 - - if latency == 0: - PmPtr = NULL - else: - PmPtr = <PmTimeProcPtr>&Pt_Time - if self.debug: print "Opening Midi Output" - # Why is bufferSize 0 here? - err = Pm_OpenOutput(&(self.midi), self.i, NULL, 0, PmPtr, NULL, latency) - if err < 0: - s = Pm_GetErrorText(err) - # Something's amiss here - if we try to throw an Exception - # here, we crash. - if not err == -10000: - raise Exception,s - else: - print "Unable to open Midi OutputDevice=",OutputDevice," err=",s - - def __dealloc__(self): - if self.debug: print "Closing MIDI output stream and destroying instance" - #err = Pm_Abort(self.midi) - #if err < 0: raise Exception, Pm_GetErrorText(err) - err = Pm_Close(self.midi) - if err < 0: raise Exception, Pm_GetErrorText(err) - - - def _check_open(self): - """ checks to see if the midi is open, and if not, raises an error. - """ - - if self.midi == NULL: - raise Exception, "midi Output not open." - - if self._aborted: - raise Exception, "midi Output aborted. Need to call Close after Abort." - - def Close(self): - """ -Close() - closes a midi stream, flushing any pending buffers. - (PortMidi attempts to close open streams when the application - exits -- this is particularly difficult under Windows.) - """ - #if not self.midi: - # return - - err = Pm_Close(self.midi) - if err < 0: - raise Exception, Pm_GetErrorText(err) - #self.midi = NULL - - - def Abort(self): - """ -Abort() terminates outgoing messages immediately - The caller should immediately close the output port; - this call may result in transmission of a partial midi message. - There is no abort for Midi input because the user can simply - ignore messages in the buffer and close an input device at - any time. - """ - #if not self.midi: - # return - - err = Pm_Abort(self.midi) - if err < 0: - raise Exception, Pm_GetErrorText(err) - - self._aborted = 1 - - - def Write(self, data): - """ -Write(data) - output a series of MIDI information in the form of a list: - Write([[[status <,data1><,data2><,data3>],timestamp], - [[status <,data1><,data2><,data3>],timestamp],...]) - <data> fields are optional - example: choose program change 1 at time 20000 and - send note 65 with velocity 100 500 ms later. - Write([[[0xc0,0,0],20000],[[0x90,60,100],20500]]) - notes: - 1. timestamps will be ignored if latency = 0. - 2. To get a note to play immediately, send MIDI info with - timestamp read from function Time. - 3. understanding optional data fields: - Write([[[0xc0,0,0],20000]]) is equivalent to - Write([[[0xc0],20000]]) - """ - cdef PmEvent buffer[1024] - cdef PmError err - cdef int i - - self._check_open() - - - if len(data) > 1024: raise IndexError, 'maximum list length is 1024' - else: - for loop1 in range(len(data)): - if ((len(data[loop1][0]) > 4) | - (len(data[loop1][0]) < 1)): - raise IndexError, str(len(data[loop1][0]))+' arguments in event list' - buffer[loop1].message = 0 - for i in range(len(data[loop1][0])): - buffer[loop1].message = buffer[loop1].message + ((data[loop1][0][i]&0xFF) << (8*i)) - buffer[loop1].timestamp = data[loop1][1] - if self.debug: print loop1," : ",buffer[loop1].message," : ",buffer[loop1].timestamp - if self.debug: print "writing to midi buffer" - err= Pm_Write(self.midi, buffer, len(data)) - if err < 0: raise Exception, Pm_GetErrorText(err) - - def WriteShort(self, status, data1 = 0, data2 = 0): - """ -WriteShort(status <, data1><, data2>) - output MIDI information of 3 bytes or less. - data fields are optional - status byte could be: - 0xc0 = program change - 0x90 = note on - etc. - data bytes are optional and assumed 0 if omitted - example: note 65 on with velocity 100 - WriteShort(0x90,65,100) - """ - cdef PmEvent buffer[1] - cdef PmError err - self._check_open() - - buffer[0].timestamp = Pt_Time() - buffer[0].message = ((((data2) << 16) & 0xFF0000) | (((data1) << 8) & 0xFF00) | ((status) & 0xFF)) - if self.debug: print "Writing to MIDI buffer" - err = Pm_Write(self.midi, buffer, 1) # stream, buffer, length - if err < 0 : raise Exception, Pm_GetErrorText(err) - - def WriteSysEx(self, when, msg): - """ - WriteSysEx(<timestamp>,<msg>) - writes a timestamped system-exclusive midi message. - <msg> can be a *list* or a *string* - example: - (assuming y is an input MIDI stream) - y.WriteSysEx(0,'\\xF0\\x7D\\x10\\x11\\x12\\x13\\xF7') - is equivalent to - y.WriteSysEx(pypm.Time, - [0xF0, 0x7D, 0x10, 0x11, 0x12, 0x13, 0xF7]) - """ - cdef PmError err - cdef char *cmsg - cdef PtTimestamp CurTime - - self._check_open() - - if type(msg) is list: - msg = array.array('B',msg).tostring() # Markus Pfaff contribution - cmsg = msg - - CurTime = Pt_Time() - err = Pm_WriteSysEx(self.midi, when, <unsigned char *> cmsg) - if err < 0 : raise Exception, Pm_GetErrorText(err) - while Pt_Time() == CurTime: # wait for SysEx to go thru or...my - pass # win32 machine crashes w/ multiple SysEx - - - - - - - - - - - -cdef class Input: - """ -class Input: - define an input MIDI stream. Takes the form: - x = pypm.Input(MidiInputDevice) - """ - cdef PmStream *midi - cdef int debug - cdef int i - - def __init__(self, InputDevice, buffersize=4096): - cdef PmError err - self.i = InputDevice - self.debug = 0 - err= Pm_OpenInput(&(self.midi),self.i,NULL,buffersize,&Pt_Time,NULL) - if err < 0: raise Exception, Pm_GetErrorText(err) - if self.debug: print "MIDI input opened." - - def __dealloc__(self): - cdef PmError err - if self.debug: print "Closing MIDI input stream and destroying instance" - - err = Pm_Close(self.midi) - if err < 0: - raise Exception, Pm_GetErrorText(err) - - - - def _check_open(self): - """ checks to see if the midi is open, and if not, raises an error. - """ - - if self.midi == NULL: - raise Exception, "midi Input not open." - - - def Close(self): - """ -Close() - closes a midi stream, flushing any pending buffers. - (PortMidi attempts to close open streams when the application - exits -- this is particularly difficult under Windows.) - """ - #if not self.midi: - # return - - err = Pm_Close(self.midi) - if err < 0: - raise Exception, Pm_GetErrorText(err) - #self.midi = NULL - - - - def SetFilter(self, filters): - """ - SetFilter(<filters>) sets filters on an open input stream - to drop selected input types. By default, only active sensing - messages are filtered. To prohibit, say, active sensing and - sysex messages, call - SetFilter(stream, FILT_ACTIVE | FILT_SYSEX); - - Filtering is useful when midi routing or midi thru functionality - is being provided by the user application. - For example, you may want to exclude timing messages - (clock, MTC, start/stop/continue), while allowing note-related - messages to pass. Or you may be using a sequencer or drum-machine - for MIDI clock information but want to exclude any notes - it may play. - - Note: SetFilter empties the buffer after setting the filter, - just in case anything got through. - """ - cdef PmEvent buffer[1] - cdef PmError err - - self._check_open() - - - err = Pm_SetFilter(self.midi, filters) - - if err < 0: raise Exception, Pm_GetErrorText(err) - - while(Pm_Poll(self.midi) != pmNoError): - - err = Pm_Read(self.midi,buffer,1) - if err < 0: raise Exception, Pm_GetErrorText(err) - - def SetChannelMask(self, mask): - """ - SetChannelMask(<mask>) filters incoming messages based on channel. - The mask is a 16-bit bitfield corresponding to appropriate channels - Channel(<channel>) can assist in calling this function. - i.e. to set receive only input on channel 1, call with - SetChannelMask(Channel(1)) - Multiple channels should be OR'd together, like - SetChannelMask(Channel(10) | Channel(11)) - note: PyPortMidi Channel function has been altered from - the original PortMidi c call to correct for what - seems to be a bug --- i.e. channel filters were - all numbered from 0 to 15 instead of 1 to 16. - """ - cdef PmError err - - self._check_open() - - err = Pm_SetChannelMask(self.midi,mask) - if err < 0: raise Exception, Pm_GetErrorText(err) - - def Poll(self): - """ - Poll tests whether input is available, - returning TRUE, FALSE, or an error value. - """ - cdef PmError err - self._check_open() - - err = Pm_Poll(self.midi) - if err < 0: raise Exception, Pm_GetErrorText(err) - return err - - def Read(self,length): - """ -Read(length): returns up to <length> midi events stored in -the buffer and returns them as a list: -[[[status,data1,data2,data3],timestamp], - [[status,data1,data2,data3],timestamp],...] -example: Read(50) returns all the events in the buffer, - up to 50 events. - """ - cdef PmEvent buffer[1024] - - self._check_open() - - x = [] - - if length > 1024: raise IndexError, 'maximum buffer length is 1024' - if length < 1: raise IndexError, 'minimum buffer length is 1' - NumEvents = Pm_Read(self.midi,buffer,length) - if NumEvents < 0: raise Exception, Pm_GetErrorText(NumEvents) - x=[] - if NumEvents >= 1: - for loop in range(NumEvents): - x.append([[buffer[loop].message & 0xff, (buffer[loop].message >> 8) & 0xFF, (buffer[loop].message >> 16) & 0xFF, (buffer[loop].message >> 24) & 0xFF], buffer[loop].timestamp]) - return x diff --git a/3rdparty/portmidi/pm_python/pyportmidi/midi.py b/3rdparty/portmidi/pm_python/pyportmidi/midi.py deleted file mode 100644 index 71e4f2b4b8f..00000000000 --- a/3rdparty/portmidi/pm_python/pyportmidi/midi.py +++ /dev/null @@ -1,566 +0,0 @@ -""" -Module for interacting with midi input and output. - -The midi module can send output to midi devices, and get input -from midi devices. It can also list midi devices on the system. - -Including real midi devices, and virtual ones. - -It uses the portmidi library. Is portable to which ever platforms -portmidi supports (currently windows, OSX, and linux). -""" - -import atexit - - - -_init = False -_pypm = None - - -__all__ = [ "Input", - "MidiException", - "Output", - "get_count", - "get_default_input_id", - "get_default_output_id", - "get_device_info", - "init", - "quit", - "time", - ] - -__theclasses__ = ["Input", "Output"] - - -def init(): - """initialize the midi module - pyportmidi.init(): return None - - Call the initialisation function before using the midi module. - - It is safe to call this more than once. - """ - global _init, _pypm - if not _init: - import pyportmidi._pyportmidi - _pypm = pyportmidi._pyportmidi - - _pypm.Initialize() - _init = True - atexit.register(quit) - - -def quit(): - """uninitialize the midi module - pyportmidi.quit(): return None - - - Called automatically atexit if you don't call it. - - It is safe to call this function more than once. - """ - global _init, _pypm - if _init: - # TODO: find all Input and Output classes and close them first? - _pypm.Terminate() - _init = False - del _pypm - -def _check_init(): - if not _init: - raise RuntimeError("pyportmidi not initialised.") - -def get_count(): - """gets the number of devices. - pyportmidi.get_count(): return num_devices - - - Device ids range from 0 to get_count() -1 - """ - _check_init() - return _pypm.CountDevices() - - - - -def get_default_input_id(): - """gets default input device number - pyportmidi.get_default_input_id(): return default_id - - - Return the default device ID or -1 if there are no devices. - The result can be passed to the Input()/Ouput() class. - - On the PC, the user can specify a default device by - setting an environment variable. For example, to use device #1. - - set PM_RECOMMENDED_INPUT_DEVICE=1 - - The user should first determine the available device ID by using - the supplied application "testin" or "testout". - - In general, the registry is a better place for this kind of info, - and with USB devices that can come and go, using integers is not - very reliable for device identification. Under Windows, if - PM_RECOMMENDED_OUTPUT_DEVICE (or PM_RECOMMENDED_INPUT_DEVICE) is - *NOT* found in the environment, then the default device is obtained - by looking for a string in the registry under: - HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Input_Device - and HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Output_Device - for a string. The number of the first device with a substring that - matches the string exactly is returned. For example, if the string - in the registry is "USB", and device 1 is named - "In USB MidiSport 1x1", then that will be the default - input because it contains the string "USB". - - In addition to the name, get_device_info() returns "interf", which - is the interface name. (The "interface" is the underlying software - system or API used by PortMidi to access devices. Examples are - MMSystem, DirectX (not implemented), ALSA, OSS (not implemented), etc.) - At present, the only Win32 interface is "MMSystem", the only Linux - interface is "ALSA", and the only Max OS X interface is "CoreMIDI". - To specify both the interface and the device name in the registry, - separate the two with a comma and a space, e.g.: - MMSystem, In USB MidiSport 1x1 - In this case, the string before the comma must be a substring of - the "interf" string, and the string after the space must be a - substring of the "name" name string in order to match the device. - - Note: in the current release, the default is simply the first device - (the input or output device with the lowest PmDeviceID). - """ - return _pypm.GetDefaultInputDeviceID() - - - - -def get_default_output_id(): - """gets default output device number - pyportmidi.get_default_output_id(): return default_id - - - Return the default device ID or -1 if there are no devices. - The result can be passed to the Input()/Ouput() class. - - On the PC, the user can specify a default device by - setting an environment variable. For example, to use device #1. - - set PM_RECOMMENDED_OUTPUT_DEVICE=1 - - The user should first determine the available device ID by using - the supplied application "testin" or "testout". - - In general, the registry is a better place for this kind of info, - and with USB devices that can come and go, using integers is not - very reliable for device identification. Under Windows, if - PM_RECOMMENDED_OUTPUT_DEVICE (or PM_RECOMMENDED_INPUT_DEVICE) is - *NOT* found in the environment, then the default device is obtained - by looking for a string in the registry under: - HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Input_Device - and HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Output_Device - for a string. The number of the first device with a substring that - matches the string exactly is returned. For example, if the string - in the registry is "USB", and device 1 is named - "In USB MidiSport 1x1", then that will be the default - input because it contains the string "USB". - - In addition to the name, get_device_info() returns "interf", which - is the interface name. (The "interface" is the underlying software - system or API used by PortMidi to access devices. Examples are - MMSystem, DirectX (not implemented), ALSA, OSS (not implemented), etc.) - At present, the only Win32 interface is "MMSystem", the only Linux - interface is "ALSA", and the only Max OS X interface is "CoreMIDI". - To specify both the interface and the device name in the registry, - separate the two with a comma and a space, e.g.: - MMSystem, In USB MidiSport 1x1 - In this case, the string before the comma must be a substring of - the "interf" string, and the string after the space must be a - substring of the "name" name string in order to match the device. - - Note: in the current release, the default is simply the first device - (the input or output device with the lowest PmDeviceID). - """ - _check_init() - return _pypm.GetDefaultOutputDeviceID() - - -def get_device_info(an_id): - """ returns information about a midi device - pyportmidi.get_device_info(an_id): return (interf, name, input, output, opened) - - interf - a text string describing the device interface, eg 'ALSA'. - name - a text string for the name of the device, eg 'Midi Through Port-0' - input - 0, or 1 if the device is an input device. - output - 0, or 1 if the device is an output device. - opened - 0, or 1 if the device is opened. - - If the id is out of range, the function returns None. - """ - _check_init() - return _pypm.GetDeviceInfo(an_id) - - -class Input(object): - """Input is used to get midi input from midi devices. - Input(device_id) - Input(device_id, buffer_size) - - buffer_size -the number of input events to be buffered waiting to - be read using Input.read() - """ - - def __init__(self, device_id, buffer_size=4096): - """ - The buffer_size specifies the number of input events to be buffered - waiting to be read using Input.read(). - """ - _check_init() - - if device_id == -1: - raise MidiException("Device id is -1, not a valid output id. -1 usually means there were no default Output devices.") - - try: - r = get_device_info(device_id) - except TypeError: - raise TypeError("an integer is required") - except OverflowError: - raise OverflowError("long int too large to convert to int") - - # and now some nasty looking error checking, to provide nice error - # messages to the kind, lovely, midi using people of whereever. - if r: - interf, name, input, output, opened = r - if input: - try: - self._input = _pypm.Input(device_id, buffer_size) - except TypeError: - raise TypeError("an integer is required") - self.device_id = device_id - - elif output: - raise MidiException("Device id given is not a valid input id, it is an output id.") - else: - raise MidiException("Device id given is not a valid input id.") - else: - raise MidiException("Device id invalid, out of range.") - - - - - def _check_open(self): - if self._input is None: - raise MidiException("midi not open.") - - - - def close(self): - """ closes a midi stream, flushing any pending buffers. - Input.close(): return None - - PortMidi attempts to close open streams when the application - exits -- this is particularly difficult under Windows. - """ - _check_init() - if not (self._input is None): - self._input.Close() - self._input = None - - - - def read(self, num_events): - """reads num_events midi events from the buffer. - Input.read(num_events): return midi_event_list - - Reads from the Input buffer and gives back midi events. - [[[status,data1,data2,data3],timestamp], - [[status,data1,data2,data3],timestamp],...] - """ - _check_init() - self._check_open() - return self._input.Read(num_events) - - - def poll(self): - """returns true if there's data, or false if not. - Input.poll(): return Bool - - raises a MidiException on error. - """ - _check_init() - self._check_open() - - r = self._input.Poll() - if r == _pypm.TRUE: - return True - elif r == _pypm.FALSE: - return False - else: - err_text = GetErrorText(r) - raise MidiException( (r, err_text) ) - - - - -class Output(object): - """Output is used to send midi to an output device - Output(device_id) - Output(device_id, latency = 0) - Output(device_id, buffer_size = 4096) - Output(device_id, latency, buffer_size) - - The buffer_size specifies the number of output events to be - buffered waiting for output. (In some cases -- see below -- - PortMidi does not buffer output at all and merely passes data - to a lower-level API, in which case buffersize is ignored.) - - latency is the delay in milliseconds applied to timestamps to determine - when the output should actually occur. (If latency is < 0, 0 is - assumed.) - - If latency is zero, timestamps are ignored and all output is delivered - immediately. If latency is greater than zero, output is delayed until - the message timestamp plus the latency. (NOTE: time is measured - relative to the time source indicated by time_proc. Timestamps are - absolute, not relative delays or offsets.) In some cases, PortMidi - can obtain better timing than your application by passing timestamps - along to the device driver or hardware. Latency may also help you - to synchronize midi data to audio data by matching midi latency to - the audio buffer latency. - - """ - - def __init__(self, device_id, latency = 0, buffer_size = 4096): - """Output(device_id) - Output(device_id, latency = 0) - Output(device_id, buffer_size = 4096) - Output(device_id, latency, buffer_size) - - The buffer_size specifies the number of output events to be - buffered waiting for output. (In some cases -- see below -- - PortMidi does not buffer output at all and merely passes data - to a lower-level API, in which case buffersize is ignored.) - - latency is the delay in milliseconds applied to timestamps to determine - when the output should actually occur. (If latency is < 0, 0 is - assumed.) - - If latency is zero, timestamps are ignored and all output is delivered - immediately. If latency is greater than zero, output is delayed until - the message timestamp plus the latency. (NOTE: time is measured - relative to the time source indicated by time_proc. Timestamps are - absolute, not relative delays or offsets.) In some cases, PortMidi - can obtain better timing than your application by passing timestamps - along to the device driver or hardware. Latency may also help you - to synchronize midi data to audio data by matching midi latency to - the audio buffer latency. - """ - - _check_init() - self._aborted = 0 - - if device_id == -1: - raise MidiException("Device id is -1, not a valid output id. -1 usually means there were no default Output devices.") - - try: - r = get_device_info(device_id) - except TypeError: - raise TypeError("an integer is required") - except OverflowError: - raise OverflowError("long int too large to convert to int") - - # and now some nasty looking error checking, to provide nice error - # messages to the kind, lovely, midi using people of whereever. - if r: - interf, name, input, output, opened = r - if output: - try: - self._output = _pypm.Output(device_id, latency) - except TypeError: - raise TypeError("an integer is required") - self.device_id = device_id - - elif input: - raise MidiException("Device id given is not a valid output id, it is an input id.") - else: - raise MidiException("Device id given is not a valid output id.") - else: - raise MidiException("Device id invalid, out of range.") - - def _check_open(self): - if self._output is None: - raise MidiException("midi not open.") - - if self._aborted: - raise MidiException("midi aborted.") - - - def close(self): - """ closes a midi stream, flushing any pending buffers. - Output.close(): return None - - PortMidi attempts to close open streams when the application - exits -- this is particularly difficult under Windows. - """ - _check_init() - if not (self._output is None): - self._output.Close() - self._output = None - - def abort(self): - """terminates outgoing messages immediately - Output.abort(): return None - - The caller should immediately close the output port; - this call may result in transmission of a partial midi message. - There is no abort for Midi input because the user can simply - ignore messages in the buffer and close an input device at - any time. - """ - - _check_init() - if self._output: - self._output.Abort() - self._aborted = 1 - - - - - - def write(self, data): - """writes a list of midi data to the Output - Output.write(data) - - writes series of MIDI information in the form of a list: - write([[[status <,data1><,data2><,data3>],timestamp], - [[status <,data1><,data2><,data3>],timestamp],...]) - <data> fields are optional - example: choose program change 1 at time 20000 and - send note 65 with velocity 100 500 ms later. - write([[[0xc0,0,0],20000],[[0x90,60,100],20500]]) - notes: - 1. timestamps will be ignored if latency = 0. - 2. To get a note to play immediately, send MIDI info with - timestamp read from function Time. - 3. understanding optional data fields: - write([[[0xc0,0,0],20000]]) is equivalent to - write([[[0xc0],20000]]) - - Can send up to 1024 elements in your data list, otherwise an - IndexError exception is raised. - """ - _check_init() - self._check_open() - - self._output.Write(data) - - - def write_short(self, status, data1 = 0, data2 = 0): - """write_short(status <, data1><, data2>) - Output.write_short(status) - Output.write_short(status, data1 = 0, data2 = 0) - - output MIDI information of 3 bytes or less. - data fields are optional - status byte could be: - 0xc0 = program change - 0x90 = note on - etc. - data bytes are optional and assumed 0 if omitted - example: note 65 on with velocity 100 - write_short(0x90,65,100) - """ - _check_init() - self._check_open() - self._output.WriteShort(status, data1, data2) - - - def write_sys_ex(self, when, msg): - """writes a timestamped system-exclusive midi message. - Output.write_sys_ex(when, msg) - - msg - can be a *list* or a *string* - when - a timestamp in miliseconds - example: - (assuming o is an onput MIDI stream) - o.write_sys_ex(0,'\\xF0\\x7D\\x10\\x11\\x12\\x13\\xF7') - is equivalent to - o.write_sys_ex(pyportmidi.time(), - [0xF0,0x7D,0x10,0x11,0x12,0x13,0xF7]) - """ - _check_init() - self._check_open() - self._output.WriteSysEx(when, msg) - - - def note_on(self, note, velocity=None, channel = 0): - """turns a midi note on. Note must be off. - Output.note_on(note, velocity=None, channel = 0) - - Turn a note on in the output stream. The note must already - be off for this to work correctly. - """ - if velocity is None: - velocity = 0 - - if not (0 <= channel <= 15): - raise ValueError("Channel not between 0 and 15.") - - self.write_short(0x90+channel, note, velocity) - - def note_off(self, note, velocity=None, channel = 0): - """turns a midi note off. Note must be on. - Output.note_off(note, velocity=None, channel = 0) - - Turn a note off in the output stream. The note must already - be on for this to work correctly. - """ - if velocity is None: - velocity = 0 - - if not (0 <= channel <= 15): - raise ValueError("Channel not between 0 and 15.") - - self.write_short(0x80 + channel, note, velocity) - - - def set_instrument(self, instrument_id, channel = 0): - """select an instrument, with a value between 0 and 127 - Output.set_instrument(instrument_id, channel = 0) - - """ - if not (0 <= instrument_id <= 127): - raise ValueError("Undefined instrument id: %d" % instrument_id) - - if not (0 <= channel <= 15): - raise ValueError("Channel not between 0 and 15.") - - self.write_short(0xc0+channel, instrument_id) - - - -def time(): - """returns the current time in ms of the PortMidi timer - pyportmidi.time(): return time - - The time is reset to 0, when the module is inited. - """ - return _pypm.Time() - - - - - - - - -class MidiException(Exception): - """MidiException(errno) that can be raised. - """ - def __init__(self, value): - self.parameter = value - def __str__(self): - return repr(self.parameter) - - - diff --git a/3rdparty/portmidi/pm_python/setup.py b/3rdparty/portmidi/pm_python/setup.py deleted file mode 100644 index 14ab1c758af..00000000000 --- a/3rdparty/portmidi/pm_python/setup.py +++ /dev/null @@ -1,185 +0,0 @@ -import sys -import os -import logging - -from distutils.core import setup, Command -from distutils.extension import Extension -try: - from Cython.Distutils import build_ext -except ImportError: - logging.warn("Cython is preferred over pyrex for python3 compatibility.") - from Pyrex.Distutils import build_ext - - - - - -DESCRIPTION = open('README_PYTHON.txt').read() -CHANGES = open('CHANGES.txt').read() -TODO = open('TODO.txt').read() - -EXTRAS = {} - -long_description = DESCRIPTION + CHANGES + TODO -#import sys -#if "checkdocs" in sys.argv: -# print long_description - - -METADATA = { - 'name': 'pyportmidi', - 'version': '0.0.7', - 'license': 'MIT License', - 'url': 'http://pypi.python.org/pyportmidi/', - 'author': 'John Harrison, Roger B. Dannenberg, Rene Dudfield, others...', - 'author_email': 'renesd@gmail.com', - 'maintainer': 'Rene Dudfield', - 'maintainer_email': 'renesd@gmail.com', - 'description': 'Python Wrappings for PortMidi #python. CHANGES: new package layout.', - 'long_description': long_description, - 'classifiers': [ - 'Development Status :: 2 - Pre-Alpha', - 'Intended Audience :: Developers', - 'Intended Audience :: Information Technology', - 'License :: OSI Approved :: BSD License', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX :: Linux', - 'Programming Language :: Cython', - 'Programming Language :: C', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.5', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.0', - 'Programming Language :: Python :: 3.1', - 'Programming Language :: Python :: 3.2', - 'Topic :: Multimedia :: Sound/Audio :: MIDI', - 'Topic :: Software Development :: Libraries', - ], -} - - -if "bdist_msi" in sys.argv: - # hack the version name to a format msi doesn't have trouble with - METADATA["version"] = METADATA["version"].replace("pre", "a0") - METADATA["version"] = METADATA["version"].replace("rc", "b0") - METADATA["version"] = METADATA["version"].replace("release", "") - - - - - -# allow optionally using setuptools for bdist_egg. -using_setuptools = False - -if "-setuptools" in sys.argv: - using_setuptools = True - - from setuptools import setup, Command - sys.argv.remove ("-setuptools") - - EXTRAS.update({'include_package_data': True, - 'install_requires': [], - 'zip_safe': False, - 'test_suite' : 'pyportmidi.tests', - } - ) - - -# test command. For doing 'python setup.py test' -class TestCommand(Command): - user_options = [ ] - - def initialize_options(self): - self._dir = os.getcwd() - - def finalize_options(self): - pass - - def run(self): - ''' - runs the tests with default options. - ''' - import pyportmidi.tests - pyportmidi.tests.main() - - #import subprocess - #return subprocess.call([sys.executable, "run_tests.py"]) - - -cmdclass = {'build_ext': build_ext} - -# we use our test command. -if not using_setuptools: - import os - cmdclass['test'] = TestCommand - - - -scripts = [] - -PACKAGEDATA = { - 'cmdclass': cmdclass, - - 'package_dir': {'pyportmidi': 'pyportmidi', - #'pyportmidi.tests': 'test', - #'pyportmidi.docs': 'docs', - #'pyportmidi.examples': 'examples', - - }, - 'packages': ['pyportmidi', - 'pyportmidi.tests', - ], - 'scripts': scripts, -} - - -PACKAGEDATA.update(METADATA) -PACKAGEDATA.update(EXTRAS) - - - -if sys.platform == 'win32': - print "Found Win32 platform" - EXTENSION = dict( - ext_modules=[ - Extension("pyportmidi._pyportmidi", [os.path.join("pyportmidi", "_pyportmidi.pyx")], - library_dirs = ["../Release"], - libraries = ["portmidi", "winmm"], - include_dirs = ["../porttime"], -# define_macros = [("_WIN32_", None)]) # needed by portmidi.h - extra_compile_args = ["/DWIN32"]) # needed by portmidi.h - ] - ) -elif sys.platform == 'darwin': - print "Found darwin (OS X) platform" - library_dirs = ["/usr/local/lib"] - include_dirs = ["/usr/local/include"] - EXTENSION = dict( - ext_modules=[ - Extension("pyportmidi._pyportmidi", [os.path.join("pyportmidi", "_pyportmidi.pyx")], - library_dirs = library_dirs, - include_dirs = include_dirs, - libraries = ["portmidi"], - extra_link_args=["-framework", "CoreFoundation", - "-framework", "CoreMIDI", - "-framework", "CoreAudio"]) - ] - ) -else: - print "Assuming Linux platform" - EXTENSION = dict( - ext_modules=[ - Extension("pyportmidi._pyportmidi", [os.path.join("pyportmidi", "_pyportmidi.pyx")], - library_dirs=["./linux"], - libraries = ["portmidi", "asound", "pthread"] - ) - ] - - ) - -PACKAGEDATA.update(EXTENSION) - -setup(**PACKAGEDATA) diff --git a/3rdparty/portmidi/pm_qt/README_QT.txt b/3rdparty/portmidi/pm_qt/README_QT.txt deleted file mode 100644 index 181ad9f5a16..00000000000 --- a/3rdparty/portmidi/pm_qt/README_QT.txt +++ /dev/null @@ -1,15 +0,0 @@ -README_QT.txt for PortMidi -Richard Starfield -20 Sep 2010 - -This is a QtCreator build file for PortMidi. - -To build PortMidi on Windows with QtCreator: - -Move portmidi/pm_qt/portmidi.pro to portmidi/portmidi.pro - -Open portmidi.pro in QtCreator, change to the release build option and build all to compile the static library. - -This has been tested in Windows. The project file does include Linux build switches but they haven't been tested yet. - -To compile a DLL instead of a static library change line 11 from "CONFIG += staticlib" to "CONFIG += DLL" diff --git a/3rdparty/portmidi/pm_qt/portmidi.pro b/3rdparty/portmidi/pm_qt/portmidi.pro deleted file mode 100644 index d2298f7596a..00000000000 --- a/3rdparty/portmidi/pm_qt/portmidi.pro +++ /dev/null @@ -1,47 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2010-09-02T12:50:47 -# -#------------------------------------------------- - -QT -= core gui - -TARGET = portmidi -TEMPLATE = lib -CONFIG += staticlib # replace this with DLL for dynamic link on Windows - -INCLUDEPATH = pm_common/ porttime/ - -win32 { - INCLUDEPATH += pm_win/ - LIBS += -lwinmm - SOURCES += pm_win/pmwinmm.c \ - pm_win/pmwin.c - HEADERS += pm_win/pmwinmm.h -} - -# this build hasn't been tested on Linux yet -unix { - DEFINES += PMALSA - INCLUDEPATH += pm_linux/ - LIBS += -lasound - SOURCES += pm_linux/finddefault.c \ - pm_linux/pmlinux.c \ - pm_linux/pmlinuxalsa.c - HEADERS += pm_linux/pmlinux.h pm_linux/pmlinuxalsa.h -} - - -DEFINES -= UNICODE - -SOURCES += \ - pm_common/portmidi.c \ - pm_common/pmutil.c \ - porttime/porttime.c \ - porttime/ptwinmm.c - -HEADERS += \ - pm_common/pmutil.h \ - pm_common/pminternal.h \ - pm_common/portmidi.h \ - porttime/porttime.h diff --git a/3rdparty/portmidi/pm_test/CMakeLists.txt b/3rdparty/portmidi/pm_test/CMakeLists.txt index b89074b0bd5..ae0fe48b53d 100644 --- a/3rdparty/portmidi/pm_test/CMakeLists.txt +++ b/3rdparty/portmidi/pm_test/CMakeLists.txt @@ -1,4 +1,4 @@ -# pm_test +# CMake file to build tests in this directory: pm_test # set the build directory to be in portmidi, not in portmidi/pm_test # this is required for Xcode: @@ -6,21 +6,41 @@ if(APPLE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) endif(APPLE) -if(WIN32) -include(../pm_win/static.cmake) -endif(WIN32) +# if(WIN32) +# if(NOT BUILD_SHARED_LIBS) + # /MDd is multithread debug DLL, /MTd is multithread debug + # /MD is multithread DLL, /MT is multithread. Change to static: +# include(../pm_win/static.cmake) +# endif() +# endif(WIN32) + +if(HAIKU) + add_compile_options(-fPIC) # Haiku x86_64 needs this explicitly +endif() -macro(make_a_test name) +macro(add_test name) add_executable(${name} ${name}.c) - target_link_libraries(${name} portmidi-static ${PM_NEEDED_LIBS}) - add_dependencies(${name} portmidi-static) -endmacro(make_a_test) + target_link_libraries(${name} PRIVATE portmidi) + set_property(TARGET ${name} PROPERTY MSVC_RUNTIME_LIBRARY + "MultiThreaded$<$<CONFIG:Debug>:Debug>${MSVCRT_DLL}") +endmacro(add_test) -make_a_test(test) -make_a_test(midithread) -make_a_test(midithru) -make_a_test(sysex) -make_a_test(latency) -make_a_test(mm) -make_a_test(midiclock) -make_a_test(qtest) +add_test(testio) +add_test(midithread) +add_test(midithru) +add_test(sysex) +add_test(latency) +add_test(mm) +add_test(midiclock) +add_test(qtest) +add_test(fast) +add_test(fastrcv) +add_test(pmlist) +if(WIN32) +# windows does not implement Pm_CreateVirtualInput or Pm_CreateVirtualOutput +else(WIN32) +add_test(recvvirtual) +add_test(sendvirtual) +add_test(multivirtual) +add_test(virttest) +endif(WIN32) diff --git a/3rdparty/portmidi/pm_test/README.txt b/3rdparty/portmidi/pm_test/README.txt new file mode 100644 index 00000000000..b5a83d693b8 --- /dev/null +++ b/3rdparty/portmidi/pm_test/README.txt @@ -0,0 +1,376 @@ +README.txt - for pm_test directory + +These are all test programs for PortMidi + +Because device numbers depend on the system, there is no automated +script to run all tests on PortMidi. + +To run the full set of tests manually: + +Note: everything is run from the ../Debug or ../Release directory. +Actual or example input is marked with >>, e.g., >>0 means type 0<ENTER> +Comments are shown in square brackets [like this] + +1. ./qtest -- output should show a bunch of tests and no error message. + +2. ./testio [test input] +Latency in ms: >>0 +enter your choice... >>1 +Type input number: >>6 [pick a working input device] +[play some notes, look for note-on (0x90) with pitch and velocity data] + +3. ./testio [test input (fail w/assert)] +Latency in ms: >>0 +enter your choice... >>2 +Type input number: >>6 [pick a working input device] +[play some notes, program will abort after 5 messages +(this test only applies to a Debug build, otherwise +the assert() macro is disabled.)] + +4. ./testio [test input (fail w/NULL assign)] +Latency in ms: >>0 +enter your choice... >>3 +Type input number: >>6 [pick a working input device] +[play some notes, program will Segmentation fault after 5 messages +(this test may not Segfault in the Release build; if not +try testing with a Debug build.)] + +5. ./testio [test output, no latency] +Latency in ms: >>0 +enter your choice... >>4 +Type output number: >>2 [pick a working output device] +>> [type ENTER when prompted (7 times)] +[hear note on, note off, note on, note off, chord] + +6. ./testio [test output, latency > 0] +Latency in ms: >>300 +enter your choice... >>4 +Type output number: >>2 [pick a working output device] +>> [type ENTER when prompted (7 times)] +[hear note on, note off, note on, note off, arpeggiated chord + (delay of 300ms should be apparent)] + +7. ./testio [for both, no latency] +Latency in ms: >>0 +enter your choice... >>5 +Type input number: >>6 [pick a working input device] +Type output number: >>2 [pick a working output device] +[play notes on input, hear them on output] + +8. ./testio [for both, latency > 0] +Latency in ms: >>300 +enter your choice... >>5 +Type input number: >>6 [pick a working input device] +Type output number: >>2 [pick a working output device] +[play notes on input, hear them on output (delay of 300ms is apparent)] + +9. ./testio [stream test] +Latency in ms: >>0 [does not matter] +enter your choice... >>6 +Type output number: >>2 [pick a working output device] +>> [type ENTER to start] +[hear 4 notes: C D E F# at one note per second, then all turn off] +ready to close and terminate... (type ENTER) :>> [type ENTER (twice)] + +10. ./testio [isochronous out] +Latency in ms: >>300 +enter your choice... >>7 +Type output number: >>2 [pick a working output device] +ready to send program 1 change... (type ENTER): >> [type ENTER] +[hear 80 notes, exactly 4 notes per second, no jitter] + +11. ./latency [no MIDI, histogram] +Choose timer period (in ms, >= 1): >>1 +? >>1 [No MIDI traffic option] +[wait about 10 seconds] +>> [type ENTER] +[output should be something like ... Maximum latency: 1 milliseconds] + +12. ./latency [MIDI input, histogram] +Choose timer period (in ms, >= 1): >>1 +? >>2 [MIDI input option] +Midi input device number: >>6 [pick a working input device] +[wait about 5 seconds, play input for 10 seconds ] +>> [type ENTER] +[output should be something like ... Maximum latency: 3 milliseconds] + +13. ./latency [MIDI output, histogram] +Choose timer period (in ms, >= 1): >>1 +? >>3 [MIDI output option] +Midi output device number: >>2 [pick a working output device] +Midi output should be sent every __ callback iterations: >>50 +[wait until you hear notes for 5 or 10 seconds] +>> [type ENTER to stop] +[output should be something like ... Maximum latency: 2 milliseconds] + +14. ./latency [MIDI input and output, histogram] +Choose timer period (in ms, >= 1): >>1 +? >>4 [MIDI input and output option] +Midi input device number: >>6 [pick a working input device] +Midi output device number: >>2 [pick a working output device] +Midi output should be sent every __ callback iterations: >>50 +[wait until you hear notes, simultaneously play notes for 5 or 10 seconds] +>> [type ENTER to stop] +[output should be something like ... Maximum latency: 1 milliseconds] + +15. ./mm [test with device input] +Type input device number: >>6 [pick a working input device] +[play some notes, see notes printed] +>>q [Type q ENTER when finished to exit] + +16. ./midithread -i 6 -o 2 [use working input/output device numbers] +>>5 [enter a transposition number] +[play some notes, hear parallel 4ths] +>>q [quit after ENTER a couple of times] + +17. ./midiclock [in one shell] + ./mm [in another shell] +[Goal is send clock messages to MIDI monitor program. This requires + either a hardware loopback (MIDI cable from OUT to IN on interface) + or a software loopback (macOS IAC bus or ALSA MIDI Through Port)] +[For midiclock application:] + Type output device number: >>0 [pick a device with loopback] + Type ENTER to start MIDI CLOCK: >> [type ENTER] +[For mm application:] + Type input device number: >>1 [pick device with loopback] + [Wait a few seconds] + >>s [to get Clock Count] + >>s [expect to get a higher Clock Count] +[For midiclock application:] + >>c [turn off clocks] +[For mm application:] + >>s [to get Clock Count] + >>s [expect to Clock Count stays the same] +[For midiclock application:] + >>t [turn on time code, see Time Code Quarter Frame messages from mm] + >>q [to quit] +[For mm application:] + >>q [to quit] + +18. ./midithru -i 6 -o 2 [use working input/output device numbers] +[Play notes on input evice; notes are sent immediately and also with a + 2 sec delay to the output device; program terminates in 60 seconds or + when you play B3 (B below Middle C)] +>> [ENTER to exit] + +19. ./recvvirtual [in one shell, macOS and Linux only] + ./testio [in another shell] +[For testio application:] + Latency in ms: >>0 + enter your choice... >>4 [test output] + Type output number: >>9 [select the "portmidi (output)" device] + [type ENTER to each prompt, see that recvvirtual "Got message 0" + through "Got message 9"] + >> [ENTER to quit] +[For recvvirtual application:] + >> [ENTER to quit] + +20. ./sendvirtual [in one shell, macOS and Linux only] + ./mm [in another shell] +[For mm application:] + Type input device number: >>10 [select the "portmidi" device] +[For sendvirtual application:] + Type ENTER to send messages: >> [type ENTER] + [see NoteOn and off messages received by mm for Key 60-64] + >> [ENTER to quit] +[For mm application:] + >>q [and ENTER twice to quit] + +21. ./sysex [no latency] +[This requires either a hardware loopback (MIDI cable from OUT to IN + on interface) or a software loopback (macOS IAC bus or ALSA MIDI + Through Port)] +>>l [for loopback test] +Type output device number: >>0 [pick output device to loopback] +Latency in milliseconds: >>0 +Type input device number: >>0 [pick input device for loopback] +[Program will send 100,000 bytes. After awhile, program will quit. + You can read the Cummulative bytes/sec value.] + +22. ./sysex [latency > 0] +[This requires either a hardware loopback (MIDI cable from OUT to IN + on interface) or a software loopback (macOS IAC bus or ALSA MIDI + Through Port)] +>>l [for loopback test] +Type output device number: >>0 [pick output device to loopback] +Latency in milliseconds: >>100 +Type input device number: >>0 [pick input device for loopback] +[Program will send 100,000 bytes. After awhile, program will quit. You + can read the Cummulative bytes/sec value; it is affected by latency.] + +23. ./fast [no latency] + ./fastrcv [in another shell] +[This is a speed check, especially for macOSX IAC bus connections, + which are known to drop messages if you send messages too fast. + fast and fastrcv must use a loopback to function.] +[In fastrcv:] + Input device number: >>1 [pick a non-hardware device if possible] +[In fast:] + Latency in ms: >>0 + Rate in messages per second: >>10000 + Duration in seconds: >>10 + Output device number: >>0 [pick a non-hardware device if possible] + sending output... +[see message counts and times; on Linux you should get about 10000 + messages/s; on macOS you should get about 1800 messages/s; Windows + does not have software ports, so data rate might be limited by the + loopback device you use.] + +Check output of fastrcv: there should be no errors, just msg/sec.] + +24. ./fast [latency > 0] + ./fastrcv [in another shell] +[This is a speed check, especially for macOSX IAC bus connections, + which are known to drop messages if you send messages too fast. + fast and fastrcv must use a loopback to function.] +[In fastrcv:] + Input device number: >>1 [pick a non-hardware device if possible] +[In fast:] + Latency in ms: >>30 [Note for ALSA, use latency * msgs/ms < 400] + Rate in messages per second: >>10000 + Duration in seconds: >>10 + Output device number: >>0 [pick a non-hardware device if possible] + sending output... +[see message counts and times; on Linux you should get about 10000 + messages/s; on macOS you should get about 1800 messages/s; Windows + does not have software ports, so data rate might be limited by the + loopback device you use.] + +Check output of fastrcv: there should be no errors, just msg/sec.] + +25. ./fast [virtual output port, latency = 0, macOS and Linux only] + ./fastrcv [in another shell] +[Start fast first:] + Latency in ms: >>0 + Rate in messages per second: >>10000 + Duration in seconds: >>10 + Output device number: >>9 [enter number listed for "Create virtual + port named 'fast' (output)"] + Pausing so you can connect a receiver to the newly created + "fast" port. Type ENTER to proceed: +[In fastrcv:] + Input device number: >>3 [pick the device named "fast (input)"] +[In fast:] + >> [type ENTER to start] +[see message counts and times as above ] + +Check output of fastrcv: there should be no errors, just msg/sec.] + +26. ./fast [virtual output port, latency > 0, macOS and Linux only] + ./fastrcv [in another shell] +[Start fast first:] + Latency in ms: >>30 [Note for ALSA, use latency * msgs/ms < 400] + Rate in messages per second: >>10000 + Duration in seconds: >>10 + Output device number: >>9 [enter number listed for "Create virtual + port named 'fast' (output)"] + Pausing so you can connect a receiver to the newly created + "fast" port. Type ENTER to proceed: +[In fastrcv:] + Input device number: >>3 [pick the device named "fast (input)"] +[In fast:] + >> [type ENTER to start] +[see message counts and times as above ] + +Check output of fastrcv: there should be no errors, just msg/sec.] + +27. ./fast [latency = 0, macOS and Linux only] + ./fastrcv [virtual input port, in another shell] +[In fastrcv:] + Input device number: >>8 [enter number listed for "Create virtual + port named 'fastrcv' (input)"] +[In fast:] + Latency in ms: >>0 + Rate in messages per second: >>10000 + Duration in seconds: >>10 + Output device number: >>7 [pick the device named "fastrcv (output)"] + sending output... +[see message counts and times as above ] + +Check output of fastrcv: there should be no errors, just msg/sec.] + +28. ./fast [latency > 0, macOS and Linux only] + ./fastrcv [virtual input port, in another shell] +[In fastrcv:] + Input device number: >>8 [enter number listed for "Create virtual + port named 'fastrcv' (input)"] +[In fast:] + Latency in ms: >>30 [Note for ALSA, use latency * msgs/ms < 400] + Rate in messages per second: >>10000 + Duration in seconds: >>10 + Output device number: >>7 [pick the device named "fastrcv (output)"] + sending output... +[see message counts and times as above ] + +Check output of fastrcv: there should be no errors, just msg/sec.] + +29. ./midithru -v -n [virtual input and output, macOS and Linux only] + ./fast [latency = 0] + ./fastrcv [in another shell] +[Start midithru first, it will run for 60 seconds] +[In fastrcv:] + Input device number: >>3 [pick the device named + port named "midithru (input)"] +[In fast:] + Latency in ms: >>0 + Rate in messages per second: >>10000 + Duration in seconds: >>10 + Output device number: >>8 [pick the device named "midithru (output)"] + sending output... +[see message counts and times as above, on Mac, output from fast to + midithru AND output from midithru to fastrcv are rate limited, so + as in other tests, it will take more than 10s to receive all the + messages and the receiving message rate will be about 1800 messages/second] + +30. ./multivirtual [macOS and Linux only] + ./testio + ./testio +[Start multivirtual first] +[In first testio:] + Latency in ms: >>0 + enter your choice... >>5 [test both] + Type input number: >>1 [pick portmidi1 (input) + Type output number: >>4 [pick portmidi1 (output) +[In second testio:] + Latency in ms: >>10 + enter your choice... >>5 [test both] + Type input number: >>2 [pick portmidi2 (input) + Type output number: >>5 [pick portmidi2 (output) +[In multivirtual:] + Type ENTER to send messages: >> [type ENTER to start] +[see that each testio gets 11 messages (0 to 10) at reasonable times + (e.g. 2077 to 7580, and the "@" times (real times) should match the + timestamps). multivirtual should also report reasonable times and + line near the end of output should be "Got 11 messages from + portmidi1 and 11 from portmidi2; expected 11."] + +31. ./multivirtual [macOS and Linux only] + ./multivirtual +[Second instance should report "PortMidi call failed... + PortMidi: Cannot create virtual device: name is taken"] + +32. pmdefaults (if built, requires Java and some CMake options) + [must be run from pm_java/pmdefaults] + ./testio +[In pmdefaults: + Select an input device. Input should flash the green + test light. + Select an output device. Test button should play a note. + Save the selections. + Quit the program.] +[In testio:] + Latency in ms: >>0 + enter your choice... >>5 [test both] + [In the device list, default devices are marked. They + should match the devices selected with pmdefaults.] + ^C to quit. +33. pmlist + ./pmlist [check the output] + [plug in or remove a device] + >> [type RETURN] + [check for changes in device list] + >>q + + + + diff --git a/3rdparty/portmidi/pm_test/fast.c b/3rdparty/portmidi/pm_test/fast.c new file mode 100644 index 00000000000..102697e456e --- /dev/null +++ b/3rdparty/portmidi/pm_test/fast.c @@ -0,0 +1,290 @@ +/* fast.c -- send many MIDI messages very fast. + * + * This is a stress test created to explore reports of + * pm_write() call blocking (forever) on Linux when + * sending very dense MIDI sequences. + * + * Modified 8 Aug 2017 with -n to send expired timestamps + * to test a theory about why Linux ALSA hangs in Audacity. + * + * Modified 9 Aug 2017 with -m, -p to test when timestamps are + * wrapping from negative to positive or positive to negative. + * + * Roger B. Dannenberg, Aug 2017 + */ + +#include "portmidi.h" +#include "porttime.h" +#include "stdlib.h" +#include "stdio.h" +#include "string.h" +#include "assert.h" + +#define DEVICE_INFO NULL +#define DRIVER_INFO NULL +#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ + +#define STRING_MAX 80 /* used for console input */ +// need to get declaration for Sleep() +#ifdef WIN32 +#include "windows.h" +#else +#include <unistd.h> +#define Sleep(n) usleep(n * 1000) +#endif + + +int32_t latency = 0; +int32_t msgrate = 0; +int deviceno = -9999; +int duration = 0; +int expired_timestamps = FALSE; +int use_timeoffset = 0; + +/* read a number from console */ +/**/ +int get_number(const char *prompt) +{ + int n = 0, i; + fputs(prompt, stdout); + while (n != 1) { + n = scanf("%d", &i); + while (getchar() != '\n') ; + } + return i; +} + + +/* get_time -- the time reference. Normally, this will be the default + * time, Pt_Time(), but if you use the -p or -m option, the time + * reference will start at an offset of -10s for -m, or + * maximum_time - 10s for -p, so that we can observe what happens + * with negative time or when time changes sign or wraps (by + * generating output for more than 10s). + */ +PmTimestamp get_time(void *info) +{ + PmTimestamp now = (PmTimestamp) (Pt_Time() + use_timeoffset); + return now; +} + + +void fast_test() +{ + PmStream *midi; + char line[STRING_MAX]; + int pause = FALSE; /* pause if this is a virtual output port */ + PmError err = pmNoError; + /* output buffer size should be a little more than + msgrate * latency / 1000. PortMidi will guarantee + a minimum of latency / 2 */ + int buffer_size = msgrate * latency / 900; + PmTimestamp start, now; + int msgcnt = 0; + int polling_count = 0; + int pitch = 60; + int printtime = 1000; + + /* It is recommended to start timer before PortMidi */ + TIME_START; + + /* open output device */ + if (deviceno == Pm_CountDevices()) { + deviceno = Pm_CreateVirtualOutput("fast", NULL, DEVICE_INFO); + if (deviceno >= 0) { + err = Pm_OpenOutput(&midi, deviceno, DRIVER_INFO, buffer_size, + get_time, NULL, latency); + pause = TRUE; + } + } else if (err >= pmNoError) { + err = Pm_OpenOutput(&midi, deviceno, DRIVER_INFO, buffer_size, + get_time, NULL, latency); + } + if (err == pmHostError) { + Pm_GetHostErrorText(line, STRING_MAX); + printf("PortMidi found host error...\n %s\n", line); + goto done; + } else if (err < 0) { + printf("PortMidi call failed...\n %s\n", Pm_GetErrorText(err)); + goto done; + } + printf("Midi Output opened with %ld ms latency.\n", (long) latency); + if (pause) { + printf("Pausing so you can connect a receiver to the newly created\n" + " \"fast\" port. Type ENTER to proceed: "); + while (getchar() != '\n') ; + } + /* wait a sec after printing previous line */ + start = get_time(NULL) + 1000; + while (start > get_time(NULL)) { + Sleep(10); + } + printf("sending output...\n"); + fflush(stdout); /* make sure message goes to console */ + + /* every 10ms send on/off pairs at timestamps set to current time */ + now = get_time(NULL); + /* if expired_timestamps, we want to send timestamps that have + * expired. They should be sent immediately, but there's a suggestion + * that negative delay might cause problems in the ALSA implementation + * so this is something we can test using the -n flag. + */ + if (expired_timestamps) { + now = now - 2 * latency; + } + + while (((PmTimestamp) (now - start)) < duration * 1000 || pitch != 60) { + /* how many messages do we send? Total should be + * (elapsed * rate) / 1000 + */ + int send_total = (((PmTimestamp) ((now - start))) * msgrate) / 1000; + /* always send until pitch would be 60 so if we run again, the + next pitch (60) will be expected */ + if (msgcnt < send_total) { + if ((msgcnt & 1) == 0) { + Pm_WriteShort(midi, now, Pm_Message(0x90, pitch, 100)); + } else { + Pm_WriteShort(midi, now, Pm_Message(0x90, pitch, 0)); + /* play 60, 61, 62, ... 71, then wrap back to 60, 61, ... */ + pitch = (pitch - 59) % 12 + 60; + } + msgcnt += 1; + if (((PmTimestamp) (now - start)) >= printtime) { + printf("%d at %dms, polling count %d\n", msgcnt, now - start, + polling_count); + fflush(stdout); /* make sure message goes to console */ + printtime += 1000; /* next msg in 1s */ + } + } + now = get_time(NULL); + polling_count++; + } + /* close device (this not explicitly needed in most implementations) */ + printf("ready to close and terminate... (type RETURN):"); + while (getchar() != '\n') ; + + Pm_Close(midi); + done: + Pm_Terminate(); + printf("done closing and terminating...\n"); +} + + +void show_usage() +{ + printf("Usage: fast [-h] [-l latency] [-r rate] [-d device] [-s dur] " + "[-n] [-p] [-m]\n" + ", where latency is in ms,\n" + " rate is messages per second,\n" + " device is the PortMidi device number,\n" + " dur is the length of the test in seconds,\n" + " -n means send timestamps in the past,\n" + " -p means use a large positive time offset,\n" + " -m means use a large negative time offset, and\n" + " -h means help.\n"); +} + +int main(int argc, char *argv[]) +{ + int default_in; + int default_out; + char *deflt; + int i = 0; + int latency_valid = FALSE; + int rate_valid = FALSE; + int device_valid = FALSE; + int dur_valid = FALSE; + + if (sizeof(void *) == 8) + printf("Apparently this is a 64-bit machine.\n"); + else if (sizeof(void *) == 4) + printf ("Apparently this is a 32-bit machine.\n"); + + if (argc <= 1) { + show_usage(); + } else { + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-h") == 0) { + show_usage(); + } else if (strcmp(argv[i], "-l") == 0 && (i + 1 < argc)) { + i = i + 1; + latency = atoi(argv[i]); + printf("Latency will be %ld\n", (long) latency); + latency_valid = TRUE; + } else if (strcmp(argv[i], "-r") == 0) { + i = i + 1; + msgrate = atoi(argv[i]); + printf("Rate will be %d messages/second\n", msgrate); + rate_valid = TRUE; + } else if (strcmp(argv[i], "-d") == 0) { + i = i + 1; + deviceno = atoi(argv[i]); + printf("Device will be %d\n", deviceno); + } else if (strcmp(argv[i], "-s") == 0) { + i = i + 1; + duration = atoi(argv[i]); + printf("Duration will be %d seconds\n", duration); + dur_valid = TRUE; + } else if (strcmp(argv[i], "-n") == 0) { + printf("Sending expired timestamps (-n)\n"); + expired_timestamps = TRUE; + } else if (strcmp(argv[i], "-p") == 0) { + printf("Time offset set to 2147473648 (-p)\n"); + use_timeoffset = 2147473648; + } else if (strcmp(argv[i], "-m") == 0) { + printf("Time offset set to -10000 (-m)\n"); + use_timeoffset = -10000; + } else { + show_usage(); + } + } + } + + if (!latency_valid) { + // coerce to known size + latency = (int32_t) get_number("Latency in ms: "); + } + + if (!rate_valid) { + // coerce from "%d" to known size + msgrate = (int32_t) get_number("Rate in messages per second: "); + } + + if (!dur_valid) { + duration = get_number("Duration in seconds: "); + } + + /* list device information */ + default_in = Pm_GetDefaultInputDeviceID(); + default_out = Pm_GetDefaultOutputDeviceID(); + for (i = 0; i < Pm_CountDevices(); i++) { + const PmDeviceInfo *info = Pm_GetDeviceInfo(i); + if (info->output) { + printf("%d: %s, %s", i, info->interf, info->name); + if (i == deviceno) { + device_valid = TRUE; + deflt = "selected "; + } else if (i == default_out) { + deflt = "default "; + } else { + deflt = ""; + } + printf(" (%soutput)\n", deflt); + } + } + printf("%d: Create virtual port named \"fast\"", i); + if (i == deviceno) { + device_valid = TRUE; + deflt = "selected "; + } else { + deflt = ""; + } + printf(" (%soutput)\n", deflt); + + if (!device_valid) { + deviceno = get_number("Output device number: "); + } + + fast_test(); + return 0; +} diff --git a/3rdparty/portmidi/pm_test/fastrcv.c b/3rdparty/portmidi/pm_test/fastrcv.c new file mode 100644 index 00000000000..daee40c5fa0 --- /dev/null +++ b/3rdparty/portmidi/pm_test/fastrcv.c @@ -0,0 +1,255 @@ +/* fastrcv.c -- send many MIDI messages very fast. + * + * This is a stress test created to explore reports of + * pm_write() call blocking (forever) on Linux when + * sending very dense MIDI sequences. + * + * Modified 8 Aug 2017 with -n to send expired timestamps + * to test a theory about why Linux ALSA hangs in Audacity. + * + * Roger B. Dannenberg, Aug 2017 + */ + +#include "portmidi.h" +#include "porttime.h" +#include "stdlib.h" +#include "stdio.h" +#include "string.h" +#include "assert.h" + +#define INPUT_BUFFER_SIZE 1000 /* big to avoid losing any input */ +#define DEVICE_INFO NULL +#define DRIVER_INFO NULL +#define TIME_PROC ((PmTimeProcPtr) Pt_Time) +#define TIME_INFO NULL +#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ + +#define STRING_MAX 80 /* used for console input */ +// need to get declaration for Sleep() +#ifdef WIN32 +#include "windows.h" +#else +#include <unistd.h> +#define Sleep(n) usleep(n * 1000) +#endif + + +int deviceno = -9999; +int verbose = FALSE; + + +static void prompt_and_exit(void) +{ + printf("type ENTER..."); + while (getchar() != '\n') ; + /* this will clean up open ports: */ + exit(-1); +} + + +static PmError checkerror(PmError err) +{ + if (err == pmHostError) { + /* it seems pointless to allocate memory and copy the string, + * so I will do the work of Pm_GetHostErrorText directly + */ + char errmsg[80]; + Pm_GetHostErrorText(errmsg, 80); + printf("PortMidi found host error...\n %s\n", errmsg); + prompt_and_exit(); + } else if (err < 0) { + printf("PortMidi call failed...\n %s\n", Pm_GetErrorText(err)); + prompt_and_exit(); + } + return err; +} + + +/* read a number from console */ +/**/ +int get_number(const char *prompt) +{ + int n = 0, i; + fputs(prompt, stdout); + while (n != 1) { + n = scanf("%d", &i); + while (getchar() != '\n') ; + } + return i; +} + + +void fastrcv_test() +{ + PmStream * midi; + PmError status, length; + PmEvent buffer[1]; + PmTimestamp start; + /* every 10ms read all messages, keep counts */ + /* every 1000ms, print report */ + int msgcnt = 0; + /* expect repeating sequence of 60 through 71, alternating on/off */ + int expected_pitch = 60; + int expected_on = TRUE; + int report_time; + PmTimestamp last_timestamp = -1; + PmTimestamp last_delta = -1; + + /* It is recommended to start timer before PortMidi */ + TIME_START; + + /* open output device */ + if (deviceno == Pm_CountDevices()) { + int id = Pm_CreateVirtualInput("fastrcv", NULL, DEVICE_INFO); + if (id < 0) checkerror(id); /* error reporting */ + checkerror(Pm_OpenInput(&midi, id, DRIVER_INFO, + INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO)); + } else { + Pm_OpenInput(&midi, deviceno, DRIVER_INFO, INPUT_BUFFER_SIZE, + TIME_PROC, TIME_INFO); + } + printf("Midi Input opened.\n"); + + /* wait a sec after printing previous line */ + start = Pt_Time() + 1000; + while (start > Pt_Time()) { + Sleep(10); + } + + report_time = Pt_Time() + 1000; /* report every 1s */ + while (TRUE) { + PmTimestamp now = Pt_Time(); + status = Pm_Poll(midi); + if (status == TRUE) { + length = Pm_Read(midi, buffer, 1); + if (length > 0) { + int status = Pm_MessageStatus(buffer[0].message); + if (status == 0x80) { /* convert NoteOff to NoteOn, vel=0 */ + status = 0x90; + buffer[0].message = Pm_Message(status, + Pm_MessageData1(buffer[0].message), 0); + } + /* only listen to NOTEON messages */ + if (status == 0x90) { + int pitch = Pm_MessageData1(buffer[0].message); + int vel = Pm_MessageData2(buffer[0].message); + int is_on = (vel > 0); + if (verbose) { + printf("Note pitch %d vel %d\n", pitch, vel); + } + msgcnt++; + if (pitch != expected_pitch || expected_on != is_on) { + printf("Unexpected note-on: pitch %d vel %d, " + "expected: pitch %d Note%s\n", pitch, vel, + expected_pitch, (expected_on ? "On" : "Off")); + } + if (is_on) { + expected_on = FALSE; + expected_pitch = pitch; + } else { + expected_on = TRUE; + expected_pitch = (pitch + 1) % 72; + if (expected_pitch < 60) expected_pitch = 60; + } + if (last_timestamp >= 0) { + last_delta = buffer[0].timestamp - last_timestamp; + } + last_timestamp = buffer[0].timestamp; + } + } + } + if (now >= report_time) { + printf("%d msgs/sec", msgcnt); + /* if available, print the last timestamp and last delta time */ + if (last_timestamp >= 0) { + printf(" last timestamp %d", (int) last_timestamp); + last_timestamp = -1; + } + if (last_delta >= 0) { + printf(" last delta time %d", (int) last_delta); + last_delta = -1; + } + printf("\n"); + report_time += 1000; + msgcnt = 0; + } + } +} + + +void show_usage() +{ + printf("Usage: fastrcv [-h] [-v] [-d device], where\n" + "device is the PortMidi device number,\n" + "-h means help,\n" + "-v means verbose (print messages)\n"); +} + +int main(int argc, char *argv[]) +{ + int default_in; + int default_out; + char *deflt; + + int i = 0, n = 0; + int test_input = 0, test_output = 0, test_both = 0, somethingStupid = 0; + int stream_test = 0; + int device_valid = FALSE; + + if (sizeof(void *) == 8) + printf("Apparently this is a 64-bit machine.\n"); + else if (sizeof(void *) == 4) + printf ("Apparently this is a 32-bit machine.\n"); + + if (argc <= 1) { + show_usage(); + } else { + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-h") == 0) { + show_usage(); + } else if (strcmp(argv[i], "-v") == 0) { + verbose = TRUE; + } else if (strcmp(argv[i], "-d") == 0) { + i = i + 1; + deviceno = atoi(argv[i]); + printf("Device will be %d\n", deviceno); + } else { + show_usage(); + } + } + } + + /* list device information */ + default_in = Pm_GetDefaultInputDeviceID(); + default_out = Pm_GetDefaultOutputDeviceID(); + for (i = 0; i < Pm_CountDevices(); i++) { + const PmDeviceInfo *info = Pm_GetDeviceInfo(i); + if (!info->output) { + printf("%d: %s, %s", i, info->interf, info->name); + if (i == deviceno) { + device_valid = TRUE; + deflt = "selected "; + } else if (i == default_out) { + deflt = "default "; + } else { + deflt = ""; + } + printf(" (%sinput)\n", deflt); + } + } + printf("%d: Create virtual port named \"fastrcv\"", i); + if (i == deviceno) { + device_valid = TRUE; + deflt = "selected "; + } else { + deflt = ""; + } + printf(" (%sinput)\n", deflt); + + if (!device_valid) { + deviceno = get_number("Input device number: "); + } + + fastrcv_test(); + return 0; +} diff --git a/3rdparty/portmidi/pm_test/latency.c b/3rdparty/portmidi/pm_test/latency.c index bfcdc0ca0a3..fe355511c1e 100644 --- a/3rdparty/portmidi/pm_test/latency.c +++ b/3rdparty/portmidi/pm_test/latency.c @@ -87,7 +87,7 @@ CHANGE LOG #define min(a, b) ((a) <= (b) ? (a) : (b)) #endif -int get_number(char *prompt); +int get_number(const char *prompt); PtTimestamp previous_callback_time = 0; @@ -116,7 +116,7 @@ void pt_callback(PtTimestamp timestamp, void *userData) /* send a note on/off if user requested it */ if (test_out && (iteration % output_period == 0)) { PmEvent buffer[1]; - buffer[0].timestamp = Pt_Time(NULL); + buffer[0].timestamp = Pt_Time(); if (note_on) { /* note off */ buffer[0].message = Pm_Message(0x90, 60, 0); @@ -157,7 +157,6 @@ void pt_callback(PtTimestamp timestamp, void *userData) int main() { - char line[STRING_MAX]; int i; int len; int choice; @@ -231,17 +230,17 @@ int main() } } - printf("%s%s", "Latency measurements will start in 5 seconds. ", - "Type return to stop: "); + printf("Latency measurements will start in 5 seconds. " + "Type return to stop: "); Pt_Start(period, &pt_callback, 0); - fgets(line, STRING_MAX, stdin); + while (getchar() != '\n') ; stop = Pt_Time(); Pt_Stop(); /* courteously turn off the last note, if necessary */ if (note_on) { PmEvent buffer[1]; - buffer[0].timestamp = Pt_Time(NULL); + buffer[0].timestamp = Pt_Time(); buffer[0].message = Pm_Message(0x90, 60, 0); Pm_Write(out, buffer, 1); } @@ -260,7 +259,7 @@ int main() printf("\nNote that due to rounding, actual latency can be 1ms higher\n"); printf("than the numbers reported here.\n"); printf("Type return to exit..."); - fgets(line, STRING_MAX, stdin); + while (getchar() != '\n') ; if(choice == 2) Pm_Close(in); @@ -276,15 +275,13 @@ int main() /* read a number from console */ -int get_number(char *prompt) -{ - char line[STRING_MAX]; +int get_number(const char *prompt) +{ int n = 0, i; - printf(prompt); + fputs(prompt, stdout); while (n != 1) { n = scanf("%d", &i); - fgets(line, STRING_MAX, stdin); - + while (getchar() != '\n') ; } return i; } diff --git a/3rdparty/portmidi/pm_test/latency.vcproj b/3rdparty/portmidi/pm_test/latency.vcproj deleted file mode 100644 index 9a79300abdc..00000000000 --- a/3rdparty/portmidi/pm_test/latency.vcproj +++ /dev/null @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="latency" - ProjectGUID="{41D78CBF-B04B-4561-BA4A-AC238C40633D}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="latency.dir\Debug" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="1" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Debug/latency.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Debug\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Debug\latency.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Debug/latency.pdb" - GenerateDebugInformation="TRUE" - SubSystem="1" - ImportLibrary="..\pm_test\Debug\latency.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="latency.dir\Release" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="0" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Release/latency.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Release\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Release\latency.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Release/latency.pdb" - SubSystem="1" - ImportLibrary="..\pm_test\Release\latency.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_test\latency.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_test/midiclock.c b/3rdparty/portmidi/pm_test/midiclock.c index 60fcf7a9aad..f0a68974a1c 100644 --- a/3rdparty/portmidi/pm_test/midiclock.c +++ b/3rdparty/portmidi/pm_test/midiclock.c @@ -24,7 +24,7 @@ typedef int boolean; #define OUTPUT_BUFFER_SIZE 0 #define DRIVER_INFO NULL -#define TIME_PROC ((int32_t (*)(void *)) Pt_Time) +#define TIME_PROC ((PmTimeProcPtr) Pt_Time) #define TIME_INFO NULL #define LATENCY 0 #define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ @@ -163,15 +163,13 @@ void timer_poll(PtTimestamp timestamp, void *userData) /* read a number from console */ /**/ -int get_number(char *prompt) +int get_number(const char *prompt) { - char line[STRING_MAX]; int n = 0, i; - printf(prompt); + fputs(prompt, stdout); while (n != 1) { n = scanf("%d", &i); - fgets(line, STRING_MAX, stdin); - + while (getchar() != '\n') ; } return i; } @@ -236,7 +234,6 @@ private void doascii(char c) */ int main(int argc, char **argv) { - char s[STRING_MAX]; /* console input */ int outp; PmError err; int i; @@ -256,22 +253,20 @@ int main(int argc, char **argv) err = Pm_OpenOutput(&midi, outp, DRIVER_INFO, OUTPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO, LATENCY); if (err) { - printf(Pm_GetErrorText(err)); + puts(Pm_GetErrorText(err)); goto error_exit_no_device; } active = true; - printf("Type RETURN to start MIDI CLOCK:\n"); - if (!fgets(s, STRING_MAX, stdin)) goto error_exit; + printf("Type ENTER to start MIDI CLOCK:\n"); + while (getchar() != '\n') ; send_start_stop = true; /* send START and then CLOCKs */ while (!done) { - if (fgets(s, STRING_MAX, stdin)) { - doascii(s[0]); - } + doascii(getchar()); + while (getchar() != '\n') ; } - error_exit: active = false; Pt_Sleep(2); /* this is to allow callback to complete -- it's real time, so it's either ok and it runs on diff --git a/3rdparty/portmidi/pm_test/midiclock.vcproj b/3rdparty/portmidi/pm_test/midiclock.vcproj deleted file mode 100644 index 2c9cf02e9c5..00000000000 --- a/3rdparty/portmidi/pm_test/midiclock.vcproj +++ /dev/null @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="midiclock" - ProjectGUID="{9B448D22-EC7E-4BD8-A552-B268D843CC3C}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="midiclock.dir\Debug" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="1" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Debug/midiclock.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Debug\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Debug\midiclock.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Debug/midiclock.pdb" - GenerateDebugInformation="TRUE" - SubSystem="1" - ImportLibrary="..\pm_test\Debug\midiclock.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="midiclock.dir\Release" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="0" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Release/midiclock.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Release\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Release\midiclock.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Release/midiclock.pdb" - SubSystem="1" - ImportLibrary="..\pm_test\Release\midiclock.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_test\midiclock.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_test/midithread.c b/3rdparty/portmidi/pm_test/midithread.c index fab9794f2da..ea0613bc5eb 100644 --- a/3rdparty/portmidi/pm_test/midithread.c +++ b/3rdparty/portmidi/pm_test/midithread.c @@ -164,22 +164,36 @@ void process_midi(PtTimestamp timestamp, void *userData) void exit_with_message(char *msg) { - char line[STRING_MAX]; printf("%s\n", msg); - fgets(line, STRING_MAX, stdin); + while (getchar() != '\n') ; exit(1); } -int main() +int main(int argc, char *argv[]) { - int id; int32_t n; const PmDeviceInfo *info; char line[STRING_MAX]; int spin; int done = FALSE; - - /* determine what type of test to run */ + int i; + int input = -1, output = -1; + + printf("Usage: midithread [-i input] [-o output]\n" + "where input and output are portmidi device numbers\n"); + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-i") == 0) { + i++; + input = atoi(argv[i]); + printf("Input device number: %d\n", input); + } else if (strcmp(argv[i], "-o") == 0) { + i++; + output = atoi(argv[i]); + printf("Output device number: %d\n", output); + } else { + return -1; + } + } printf("begin PortMidi multithread test...\n"); /* note that it is safe to call PortMidi from the main thread for @@ -221,32 +235,32 @@ int main() Pm_Initialize(); - id = Pm_GetDefaultOutputDeviceID(); - info = Pm_GetDeviceInfo(id); + output = (output < 0 ? Pm_GetDefaultOutputDeviceID() : output); + info = Pm_GetDeviceInfo(output); if (info == NULL) { - printf("Could not open default output device (%d).", id); + printf("Could not open output device (%d).", output); exit_with_message(""); } printf("Opening output device %s %s\n", info->interf, info->name); /* use zero latency because we want output to be immediate */ - Pm_OpenOutput(&midi_out, - id, + Pm_OpenOutput(&midi_out, + output, DRIVER_INFO, OUTPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO, LATENCY); - id = Pm_GetDefaultInputDeviceID(); - info = Pm_GetDeviceInfo(id); + input = (input < 0 ? Pm_GetDefaultInputDeviceID() : input); + info = Pm_GetDeviceInfo(input); if (info == NULL) { - printf("Could not open default input device (%d).", id); + printf("Could not open default input device (%d).", input); exit_with_message(""); } printf("Opening input device %s %s\n", info->interf, info->name); Pm_OpenInput(&midi_in, - id, + input, DRIVER_INFO, INPUT_BUFFER_SIZE, TIME_PROC, @@ -257,18 +271,17 @@ int main() this simple assignment is safe */ printf("Enter midi input; it will be transformed as specified by...\n"); - printf("%s\n%s\n%s\n", - "Type 'q' to quit, 'm' to monitor next pitch, t to toggle thru or", - "type a number to specify transposition.", - "Must terminate with [ENTER]"); + printf("Type 'q' to quit, 'm' to monitor next pitch, t to toggle thru or\n" + "type a number to specify transposition.\n" + "Must terminate with [ENTER]\n"); while (!done) { int32_t msg; int input; int len; - fgets(line, STRING_MAX, stdin); + if (!fgets(line, STRING_MAX, stdin)) break; /* no stdin? */ /* remove the newline: */ - len = strlen(line); + len = (int) strlen(line); if (len > 0) line[len - 1] = 0; /* overwrite the newline char */ if (strcmp(line, "q") == 0) { msg = QUIT_MSG; @@ -323,7 +336,8 @@ int main() Pm_Close(midi_in); Pm_Close(midi_out); - printf("finished portMidi multithread test...enter any character to quit [RETURN]..."); - fgets(line, STRING_MAX, stdin); + fputs("finished portMidi multithread test.\n" + "type ENTER to quit:", stdout); + while (getchar() != '\n') ; return 0; } diff --git a/3rdparty/portmidi/pm_test/midithread.vcproj b/3rdparty/portmidi/pm_test/midithread.vcproj deleted file mode 100644 index 83c82a7bec0..00000000000 --- a/3rdparty/portmidi/pm_test/midithread.vcproj +++ /dev/null @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="midithread" - ProjectGUID="{EED7440D-04E3-4948-92DB-C85B4ADB1D82}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="midithread.dir\Debug" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="1" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Debug/midithread.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Debug\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Debug\midithread.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Debug/midithread.pdb" - GenerateDebugInformation="TRUE" - SubSystem="1" - ImportLibrary="..\pm_test\Debug\midithread.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="midithread.dir\Release" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="0" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Release/midithread.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Release\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Release\midithread.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Release/midithread.pdb" - SubSystem="1" - ImportLibrary="..\pm_test\Release\midithread.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_test\midithread.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_test/midithru.c b/3rdparty/portmidi/pm_test/midithru.c index 8ad723138e4..a9df5ccf5e6 100644 --- a/3rdparty/portmidi/pm_test/midithru.c +++ b/3rdparty/portmidi/pm_test/midithru.c @@ -1,18 +1,21 @@ /* midithru.c -- example program implementing background thru processing */ -/* suppose you want low-latency midi-thru processing, but your application - wants to take advantage of the input buffer and timestamped data so that - it does not have to operate with very low latency. - - This program illustrates how to use a timer callback from PortTime to - implement a low-latency process that handles midi thru, including correctly - merging midi data from the application with midi data from the input port. - - The main application, which runs in the main program thread, will use an - interface similar to that of PortMidi, but since PortMidi does not allow - concurrent threads to share access to a stream, the application will - call private methods that transfer MIDI messages to and from the timer - thread. All PortMidi API calls are made from the timer thread. +/* suppose you want low-latency midi-thru processing, but your + application wants to take advantage of the input buffer and + timestamped data so that it does not have to operate with very low + latency. + + This program illustrates how to use a timer callback from PortTime + to implement a low-latency process that handles midi thru, + including correctly merging midi data from the application with + midi data from the input port. + + The main application, which runs in the main program thread, will + use an interface similar to that of PortMidi, but since PortMidi + does not allow concurrent threads to share access to a stream, the + application will call private methods that transfer MIDI messages + to and from the timer thread using lock-free queues. All PortMidi + API calls are made from the timer thread. */ /* DESIGN @@ -78,11 +81,14 @@ global variable current_timestamp. #define MIDI_SYSEX 0xf0 #define MIDI_EOX 0xf7 +#define STRING_MAX 80 /* used for console input */ -/* active is set true when midi processing should start */ +/* active is set true when midi processing should start, must be + * volatile to force thread to check for updates by other thread */ int active = FALSE; -/* process_midi_exit_flag is set when the timer thread shuts down */ -int process_midi_exit_flag; +/* process_midi_exit_flag is set when the timer thread shuts down; + * must be volatile so it is re-read in the while loop that waits on it */ +volatile int process_midi_exit_flag; PmStream *midi_in; PmStream *midi_out; @@ -92,12 +98,43 @@ PmStream *midi_out; #define OUT_QUEUE_SIZE 1024 PmQueue *in_queue; PmQueue *out_queue; -PmTimestamp current_timestamp = 0; +/* this is volatile because it is set in the process_midi callback and + * the main thread reads it to sense elapsed time. Without volatile, the + * optimizer can put it in a register and not see the updates. + */ +volatile PmTimestamp current_timestamp = 0; int thru_sysex_in_progress = FALSE; int app_sysex_in_progress = FALSE; PmTimestamp last_timestamp = 0; +static void prompt_and_exit(void) +{ + printf("type ENTER..."); + while (getchar() != '\n') ; + /* this will clean up open ports: */ + exit(-1); +} + + +static PmError checkerror(PmError err) +{ + if (err == pmHostError) { + /* it seems pointless to allocate memory and copy the string, + * so I will do the work of Pm_GetHostErrorText directly + */ + char errmsg[80]; + Pm_GetHostErrorText(errmsg, 80); + printf("PortMidi found host error...\n %s\n", errmsg); + prompt_and_exit(); + } else if (err < 0) { + printf("PortMidi call failed...\n %s\n", Pm_GetErrorText(err)); + prompt_and_exit(); + } + return err; +} + + /* time proc parameter for Pm_MidiOpen */ PmTimestamp midithru_time_proc(void *info) { @@ -117,8 +154,6 @@ void process_midi(PtTimestamp timestamp, void *userData) PmEvent buffer; /* just one message at a time */ current_timestamp++; /* update every millisecond */ - /* if (current_timestamp % 1000 == 0) - printf("time %d\n", current_timestamp); */ /* do nothing until initialization completes */ if (!active) { @@ -222,14 +257,13 @@ void process_midi(PtTimestamp timestamp, void *userData) void exit_with_message(char *msg) { #define STRING_MAX 80 - char line[STRING_MAX]; printf("%s\nType ENTER...", msg); - fgets(line, STRING_MAX, stdin); + while (getchar() != '\n') ; exit(1); } -void initialize() +void initialize(int input, int output, int virtual) /* set up midi processing thread and open midi streams */ { /* note that it is safe to call PortMidi from the main thread for @@ -246,7 +280,6 @@ void initialize() */ const PmDeviceInfo *info; - int id; /* make the message queues */ in_queue = Pm_QueueCreate(IN_QUEUE_SIZE, sizeof(PmEvent)); @@ -260,36 +293,63 @@ void initialize() Pm_Initialize(); - id = Pm_GetDefaultOutputDeviceID(); - info = Pm_GetDeviceInfo(id); - if (info == NULL) { - printf("Could not open default output device (%d).", id); - exit_with_message(""); + if (output < 0) { + if (!virtual) { + output = Pm_GetDefaultOutputDeviceID(); + } } - printf("Opening output device %s %s\n", info->interf, info->name); - - /* use zero latency because we want output to be immediate */ - Pm_OpenOutput(&midi_out, - id, - NULL /* driver info */, - OUT_QUEUE_SIZE, - &midithru_time_proc, - NULL /* time info */, - 0 /* Latency */); - - id = Pm_GetDefaultInputDeviceID(); - info = Pm_GetDeviceInfo(id); - if (info == NULL) { - printf("Could not open default input device (%d).", id); - exit_with_message(""); + if (output >= 0) { + info = Pm_GetDeviceInfo(output); + if (info == NULL) { + printf("Could not open default output device (%d).", output); + exit_with_message(""); + } + + printf("Opening output device %s %s\n", info->interf, info->name); + + /* use zero latency because we want output to be immediate */ + Pm_OpenOutput(&midi_out, + output, + NULL /* driver info */, + OUT_QUEUE_SIZE, + &midithru_time_proc, + NULL /* time info */, + 0 /* Latency */); + } else { /* send to virtual port */ + int id; + printf("Opening virtual output device \"midithru\"\n"); + id = Pm_CreateVirtualOutput("midithru", NULL, NULL); + if (id < 0) checkerror(id); /* error reporting */ + checkerror(Pm_OpenOutput(&midi_out, id, NULL, OUT_QUEUE_SIZE, + &midithru_time_proc, NULL, 0)); + } + if (input < 0) { + if (!virtual) { + input = Pm_GetDefaultInputDeviceID(); + } + } + if (input >= 0) { + info = Pm_GetDeviceInfo(input); + if (info == NULL) { + printf("Could not open default input device (%d).", input); + exit_with_message(""); + } + + printf("Opening input device %s %s\n", info->interf, info->name); + Pm_OpenInput(&midi_in, + input, + NULL /* driver info */, + 0 /* use default input size */, + &midithru_time_proc, + NULL /* time info */); + } else { /* receive from virtual port */ + int id; + printf("Opening virtual input device \"midithru\"\n"); + id = Pm_CreateVirtualInput("midithru", NULL, NULL); + if (id < 0) checkerror(id); /* error reporting */ + checkerror(Pm_OpenInput(&midi_in, id, NULL, 0, + &midithru_time_proc, NULL)); } - printf("Opening input device %s %s\n", info->interf, info->name); - Pm_OpenInput(&midi_in, - id, - NULL /* driver info */, - 0 /* use default input size */, - &midithru_time_proc, - NULL /* time info */); /* Note: if you set a filter here, then this will filter what goes to the MIDI THRU port. You may not want to do this. */ @@ -330,15 +390,42 @@ int main(int argc, char *argv[]) { PmTimestamp last_time = 0; PmEvent buffer; - - /* determine what type of test to run */ + int i; + int input = -1, output = -1; + int virtual = FALSE; + int delay_enable = TRUE; + + printf("Usage: midithru [-i input] [-o output] [-v] [-n]\n" + "where input and output are portmidi device numbers\n" + "if -v and input and/or output are not specified,\n" + "then virtual ports are created and used instead.\n" + "-n turns off the default MIDI delay effect.\n"); + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-i") == 0) { + i++; + input = atoi(argv[i]); + printf("Input device number: %d\n", input); + } else if (strcmp(argv[i], "-o") == 0) { + i++; + output = atoi(argv[i]); + printf("Output device number: %d\n", output); + } else if (strcmp(argv[i], "-v") == 0) { + virtual = TRUE; + } else if (strcmp(argv[i], "-n") == 0) { + delay_enable = FALSE; + printf("delay_effect is disabled\n"); + } else { + return -1; + } + } printf("begin PortMidi midithru program...\n"); - initialize(); /* set up and start midi processing */ + initialize(input, output, virtual); /* set up and start midi processing */ - printf("%s\n%s\n", - "This program will run for 60 seconds, or until you play middle C,", - "echoing all input with a 2 second delay."); + printf("This program will run for 60 seconds, " + "or until you play B below middle C,\n" + "All input is sent immediately, implementing software MIDI THRU.\n" + "Also, all input is echoed with a 2 second delay.\n"); while (current_timestamp < 60000) { /* just to make the point that this is not a low-latency process, @@ -350,11 +437,13 @@ int main(int argc, char *argv[]) while (Pm_Dequeue(in_queue, &buffer) == 1) { /* printf("timestamp %d\n", buffer.timestamp); */ /* printf("message %x\n", buffer.message); */ - buffer.timestamp = buffer.timestamp + 2000; /* delay */ - Pm_Enqueue(out_queue, &buffer); - /* play middle C to break out of loop */ + if (delay_enable) { + buffer.timestamp = buffer.timestamp + 2000; /* delay */ + Pm_Enqueue(out_queue, &buffer); + } + /* play B3 to break out of loop */ if (Pm_MessageStatus(buffer.message) == 0x90 && - Pm_MessageData1(buffer.message) == 60) { + Pm_MessageData1(buffer.message) == 59) { goto quit_now; } } diff --git a/3rdparty/portmidi/pm_test/midithru.vcproj b/3rdparty/portmidi/pm_test/midithru.vcproj deleted file mode 100644 index cf6dfdffe6c..00000000000 --- a/3rdparty/portmidi/pm_test/midithru.vcproj +++ /dev/null @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="midithru" - ProjectGUID="{80193DD1-2C02-4A4C-BDF8-49623AD6F556}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="midithru.dir\Debug" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="1" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Debug/midithru.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Debug\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Debug\midithru.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Debug/midithru.pdb" - GenerateDebugInformation="TRUE" - SubSystem="1" - ImportLibrary="..\pm_test\Debug\midithru.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="midithru.dir\Release" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="0" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Release/midithru.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Release\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Release\midithru.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Release/midithru.pdb" - SubSystem="1" - ImportLibrary="..\pm_test\Release\midithru.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_test\midithru.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_test/mm.c b/3rdparty/portmidi/pm_test/mm.c index 0f2a52ee267..8fe5358b591 100644 --- a/3rdparty/portmidi/pm_test/mm.c +++ b/3rdparty/portmidi/pm_test/mm.c @@ -110,20 +110,18 @@ private void showhelp(); private void showbytes(PmMessage data, int len, boolean newline); private void showstatus(boolean flag); private void doascii(char c); -private int get_number(char *prompt); +private int get_number(const char *prompt); /* read a number from console */ /**/ -int get_number(char *prompt) +int get_number(const char *prompt) { - char line[STRING_MAX]; int n = 0, i; - printf(prompt); + fputs(prompt, stdout); while (n != 1) { n = scanf("%d", &i); - fgets(line, STRING_MAX, stdin); - + while (getchar() != '\n') ; } return i; } @@ -136,7 +134,7 @@ void receive_poll(PtTimestamp timestamp, void *userData) if (!active) return; while ((count = Pm_Read(midi_in, &event, 1))) { if (count == 1) output(event.message); - else printf(Pm_GetErrorText(count)); + else puts(Pm_GetErrorText(count)); } } @@ -160,7 +158,7 @@ int main(int argc, char **argv) /* use porttime callback to empty midi queue and print */ Pt_Start(1, receive_poll, 0); /* list device information */ - printf("MIDI input devices:\n"); + puts("MIDI input devices:"); for (i = 0; i < Pm_CountDevices(); i++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(i); if (info->input) printf("%d: %s, %s\n", i, info->interf, info->name); @@ -168,7 +166,7 @@ int main(int argc, char **argv) inp = get_number("Type input device number: "); err = Pm_OpenInput(&midi_in, inp, NULL, 512, NULL, NULL); if (err) { - printf(Pm_GetErrorText(err)); + puts(Pm_GetErrorText(err)); Pt_Stop(); mmexit(1); } @@ -177,10 +175,8 @@ int main(int argc, char **argv) printf("Midi Monitor ready.\n"); active = true; while (!done) { - char s[100]; - if (fgets(s, 100, stdin)) { - doascii(s[0]); - } + doascii(getchar()); + while (getchar() != '\n') ; } active = false; Pm_Close(midi_in); @@ -484,8 +480,8 @@ private int put_pitch(int p) "gs", "a", "bf", "b" }; /* note octave correction below */ sprintf(result, "%s%d", ptos[p % 12], (p / 12) - 1); - printf(result); - return strlen(result); + fputs(result, stdout); + return (int) strlen(result); } @@ -534,7 +530,8 @@ private void showhelp() printf(" ------------- ----- ------------- -----\n"); printf(" Channels 1 - 16 Programs 1 - 128\n"); printf(" Controllers 0 - 127 After Touch 0 - 127\n"); - printf(" Loudness 0 - 127 Pitch Bend 0 - 16383, center = 8192\n"); + printf(" Loudness 0 - 127 Pitch Bend 0 - 16383, " + "center = 8192\n"); printf(" Pitches 0 - 127, 60 = c4 = middle C\n"); printf(" \n"); printf("n toggles notes"); @@ -568,5 +565,5 @@ private void showhelp() private void showstatus(boolean flag) { - printf(", now %s\n", flag ? "ON" : "OFF" ); + printf(", now %s\n", flag ? "ON" : "OFF"); } diff --git a/3rdparty/portmidi/pm_test/mm.vcproj b/3rdparty/portmidi/pm_test/mm.vcproj deleted file mode 100644 index 78baa9f95ad..00000000000 --- a/3rdparty/portmidi/pm_test/mm.vcproj +++ /dev/null @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="mm" - ProjectGUID="{EAADABB5-83D6-4669-98F8-6CDBE6AFD2BF}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="mm.dir\Debug" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="1" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Debug/mm.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Debug\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Debug\mm.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Debug/mm.pdb" - GenerateDebugInformation="TRUE" - SubSystem="1" - ImportLibrary="..\pm_test\Debug\mm.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="mm.dir\Release" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="0" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Release/mm.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Release\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Release\mm.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Release/mm.pdb" - SubSystem="1" - ImportLibrary="..\pm_test\Release\mm.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_test\mm.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_test/multivirtual.c b/3rdparty/portmidi/pm_test/multivirtual.c new file mode 100644 index 00000000000..059bc50e4f9 --- /dev/null +++ b/3rdparty/portmidi/pm_test/multivirtual.c @@ -0,0 +1,224 @@ +/* multivirtual.c -- test for creating two input and two output virtual ports */ +/* + * Roger B. Dannenberg + * Oct 2021 + */ +#include "portmidi.h" +#include "porttime.h" +#include "stdlib.h" +#include "stdio.h" +#include "string.h" +#include "assert.h" + +#define OUTPUT_BUFFER_SIZE 0 +#define DEVICE_INFO NULL +#define DRIVER_INFO NULL +#define TIME_PROC ((PmTimeProcPtr) Pt_Time) +#define TIME_INFO NULL +#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ + +int latency = 0; + +static void prompt_and_exit(void) +{ + printf("type ENTER..."); + while (getchar() != '\n') ; + /* this will clean up open ports: */ + exit(-1); +} + + +static PmError checkerror(PmError err) +{ + if (err == pmHostError) { + /* it seems pointless to allocate memory and copy the string, + * so I will do the work of Pm_GetHostErrorText directly + */ + char errmsg[80]; + Pm_GetHostErrorText(errmsg, 80); + printf("PortMidi found host error...\n %s\n", errmsg); + prompt_and_exit(); + } else if (err < 0) { + printf("PortMidi call failed...\n %s\n", Pm_GetErrorText(err)); + prompt_and_exit(); + } + return err; +} + +static int msg_count[2] = {0, 0}; + +void poll_input(PmStream *in, int which) +{ + PmEvent buffer[1]; + int pitch, expected, length; + PmError status = Pm_Poll(in); + if (status == TRUE) { + length = Pm_Read(in, buffer, 1); + if (length > 0) { + printf("Got message %d from portmidi%d: " + "time %ld, %2x %2x %2x\n", + msg_count[which], which + 1, (long) buffer[0].timestamp, + (status = Pm_MessageStatus(buffer[0].message)), + (pitch = Pm_MessageData1(buffer[0].message)), + Pm_MessageData2(buffer[0].message)); + if (status == 0x90) { /* 1 & 2 are on/off 60, 3 & 4 are 61, etc. */ + expected = (((msg_count[which] - 1) / 2) % 12) + 60 + + which * 12; + if (pitch != expected) { + printf("WARNING: expected pitch %d, got pitch %d\n", + expected, pitch); + } + } + msg_count[which]++; + } else { + assert(0); + } + } +} + + +void wait_until(PmTimestamp when, PmStream *in1, PmStream *in2) +{ + while (when > Pt_Time()) { + poll_input(in1, 0); + poll_input(in2, 1); + Pt_Sleep(10); + } +} + + +/* create one virtual output device and one input device */ +void init(const char *name, PmStream **midi_out, PmStream **midi_in, + int *id_out, int *id_in) +{ + PmEvent buffer[1]; + + *id_out = checkerror(Pm_CreateVirtualOutput(name, NULL, DEVICE_INFO)); + checkerror(Pm_OpenOutput(midi_out, *id_out, DRIVER_INFO, OUTPUT_BUFFER_SIZE, + TIME_PROC, TIME_INFO, latency)); + printf("Virtual Output \"%s\" id %d created and opened.\n", name, *id_out); + + *id_in = checkerror(Pm_CreateVirtualInput(name, NULL, DRIVER_INFO)); + checkerror(Pm_OpenInput(midi_in, *id_in, NULL, 0, NULL, NULL)); + printf("Virtual Input \"%s\" id %d created and opened.\n", name, *id_in); + Pm_SetFilter(*midi_in, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX); + /* empty the buffer after setting filter, just in case anything + got through */ + while (Pm_Read(*midi_in, buffer, 1)) ; +} + + +void main_test(int num) +{ + PmStream *midi1_out; + PmStream *midi2_out; + PmStream *midi1_in; + PmStream *midi2_in; + int id1_out; + int id2_out; + int id1_in; + int id2_in; + int32_t next_time; + PmEvent buffer[1]; + PmTimestamp timestamp; + int pitch = 60; + int expected_count = num + 1; /* add 1 for MIDI Program message */ + + /* It is recommended to start timer before Midi; otherwise, PortMidi may + start the timer with its (default) parameters + */ + TIME_START; + + init("portmidi1", &midi1_out, &midi1_in, &id1_out, &id1_in); + init("portmidi2", &midi2_out, &midi2_in, &id2_out, &id2_in); + + printf("Type ENTER to send messages: "); + while (getchar() != '\n') ; + + buffer[0].timestamp = Pt_Time(); +#define PROGRAM 0 + buffer[0].message = Pm_Message(0xC0, PROGRAM, 0); + Pm_Write(midi1_out, buffer, 1); + Pm_Write(midi2_out, buffer, 1); + next_time = Pt_Time() + 1000; /* wait 1s */ + while (num > 0) { + wait_until(next_time, midi1_in, midi2_in); + Pm_WriteShort(midi1_out, next_time, Pm_Message(0x90, pitch, 100)); + Pm_WriteShort(midi2_out, next_time, Pm_Message(0x90, pitch + 12, 100)); + printf("Note On pitch %d\n", pitch); + num--; + next_time += 500; + + wait_until(next_time, midi1_in, midi2_in); + Pm_WriteShort(midi1_out, next_time, Pm_Message(0x90, pitch, 0)); + Pm_WriteShort(midi2_out, next_time, Pm_Message(0x90, pitch + 12, 0)); + printf("Note Off pitch %d\n", pitch); + num--; + pitch = (pitch + 1) % 12 + 60; + next_time += 500; + } + wait_until(next_time, midi1_in, midi2_in); /* get final note-offs */ + + printf("Got %d messages from portmidi1 and %d from portmidi2; " + "expected %d.\n", msg_count[0], msg_count[1], expected_count); + + /* close devices (this not explicitly needed in most implementations) */ + printf("ready to close..."); + checkerror(Pm_Close(midi1_out)); + checkerror(Pm_Close(midi2_out)); + checkerror(Pm_Close(midi1_in)); + checkerror(Pm_Close(midi2_in)); + printf("done closing.\nNow delete the virtual devices..."); + checkerror(Pm_DeleteVirtualDevice(id1_out)); + checkerror(Pm_DeleteVirtualDevice(id1_in)); + checkerror(Pm_DeleteVirtualDevice(id2_out)); + checkerror(Pm_DeleteVirtualDevice(id2_in)); + printf("done deleting.\n"); +} + + +void show_usage() +{ + printf("Usage: multivirtual [-h] [-l latency-in-ms] [n]\n" + " -h for this message,\n" + " -l ms designates latency for precise timing (default 0),\n" + " n is number of message to send each output, not counting\n" + " initial program change.\n" + "sends change program to 1, then one note per second with 0.5s on,\n" + "0.5s off, for n/2 seconds to both output ports portmidi1 and\n" + "portmidi2. portmidi1 gets pitches from C4 (60). portmidi2 gets\n" + "pitches an octave higher. Latency >0 uses the device driver for \n" + "precise timing (see PortMidi documentation). Inputs print what\n" + "they get and print WARNING if they get something unexpected.\n" + "The expected test is use two instances of testio to loop\n" + "portmidi1 back to portmidi1 and portmidi2 back to portmidi2.\n"); + exit(0); +} + + +int main(int argc, char *argv[]) +{ + int num = 10; + int i; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-h") == 0) { + show_usage(); + } else if (strcmp(argv[i], "-l") == 0 && (i + 1 < argc)) { + i = i + 1; + latency = atoi(argv[i]); + printf("Latency will be %d\n", latency); + } else { + num = atoi(argv[1]); + if (num <= 0) { + show_usage(); + } + printf("Sending %d messages.\n", num); + } + } + + main_test(num); + + printf("finished sendvirtual test...type ENTER to quit..."); + while (getchar() != '\n') ; + return 0; +} diff --git a/3rdparty/portmidi/pm_test/pmlist.c b/3rdparty/portmidi/pm_test/pmlist.c new file mode 100644 index 00000000000..5e3d1dbc359 --- /dev/null +++ b/3rdparty/portmidi/pm_test/pmlist.c @@ -0,0 +1,63 @@ +/* pmlist.c -- list portmidi devices and numbers + * + * This program lists devices. When you type return, it + * restarts portmidi and lists devices again. It is mainly + * a test for shutting down and restarting. + * + * Roger B. Dannenberg, Feb 2022 + */ + +#include "portmidi.h" +#include "porttime.h" +#include "stdlib.h" +#include "stdio.h" +#include "string.h" +#include "assert.h" + +#define DEVICE_INFO NULL +#define DRIVER_INFO NULL +#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ + +#define STRING_MAX 80 /* used for console input */ + +void show_usage() +{ + printf("Usage: pmlist [-h]\n -h means help.\n" + " Type return to rescan and list devices, q<ret> to quit\n"); +} + + +int main(int argc, char *argv[]) +{ + if (argc > 1) { + show_usage(); + exit(0); + } + + while (1) { + char input[STRING_MAX]; + const char *deflt; + const char *in_or_out; + int default_in, default_out, i; + + // Pm_Initialize(); + /* list device information */ + default_in = Pm_GetDefaultInputDeviceID(); + default_out = Pm_GetDefaultOutputDeviceID(); + for (i = 0; i < Pm_CountDevices(); i++) { + const PmDeviceInfo *info = Pm_GetDeviceInfo(i); + printf("%d: %s, %s", i, info->interf, info->name); + deflt = ""; + if (i == default_out || i == default_in) { + deflt = "default "; + } + in_or_out = (info->input ? "input" : "output"); + printf(" (%s%s)\n", deflt, in_or_out); + } + if (fgets(input, STRING_MAX, stdin) && input[0] == 'q') { + return 0; + } + Pm_Terminate(); + } + return 0; +} diff --git a/3rdparty/portmidi/pm_test/qtest.vcproj b/3rdparty/portmidi/pm_test/qtest.vcproj deleted file mode 100644 index 70a8025b98d..00000000000 --- a/3rdparty/portmidi/pm_test/qtest.vcproj +++ /dev/null @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="qtest" - ProjectGUID="{2204E68C-5C1F-440E-8CE6-7E273D4F6AD1}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="qtest.dir\Debug" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="1" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Debug/qtest.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Debug\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Debug\qtest.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Debug/qtest.pdb" - GenerateDebugInformation="TRUE" - SubSystem="1" - ImportLibrary="..\pm_test\Debug\qtest.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="qtest.dir\Release" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="0" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Release/qtest.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Release\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Release\qtest.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Release/qtest.pdb" - SubSystem="1" - ImportLibrary="..\pm_test\Release\qtest.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_test\qtest.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_test/recvvirtual.c b/3rdparty/portmidi/pm_test/recvvirtual.c new file mode 100644 index 00000000000..8ac97bed54c --- /dev/null +++ b/3rdparty/portmidi/pm_test/recvvirtual.c @@ -0,0 +1,125 @@ +#include "portmidi.h" +#include "porttime.h" +#include "stdlib.h" +#include "stdio.h" +#include "string.h" +#include "assert.h" + +#define INPUT_BUFFER_SIZE 100 +#define DRIVER_INFO NULL +#define TIME_PROC ((PmTimeProcPtr) Pt_Time) +#define TIME_INFO NULL +#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ + +#define STRING_MAX 80 /* used for console input */ + +static void prompt_and_exit(void) +{ + printf("type ENTER..."); + while (getchar() != '\n') ; + /* this will clean up open ports: */ + exit(-1); +} + + +static PmError checkerror(PmError err) +{ + if (err == pmHostError) { + /* it seems pointless to allocate memory and copy the string, + * so I will do the work of Pm_GetHostErrorText directly + */ + char errmsg[80]; + Pm_GetHostErrorText(errmsg, 80); + printf("PortMidi found host error...\n %s\n", errmsg); + prompt_and_exit(); + } else if (err < 0) { + printf("PortMidi call failed...\n %s\n", Pm_GetErrorText(err)); + prompt_and_exit(); + } + return err; +} + + +void main_test_input(int num) +{ + PmStream *midi; + PmError status, length; + PmEvent buffer[1]; + int id; + int i = 0; /* count messages as they arrive */ + /* It is recommended to start timer before Midi; otherwise, PortMidi may + start the timer with its (default) parameters + */ + TIME_START; + + /* create a virtual input device */ + id = checkerror(Pm_CreateVirtualInput("portmidi", NULL, DRIVER_INFO)); + checkerror(Pm_OpenInput(&midi, id, NULL, 0, NULL, NULL)); + + printf("Midi Input opened. Reading %d Midi messages...\n", num); + Pm_SetFilter(midi, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX); + /* empty the buffer after setting filter, just in case anything + got through */ + while (Pm_Poll(midi)) { + Pm_Read(midi, buffer, 1); + } + /* now start paying attention to messages */ + while (i < num) { + status = Pm_Poll(midi); + if (status == TRUE) { + length = Pm_Read(midi, buffer, 1); + if (length > 0) { + printf("Got message %d: time %ld, %2lx %2lx %2lx\n", + i, + (long) buffer[0].timestamp, + (long) Pm_MessageStatus(buffer[0].message), + (long) Pm_MessageData1(buffer[0].message), + (long) Pm_MessageData2(buffer[0].message)); + i++; + } else { + assert(0); + } + } + } + + /* close device (this not explicitly needed in most implementations) */ + printf("ready to close..."); + Pm_Close(midi); + printf("done closing.\nNow delete the virtual device..."); + checkerror(Pm_DeleteVirtualDevice(id)); + printf("done deleting.\n"); +} + + +void show_usage() +{ + printf("Usage: recvvirtual [-h] [n]\n use -h for this message,\n" + " n is number of message to wait for.\n"); + exit(0); +} + + +int main(int argc, char *argv[]) +{ + char line[STRING_MAX]; + int num = 10; + + if (argc > 2) { + show_usage(); + } else if (argc == 2) { + if (strcmp(argv[1], "-h") == 0) { + show_usage(); + } else { + num = atoi(argv[1]); + if (num <= 0) { + show_usage(); + } + } + } + + main_test_input(num); + + printf("finished portMidi test...type ENTER to quit..."); + while (getchar() != '\n') ; + return 0; +} diff --git a/3rdparty/portmidi/pm_test/sendvirtual.c b/3rdparty/portmidi/pm_test/sendvirtual.c new file mode 100644 index 00000000000..14c6e9ea658 --- /dev/null +++ b/3rdparty/portmidi/pm_test/sendvirtual.c @@ -0,0 +1,148 @@ +/* sendvirtual.c -- test for creating a virtual device and sending to it */ +/* + * Roger B. Dannenberg + * Sep 2021 + */ +#include "portmidi.h" +#include "porttime.h" +#include "stdlib.h" +#include "stdio.h" +#include "string.h" +#include "assert.h" + +#define OUTPUT_BUFFER_SIZE 0 +#define DEVICE_INFO NULL +#define DRIVER_INFO NULL +#define TIME_PROC ((PmTimeProcPtr) Pt_Time) +#define TIME_INFO NULL +#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ + +int latency = 0; + +static void prompt_and_exit(void) +{ + printf("type ENTER..."); + while (getchar() != '\n') ; + /* this will clean up open ports: */ + exit(-1); +} + + +static PmError checkerror(PmError err) +{ + if (err == pmHostError) { + /* it seems pointless to allocate memory and copy the string, + * so I will do the work of Pm_GetHostErrorText directly + */ + char errmsg[80]; + Pm_GetHostErrorText(errmsg, 80); + printf("PortMidi found host error...\n %s\n", errmsg); + prompt_and_exit(); + } else if (err < 0) { + printf("PortMidi call failed...\n %s\n", Pm_GetErrorText(err)); + prompt_and_exit(); + } + return err; +} + + +void wait_until(PmTimestamp when) +{ + PtTimestamp now = Pt_Time(); + if (when > now) { + Pt_Sleep(when - now); + } +} + + +void main_test_output(int num) +{ + PmStream *midi; + int32_t next_time; + PmEvent buffer[1]; + PmTimestamp timestamp; + int pitch = 60; + int id; + + /* It is recommended to start timer before Midi; otherwise, PortMidi may + start the timer with its (default) parameters + */ + TIME_START; + + /* create a virtual output device */ + id = checkerror(Pm_CreateVirtualOutput("portmidi", NULL, DEVICE_INFO)); + checkerror(Pm_OpenOutput(&midi, id, DRIVER_INFO, OUTPUT_BUFFER_SIZE, + TIME_PROC, TIME_INFO, latency)); + + printf("Midi Output Virtual Device \"portmidi\" created.\n"); + printf("Type ENTER to send messages: "); + while (getchar() != '\n') ; + + buffer[0].timestamp = Pt_Time(); +#define PROGRAM 0 + buffer[0].message = Pm_Message(0xC0, PROGRAM, 0); + Pm_Write(midi, buffer, 1); + next_time = Pt_Time() + 1000; /* wait 1s */ + while (num > 0) { + wait_until(next_time); + Pm_WriteShort(midi, next_time, Pm_Message(0x90, pitch, 100)); + printf("Note On pitch %d\n", pitch); + num--; + next_time += 500; + + wait_until(next_time); + Pm_WriteShort(midi, next_time, Pm_Message(0x90, pitch, 0)); + printf("Note Off pitch %d\n", pitch); + num--; + pitch = (pitch + 1) % 12 + 60; + next_time += 500; + } + + /* close device (this not explicitly needed in most implementations) */ + printf("ready to close..."); + Pm_Close(midi); + printf("done closing.\nNow delete the virtual device..."); + checkerror(Pm_DeleteVirtualDevice(id)); + printf("done deleting.\n"); +} + + +void show_usage() +{ + printf("Usage: sendvirtual [-h] [-l latency-in-ms] [n]\n" + " -h for this message,\n" + " -l ms designates latency for precise timing (default 0),\n" + " n is number of message to send.\n" + "sends change program to 1, then one note per second with 0.5s on,\n" + "0.5s off, for n/2 seconds. Latency >0 uses the device driver for \n" + "precise timing (see PortMidi documentation).\n"); + exit(0); +} + + +int main(int argc, char *argv[]) +{ + int num = 10; + int i; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-h") == 0) { + show_usage(); + } else if (strcmp(argv[i], "-l") == 0 && (i + 1 < argc)) { + i = i + 1; + latency = atoi(argv[i]); + printf("Latency will be %d\n", latency); + } else { + num = atoi(argv[1]); + if (num <= 0) { + show_usage(); + } + printf("Sending %d messages.\n", num); + } + } + + main_test_output(num); + + printf("finished sendvirtual test...type ENTER to quit..."); + while (getchar() != '\n') ; + return 0; +} diff --git a/3rdparty/portmidi/pm_test/sysex.c b/3rdparty/portmidi/pm_test/sysex.c index 7bbcf0eedfd..81964961670 100644 --- a/3rdparty/portmidi/pm_test/sysex.c +++ b/3rdparty/portmidi/pm_test/sysex.c @@ -21,6 +21,11 @@ #define Sleep(n) usleep(n * 1000) #endif +// enable some extra printing +#ifndef VERBOSE +#define VERBOSE 0 +#endif + #define MIDI_SYSEX 0xf0 #define MIDI_EOX 0xf7 @@ -35,15 +40,13 @@ int latency = 0; /* read a number from console */ /**/ -int get_number(char *prompt) +int get_number(const char *prompt) { - char line[STRING_MAX]; int n = 0, i; - printf(prompt); + fputs(prompt, stdout); while (n != 1) { n = scanf("%d", &i); - fgets(line, STRING_MAX, stdin); - + while (getchar() != '\n') ; } return i; } @@ -58,7 +61,6 @@ void loopback_test() PmStream *midi_in; PmStream *midi_out; unsigned char msg[1024]; - char line[80]; int32_t len; int i; int data; @@ -90,7 +92,7 @@ void loopback_test() srand((unsigned int) Pt_Time()); /* seed for random numbers */ begin_time = Pt_Time(); - while (1) { + while (total_bytes < 100000) { PmError count; int32_t start_time; int error_position = -1; /* 0; -1; -1 for continuous */ @@ -100,9 +102,11 @@ void loopback_test() /* set error_position above to 0 for interactive, -1 for */ /* continuous */ if (error_position >= 0) { + int c; printf("Type return to send message, q to quit: "); - fgets(line, STRING_MAX, stdin); - if (line[0] == 'q') goto cleanup; + while ((c = getchar()) != '\n') { + if (c == 'q') goto cleanup; + } } /* compose the message */ @@ -125,17 +129,38 @@ void loopback_test() printf("Before sending anything, a MIDI message was found in\n"); printf("the input buffer. Please try again.\n"); break; - } + } - /* send the message */ - printf("Sending %d byte sysex message.\n", len + 2); - Pm_WriteSysEx(midi_out, 0, msg); + /* send the message two ways: 1) Pm_WriteSysEx, 2) Pm_Write */ + if (total_bytes & 1) { + printf("Sending %d byte sysex msg via Pm_WriteSysEx.\n", len + 2); + Pm_WriteSysEx(midi_out, 0, msg); + } else { + PmEvent event = {0, 0}; + int bits = 0; + printf("Sending %d byte sysex msg via Pm_Write(s).\n", len + 2); + for (i = 0; i < len + 2; i++) { + event.message |= (msg[i] << bits); + bits += 8; + if (bits == 32) { /* full message - send it */ + Pm_Write(midi_out, &event, 1); + bits = 0; + event.message = 0; + } + } + if (bits > 0) { /* last message is partially full */ + Pm_Write(midi_out, &event, 1); + } + } /* receive the message and compare to msg[] */ data = 0; shift = 0; i = 0; start_time = Pt_Time(); + if (VERBOSE) { + printf("start_time %d\n", start_time); + } error_position = -1; /* allow up to 2 seconds for transmission */ while (data != MIDI_EOX && start_time + 2000 > Pt_Time()) { @@ -144,10 +169,10 @@ void loopback_test() Sleep(1); /* be nice: give some CPU time to the system */ continue; /* continue polling for input */ } - - /* printf("read %lx ", event.message); - fflush(stdout); */ - + if (VERBOSE) { + printf("read %08x ", event.message); + fflush(stdout); + } /* compare 4 bytes of data until you reach an eox */ for (shift = 0; shift < 32 && (data != MIDI_EOX); shift += 8) { data = (event.message >> shift) & 0xFF; @@ -160,18 +185,20 @@ void loopback_test() } } if (error_position >= 0) { - printf("Error at byte %d: sent %x recd %x.\n", error_position, - expected, actual); + printf("Error at time %d byte %d: sent %x recd %x.\n", Pt_Time(), + error_position, expected, actual); break; } else if (i != len + 2) { - printf("Error: byte %d not received.\n", i); + printf("Error at time %d: byte %d not received.\n", Pt_Time(), i); break; } else { int seconds = (Pt_Time() - begin_time) / 1000; - if (seconds == 0) seconds = 1; + if (seconds == 0) seconds = 1; printf("Correctly received %d byte sysex message.\n", i); - total_bytes += i; - printf("Cummulative bytes/sec: %d\n", total_bytes / seconds); + total_bytes += i; + printf("Cummulative bytes/sec: %d, %d%% done.\n", + (int) (total_bytes / seconds), + (int) (100 * total_bytes / 100000)); } } cleanup: @@ -378,7 +405,7 @@ void receive_sysex() printf("Midi Input opened, type file for sysex data: "); /* open file */ - fgets(line, STRING_MAX, stdin); + if (!fgets(line, STRING_MAX, stdin)) return; /* no more stdin? */ /* remove the newline character */ if (strlen(line) > 0) line[strlen(line) - 1] = 0; f = fopen(line, "w"); @@ -443,7 +470,7 @@ void send_sysex() printf("Midi Output opened, type file with sysex data: "); /* open file */ - fgets(line, STRING_MAX, stdin); + if (!fgets(line, STRING_MAX, stdin)) return; /* no more stdin? */ /* remove the newline character */ if (strlen(line) > 0) line[strlen(line) - 1] = 0; f = fopen(line, "r"); @@ -487,7 +514,6 @@ void send_sysex() int main() { int i; - char line[80]; /* list device information */ for (i = 0; i < Pm_CountDevices(); i++) { @@ -498,11 +524,13 @@ int main() printf("\n"); } while (1) { + char cmd; printf("Type r to receive sysex, s to send," " l for loopback test, m to send multiple," " n to receive multiple, q to quit: "); - fgets(line, STRING_MAX, stdin); - switch (line[0]) { + cmd = getchar(); + while (getchar() != '\n') ; + switch (cmd) { case 'r': receive_sysex(); break; diff --git a/3rdparty/portmidi/pm_test/sysex.vcproj b/3rdparty/portmidi/pm_test/sysex.vcproj deleted file mode 100644 index dabeecb255c..00000000000 --- a/3rdparty/portmidi/pm_test/sysex.vcproj +++ /dev/null @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="sysex" - ProjectGUID="{71B9BC6E-7B40-4FBC-BC7F-4372AF03D0FD}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="sysex.dir\Debug" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="1" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Debug/sysex.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Debug\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Debug\sysex.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Debug/sysex.pdb" - GenerateDebugInformation="TRUE" - SubSystem="1" - ImportLibrary="..\pm_test\Debug\sysex.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="sysex.dir\Release" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="0" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Release/sysex.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Release\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Release\sysex.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Release/sysex.pdb" - SubSystem="1" - ImportLibrary="..\pm_test\Release\sysex.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_test\sysex.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_test/test.vcproj b/3rdparty/portmidi/pm_test/test.vcproj deleted file mode 100644 index 7458c31e865..00000000000 --- a/3rdparty/portmidi/pm_test/test.vcproj +++ /dev/null @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="test" - ProjectGUID="{0BEACB8B-4058-41A4-A9DE-1B1FB650B21A}" - Keyword="Win32Proj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="test.dir\Debug" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - BasicRuntimeChecks="3" - CompileAs="1" - DebugInformationFormat="3" - ExceptionHandling="0" - InlineFunctionExpansion="0" - Optimization="0" - RuntimeLibrary="1" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - AssemblerListingLocation="Debug" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Debug/test.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\"Debug\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386 /debug" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Debug\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Debug\test.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="2" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Debug/test.pdb" - GenerateDebugInformation="TRUE" - SubSystem="1" - ImportLibrary="..\pm_test\Debug\test.lib"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="test.dir\Release" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions=" /Zm1000" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - CompileAs="1" - ExceptionHandling="0" - InlineFunctionExpansion="2" - Optimization="2" - RuntimeLibrary="0" - WarningLevel="3" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - AssemblerListingLocation="Release" - ObjectFile="$(IntDir)\" - ProgramDataBaseFileName="../pm_test/Release/test.pdb" -/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCResourceCompilerTool" - AdditionalIncludeDirectories="..\pm_common;..\porttime;" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\""/> - <Tool - Name="VCMIDLTool" - PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\"Release\"" - MkTypLibCompatible="FALSE" - TargetEnvironment="1" - GenerateStublessProxies="TRUE" - TypeLibraryName="$(InputName).tlb" - OutputDirectory="$(IntDir)" - HeaderFileName="$(InputName).h" - DLLDataFileName="" - InterfaceIdentifierFileName="$(InputName)_i.c" - ProxyFileName="$(InputName)_p.c"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCLinkerTool" - AdditionalOptions=" /STACK:10000000 /machine:I386" - AdditionalDependencies="$(NOINHERIT) kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ..\Release\portmidi_s.lib winmm.lib " - OutputFile="..\pm_test\Release\test.exe" - Version="0.0" - GenerateManifest="TRUE" - LinkIncremental="1" - AdditionalLibraryDirectories="" - ProgramDataBaseFile="../pm_test/Release/test.pdb" - SubSystem="1" - ImportLibrary="..\pm_test\Release\test.lib"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter=""> - <File - RelativePath="..\pm_test\test.c"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/pm_test/test.c b/3rdparty/portmidi/pm_test/testio.c index 03d6331adef..c71ae087307 100644 --- a/3rdparty/portmidi/pm_test/test.c +++ b/3rdparty/portmidi/pm_test/testio.c @@ -12,9 +12,10 @@ #define TIME_INFO NULL #define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ -#define STRING_MAX 80 /* used for console input */ +#define WAIT_FOR_ENTER while (getchar() != '\n') ; int32_t latency = 0; +int verbose = FALSE; /* crash the program to test whether midi ports are closed */ /**/ @@ -33,15 +34,13 @@ void doSomethingStupid() { /* read a number from console */ /**/ -int get_number(char *prompt) +int get_number(const char *prompt) { - char line[STRING_MAX]; int n = 0, i; - printf(prompt); + fputs(prompt, stdout); while (n != 1) { n = scanf("%d", &i); - fgets(line, STRING_MAX, stdin); - + WAIT_FOR_ENTER } return i; } @@ -83,10 +82,10 @@ void main_test_input(unsigned int somethingStupid) { while (i < num) { status = Pm_Poll(midi); if (status == TRUE) { - length = Pm_Read(midi,buffer, 1); + length = Pm_Read(midi, buffer, 1); if (length > 0) { - printf("Got message %d: time %ld, %2lx %2lx %2lx\n", - i, + printf("Got message %d @ time %ld: timestamp %ld, " + "%2lx %2lx %2lx\n", i, (long) Pt_Time(), (long) buffer[0].timestamp, (long) Pm_MessageStatus(buffer[0].message), (long) Pm_MessageData1(buffer[0].message), @@ -113,9 +112,9 @@ void main_test_input(unsigned int somethingStupid) { -void main_test_output() { +void main_test_output(int isochronous_test) +{ PmStream * midi; - char line[80]; int32_t off_time; int chord[] = { 60, 67, 76, 83, 90 }; #define chord_size 5 @@ -142,65 +141,100 @@ void main_test_output() { printf("Midi Output opened with %ld ms latency.\n", (long) latency); /* output note on/off w/latency offset; hold until user prompts */ - printf("ready to send program 1 change... (type RETURN):"); - fgets(line, STRING_MAX, stdin); + printf("ready to send program 1 change... (type ENTER):"); + WAIT_FOR_ENTER /* if we were writing midi for immediate output, we could always use timestamps of zero, but since we may be writing with latency, we will explicitly set the timestamp to "now" by getting the time. The source of timestamps should always correspond to the TIME_PROC and TIME_INFO parameters used in Pm_OpenOutput(). */ - buffer[0].timestamp = TIME_PROC(TIME_INFO); + buffer[0].timestamp = Pt_Time(); /* Send a program change to increase the chances we will hear notes */ /* Program 0 is usually a piano, but you can change it here: */ #define PROGRAM 0 buffer[0].message = Pm_Message(0xC0, PROGRAM, 0); Pm_Write(midi, buffer, 1); - printf("ready to note-on... (type RETURN):"); - fgets(line, STRING_MAX, stdin); - buffer[0].timestamp = TIME_PROC(TIME_INFO); - buffer[0].message = Pm_Message(0x90, 60, 100); - Pm_Write(midi, buffer, 1); - printf("ready to note-off... (type RETURN):"); - fgets(line, STRING_MAX, stdin); - buffer[0].timestamp = TIME_PROC(TIME_INFO); - buffer[0].message = Pm_Message(0x90, 60, 0); - Pm_Write(midi, buffer, 1); - - /* output short note on/off w/latency offset; hold until user prompts */ - printf("ready to note-on (short form)... (type RETURN):"); - fgets(line, STRING_MAX, stdin); - Pm_WriteShort(midi, TIME_PROC(TIME_INFO), - Pm_Message(0x90, 60, 100)); - printf("ready to note-off (short form)... (type RETURN):"); - fgets(line, STRING_MAX, stdin); - Pm_WriteShort(midi, TIME_PROC(TIME_INFO), - Pm_Message(0x90, 60, 0)); - - /* output several note on/offs to test timing. - Should be 1s between notes */ - printf("chord will arpeggiate if latency > 0\n"); - printf("ready to chord-on/chord-off... (type RETURN):"); - fgets(line, STRING_MAX, stdin); - timestamp = TIME_PROC(TIME_INFO); - for (i = 0; i < chord_size; i++) { - buffer[i].timestamp = timestamp + 1000 * i; - buffer[i].message = Pm_Message(0x90, chord[i], 100); - } - Pm_Write(midi, buffer, chord_size); - - off_time = timestamp + 1000 + chord_size * 1000; - while (TIME_PROC(TIME_INFO) < off_time) - /* busy wait */; - for (i = 0; i < chord_size; i++) { - buffer[i].timestamp = timestamp + 1000 * i; - buffer[i].message = Pm_Message(0x90, chord[i], 0); + if (isochronous_test) { // play 4 notes per sec for 20s + int count; + PmTimestamp start; + if (latency < 100) { + printf("Warning: latency < 100, but this test sends messages" + " at times that are jittered by up to 100ms, so you" + " may hear uneven timing\n"); + } + printf("Starting in 1s..."); fflush(stdout); + Pt_Sleep(1000); + start = Pt_Time(); + for (count = 0; count < 80; count++) { + PmTimestamp next_time; + buffer[0].timestamp = start + count * 250; + buffer[0].message = Pm_Message(0x90, 69, 100); + buffer[1].timestamp = start + count * 250 + 200; + buffer[1].message = Pm_Message(0x90, 69, 0); + Pm_Write(midi, buffer, 2); + next_time = start + (count + 1) * 250; + // sleep for a random time up to 100ms to add jitter to + // the times at which we send messages. PortMidi timing + // should remove the jitter if latency > 100 + while (Pt_Time() < next_time) { + Pt_Sleep(rand() % 100); + } + } + printf("Done sending 80 notes at 4 notes per second.\n"); + } else { + printf("ready to note-on... (type ENTER):"); + WAIT_FOR_ENTER + buffer[0].timestamp = Pt_Time(); + buffer[0].message = Pm_Message(0x90, 60, 100); + Pm_Write(midi, buffer, 1); + printf("ready to note-off... (type ENTER):"); + WAIT_FOR_ENTER + buffer[0].timestamp = Pt_Time(); + buffer[0].message = Pm_Message(0x90, 60, 0); + Pm_Write(midi, buffer, 1); + + /* output short note on/off w/latency offset; hold until user prompts */ + printf("ready to note-on (short form)... (type ENTER):"); + WAIT_FOR_ENTER + Pm_WriteShort(midi, Pt_Time(), + Pm_Message(0x90, 60, 100)); + printf("ready to note-off (short form)... (type ENTER):"); + WAIT_FOR_ENTER + Pm_WriteShort(midi, Pt_Time(), + Pm_Message(0x90, 60, 0)); + + /* output several note on/offs to test timing. + Should be 1s between notes */ + if (latency == 0) { + printf("chord should not arpeggiate, latency == 0\n"); + } else { + printf("chord should arpeggiate (latency = %ld > 0\n", + (long) latency); + } + printf("ready to chord-on/chord-off... (type ENTER):"); + WAIT_FOR_ENTER + timestamp = Pt_Time(); + printf("starting timestamp %ld\n", (long) timestamp); + for (i = 0; i < chord_size; i++) { + buffer[i].timestamp = timestamp + 1000 * i; + buffer[i].message = Pm_Message(0x90, chord[i], 100); + } + Pm_Write(midi, buffer, chord_size); + + off_time = timestamp + 1000 + chord_size * 1000; + while (Pt_Time() < off_time) + Pt_Sleep(10); /* wait */ + for (i = 0; i < chord_size; i++) { + buffer[i].timestamp = timestamp + 1000 * i; + buffer[i].message = Pm_Message(0x90, chord[i], 0); + } + Pm_Write(midi, buffer, chord_size); } - Pm_Write(midi, buffer, chord_size); /* close device (this not explicitly needed in most implementations) */ - printf("ready to close and terminate... (type RETURN):"); - fgets(line, STRING_MAX, stdin); + printf("ready to close and terminate... (type ENTER):"); + WAIT_FOR_ENTER Pm_Close(midi); Pm_Terminate(); @@ -215,7 +249,7 @@ void main_test_both() PmStream * midi, * midiOut; PmEvent buffer[1]; PmError status, length; - int num = 10; + int num = 11; in = get_number("Type input number: "); out = get_number("Type output number: "); @@ -238,7 +272,7 @@ void main_test_both() INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO); - printf("Midi Input opened. Reading %d Midi messages...\n",num); + printf("Midi Input opened. Reading %d Midi messages...\n", num); Pm_SetFilter(midi, PM_FILT_ACTIVE | PM_FILT_CLOCK); /* empty the buffer after setting filter, just in case anything got through */ @@ -252,8 +286,8 @@ void main_test_both() length = Pm_Read(midi,buffer,1); if (length > 0) { Pm_Write(midiOut, buffer, 1); - printf("Got message %d: time %ld, %2lx %2lx %2lx\n", - i, + printf("Got message %d @ time %ld: timestamp %ld, " + "%2lx %2lx %2lx\n", i, (long) Pt_Time(), (long) buffer[0].timestamp, (long) Pm_MessageStatus(buffer[0].message), (long) Pm_MessageData1(buffer[0].message), @@ -264,6 +298,8 @@ void main_test_both() } } } + /* allow time for last message to go out */ + Pt_Sleep(100 + latency); /* close midi devices */ Pm_Close(midi); @@ -281,19 +317,18 @@ void main_test_both() */ void main_test_stream() { PmStream * midi; - char line[80]; PmEvent buffer[16]; /* determine which output device to use */ int i = get_number("Type output number: "); - latency = 500; /* ignore LATENCY for this test and + latency = 500; /* ignore LATENCY for this test and fix the latency at 500ms */ /* It is recommended to start timer before PortMidi */ TIME_START; - /* open output device */ + /* open output device */ Pm_OpenOutput(&midi, i, DRIVER_INFO, @@ -304,66 +339,66 @@ void main_test_stream() { printf("Midi Output opened with %ld ms latency.\n", (long) latency); /* output note on/off w/latency offset; hold until user prompts */ - printf("ready to send output... (type RETURN):"); - fgets(line, STRING_MAX, stdin); + printf("ready to send output... (type ENTER):"); + WAIT_FOR_ENTER /* if we were writing midi for immediate output, we could always use timestamps of zero, but since we may be writing with latency, we will explicitly set the timestamp to "now" by getting the time. The source of timestamps should always correspond to the TIME_PROC and TIME_INFO parameters used in Pm_OpenOutput(). */ - buffer[0].timestamp = TIME_PROC(TIME_INFO); + buffer[0].timestamp = Pt_Time(); buffer[0].message = Pm_Message(0xC0, 0, 0); - buffer[1].timestamp = buffer[0].timestamp; - buffer[1].message = Pm_Message(0x90, 60, 100); - buffer[2].timestamp = buffer[0].timestamp + 1000; - buffer[2].message = Pm_Message(0x90, 62, 100); - buffer[3].timestamp = buffer[0].timestamp + 2000; - buffer[3].message = Pm_Message(0x90, 64, 100); - buffer[4].timestamp = buffer[0].timestamp + 3000; - buffer[4].message = Pm_Message(0x90, 66, 100); - buffer[5].timestamp = buffer[0].timestamp + 4000; - buffer[5].message = Pm_Message(0x90, 60, 0); - buffer[6].timestamp = buffer[0].timestamp + 4000; - buffer[6].message = Pm_Message(0x90, 62, 0); - buffer[7].timestamp = buffer[0].timestamp + 4000; - buffer[7].message = Pm_Message(0x90, 64, 0); - buffer[8].timestamp = buffer[0].timestamp + 4000; - buffer[8].message = Pm_Message(0x90, 66, 0); + buffer[1].timestamp = buffer[0].timestamp; + buffer[1].message = Pm_Message(0x90, 60, 100); + buffer[2].timestamp = buffer[0].timestamp + 1000; + buffer[2].message = Pm_Message(0x90, 62, 100); + buffer[3].timestamp = buffer[0].timestamp + 2000; + buffer[3].message = Pm_Message(0x90, 64, 100); + buffer[4].timestamp = buffer[0].timestamp + 3000; + buffer[4].message = Pm_Message(0x90, 66, 100); + buffer[5].timestamp = buffer[0].timestamp + 4000; + buffer[5].message = Pm_Message(0x90, 60, 0); + buffer[6].timestamp = buffer[0].timestamp + 4000; + buffer[6].message = Pm_Message(0x90, 62, 0); + buffer[7].timestamp = buffer[0].timestamp + 4000; + buffer[7].message = Pm_Message(0x90, 64, 0); + buffer[8].timestamp = buffer[0].timestamp + 4000; + buffer[8].message = Pm_Message(0x90, 66, 0); Pm_Write(midi, buffer, 9); #ifdef SEND8 - /* Now, we're ready for the real test. - Play 4 notes at now, now+500, now+1000, and now+1500 - Then wait until now+2000. - Play 4 more notes as before. - We should hear 8 evenly spaced notes. */ - now = TIME_PROC(TIME_INFO); - for (i = 0; i < 4; i++) { - buffer[i * 2].timestamp = now + (i * 500); - buffer[i * 2].message = Pm_Message(0x90, 60, 100); - buffer[i * 2 + 1].timestamp = now + 250 + (i * 500); - buffer[i * 2 + 1].message = Pm_Message(0x90, 60, 0); - } + /* Now, we're ready for the real test. + Play 4 notes at now, now+500, now+1000, and now+1500 + Then wait until now+2000. + Play 4 more notes as before. + We should hear 8 evenly spaced notes. */ + now = Pt_Time(); + for (i = 0; i < 4; i++) { + buffer[i * 2].timestamp = now + (i * 500); + buffer[i * 2].message = Pm_Message(0x90, 60, 100); + buffer[i * 2 + 1].timestamp = now + 250 + (i * 500); + buffer[i * 2 + 1].message = Pm_Message(0x90, 60, 0); + } Pm_Write(midi, buffer, 8); while (Pt_Time() < now + 2500) - /* busy wait */; - /* now we are 500 ms behind schedule, but since the latency - is 500, the delay should not be audible */ - now += 2000; - for (i = 0; i < 4; i++) { - buffer[i * 2].timestamp = now + (i * 500); - buffer[i * 2].message = Pm_Message(0x90, 60, 100); - buffer[i * 2 + 1].timestamp = now + 250 + (i * 500); - buffer[i * 2 + 1].message = Pm_Message(0x90, 60, 0); - } + Pt_Sleep(10); + /* now we are 500 ms behind schedule, but since the latency + is 500, the delay should not be audible */ + now += 2000; + for (i = 0; i < 4; i++) { + buffer[i * 2].timestamp = now + (i * 500); + buffer[i * 2].message = Pm_Message(0x90, 60, 100); + buffer[i * 2 + 1].timestamp = now + 250 + (i * 500); + buffer[i * 2 + 1].message = Pm_Message(0x90, 60, 0); + } Pm_Write(midi, buffer, 8); #endif /* close device (this not explicitly needed in most implementations) */ - printf("ready to close and terminate... (type RETURN):"); - fgets(line, STRING_MAX, stdin); - + printf("ready to close and terminate... (type ENTER):"); + WAIT_FOR_ENTER + Pm_Close(midi); Pm_Terminate(); printf("done closing and terminating...\n"); @@ -372,8 +407,10 @@ void main_test_stream() { void show_usage() { - printf("Usage: test [-h] [-l latency-in-ms]\n"); - exit(0); + printf("Usage: test [-h] [-l latency-in-ms] [-v]\n" + " -h for this help message (only)\n" + " -l for latency\n" + " -v for verbose (enables more output)\n"); } int main(int argc, char *argv[]) @@ -381,11 +418,12 @@ int main(int argc, char *argv[]) int default_in; int default_out; int i = 0, n = 0; - char line[STRING_MAX]; int test_input = 0, test_output = 0, test_both = 0, somethingStupid = 0; + int isochronous_test = 0; int stream_test = 0; int latency_valid = FALSE; + show_usage(); if (sizeof(void *) == 8) printf("Apparently this is a 64-bit machine.\n"); else if (sizeof(void *) == 4) @@ -393,14 +431,18 @@ int main(int argc, char *argv[]) for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-h") == 0) { - show_usage(); + exit(0); } else if (strcmp(argv[i], "-l") == 0 && (i + 1 < argc)) { i = i + 1; latency = atoi(argv[i]); printf("Latency will be %ld\n", (long) latency); latency_valid = TRUE; + } else if (strcmp(argv[i], "-v") == 0) { + printf("Verbose is now TRUE\n"); + verbose = TRUE; /* not currently used for anything */ } else { show_usage(); + exit(0); } } @@ -409,21 +451,21 @@ int main(int argc, char *argv[]) printf("Latency in ms: "); if (scanf("%d", &lat) == 1) { latency = (int32_t) lat; // coerce from "%d" to known size - latency_valid = TRUE; + latency_valid = TRUE; } } /* determine what type of test to run */ printf("begin portMidi test...\n"); - printf("%s%s%s%s%s", - "enter your choice...\n 1: test input\n", - " 2: test input (fail w/assert)\n", - " 3: test input (fail w/NULL assign)\n", - " 4: test output\n 5: test both\n", - " 6: stream test\n"); + printf("enter your choice...\n 1: test input\n" + " 2: test input (fail w/assert)\n" + " 3: test input (fail w/NULL assign)\n" + " 4: test output\n 5: test both\n" + " 6: stream test (for WinMM)\n" + " 7. isochronous out\n"); while (n != 1) { n = scanf("%d", &i); - fgets(line, STRING_MAX, stdin); + WAIT_FOR_ENTER switch(i) { case 1: test_input = 1; @@ -442,9 +484,13 @@ int main(int argc, char *argv[]) case 5: test_both = 1; break; - case 6: - stream_test = 1; - break; + case 6: + stream_test = 1; + break; + case 7: + test_output = 1; + isochronous_test = 1; + break; default: printf("got %d (invalid input)\n", n); break; @@ -478,12 +524,12 @@ int main(int argc, char *argv[]) } else if (test_input) { main_test_input(somethingStupid); } else if (test_output) { - main_test_output(); + main_test_output(isochronous_test); } else if (test_both) { main_test_both(); } printf("finished portMidi test...type ENTER to quit..."); - fgets(line, STRING_MAX, stdin); + WAIT_FOR_ENTER return 0; } diff --git a/3rdparty/portmidi/pm_test/virttest.c b/3rdparty/portmidi/pm_test/virttest.c new file mode 100644 index 00000000000..1aeb09b8c54 --- /dev/null +++ b/3rdparty/portmidi/pm_test/virttest.c @@ -0,0 +1,339 @@ +/* virttest.c -- test for creating/deleting virtual ports */ +/* + * Roger B. Dannenberg + * Oct 2021 + +This test is performed by running 2 instances of the program. The +first instance makes input and output ports named portmidi and waits +for a message. The second tries to do the same, but will fail because +portmidi already exists. It then opens portmidi (both input and +output). In greater detail: + +FIRST INSTANCE SECOND INSTANCE +-------------- --------------- + +initialize PortMidi initialize PortMidi +create portmidi in +create portmidi out +wait for input + create portmidi in -> fails + open portmidi in/out + send to portmidi +recv from portmidi +send to portmidi +wait 1s recv from portmidi + close portmidi in and out + terminate PortMidi +list all devices: + - check for correct number + - check for good description of portmidi in port (open) + - check for good description of portmidi out port (open) +close portmidi in +list all devices: + - check for correct number + - check for good description of portmidi in port (closed) + - check for good description of portmidi out port (open) +close portmidi out +list all devices: + - check for correct number + - check for good description of portmidi in port (closed) + - check for good description of portmidi out port (closed) +delete portmidi in + - check for correct number + - check for NULL description of portmidi in port + - check for good description of portmidi out port (closed) +delete portmidi out + - check for correct number + - check for NULL description of portmidi in port + - check for NULL description of portmidi out port +terminate portmidi +REPEAT 3 TIMES wait 2 seconds to give head start to other instance + REPEAT 3 TIMES + */ + +#include "portmidi.h" +#include "porttime.h" +#include "stdlib.h" +#include "stdio.h" +#include "string.h" +#include "assert.h" + +#define OUTPUT_BUFFER_SIZE 0 +#define INPUT_BUFFER_SIZE 10 +#define DEVICE_INFO NULL +#define DRIVER_INFO NULL +#define TIME_PROC ((PmTimeProcPtr) Pt_Time) +#define TIME_INFO NULL +#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ + + +static void prompt_and_exit(void) +{ + printf("type ENTER..."); + while (getchar() != '\n') ; + /* this will clean up open ports: */ + exit(-1); +} + + +static PmError printerror(PmError err, const char *msg) +{ + if (err == pmHostError) { + /* it seems pointless to allocate memory and copy the string, + * so I will do the work of Pm_GetHostErrorText directly + */ + char errmsg[80]; + Pm_GetHostErrorText(errmsg, 80); + printf("%s\n %s\n", msg, errmsg); + } else if (err < 0) { + printf("%s\n %s\n", msg, Pm_GetErrorText(err)); + } + return err; +} + + +static PmError checkerror(PmError err) +{ + if (err < 0) { + printerror(err, "PortMidi call failed..."); + prompt_and_exit(); + } + return err; +} + + +void wait_until(PmTimestamp when) +{ + PtTimestamp now = Pt_Time(); + if (when > now) { + Pt_Sleep(when - now); + } +} + + +void show_usage() +{ + printf("Usage: virttest\n" + " run two instances to test virtual port create/delete\n"); +} + + +void check_info(int id, char stat, int input, int virtual) +{ + const PmDeviceInfo *info = Pm_GetDeviceInfo(id); + if (stat == 'd') { + if (info) { + printf("Expected device %d to be deleted.\n", id); + prompt_and_exit(); + } + return; + } + if (!info) { + printf("Expected device %d to not be deleted.\n", id); + prompt_and_exit(); + } + if (strcmp("portmidi", info->name) != 0) { + printf("Device %d name is %s, not \"portmidi\".\n", id, info->name); + prompt_and_exit(); + } + if (info->input != input || (!info->output) != input) { + printf("Device %d input/output fields are wrong.\n", id); + prompt_and_exit(); + } + if ((!info->opened && stat == 'o') || (info->opened && stat == 'c')) { + printf("Device %d opened==%d, status should be %c.\n", id, + info->opened, stat); + prompt_and_exit(); + } + if (info->is_virtual != virtual) { + printf("Expected device %d to be virtual.\n", id); + prompt_and_exit(); + } +} + + +/* stat is 'o' for open, 'c' for closed, 'd' for deleted device */ +void check_ports(int cnt, int in_id, char in_stat, + int out_id, char out_stat, int virtual) +{ + if (cnt != Pm_CountDevices()) { + printf("Device count changed from %d to %d.\n", cnt, Pm_CountDevices()); + prompt_and_exit(); + } + check_info(in_id, in_stat, TRUE, virtual); + check_info(out_id, out_stat, FALSE, virtual); +} + + +void devices_list() +{ + int i; + for (i = 0; i < Pm_CountDevices(); i++) { + const PmDeviceInfo *info = Pm_GetDeviceInfo(i); + if (info) { + printf("%d: %s %s %s %s\n", i, info->name, + (info->input ? "input" : "output"), + (info->is_virtual ? "virtual" : "real_device"), + (info->opened ? "opened" : "closed")); + } + } +} + + +void test2() +{ + PmStream *out = NULL; + PmStream *in = NULL; + int out_id; + int in_id; + PmEvent buffer[1]; + PmTimestamp timestamp; + int pitch = 60; + int device_count = 0; + int i; + + printf("This must be virttest instance #2\n"); + + /* find and open portmidi in and out */ + device_count = Pm_CountDevices(); + for (i = 0; i < device_count; i++) { + const PmDeviceInfo *info = Pm_GetDeviceInfo(i); + if (info && strcmp(info->name, "portmidi") == 0) { + if (info->input) { + checkerror(Pm_OpenInput(&in, i, DRIVER_INFO, + INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO)); + in_id = i; + } else { + checkerror(Pm_OpenOutput(&out, i, DRIVER_INFO, + OUTPUT_BUFFER_SIZE, NULL, NULL, 0)); + out_id = i; + } + } + } + if (!in) { + printf("Did not open portmidi as input (virtual output).\n"); + prompt_and_exit(); + } + if (!out) { + printf("Did not open portmidi as output (virtual input).\n"); + prompt_and_exit(); + } + printf("Input device %d and output device %d are open.\n", in_id, out_id); + + /* send a message */ + buffer[0].timestamp = 0; + buffer[0].message = Pm_Message(0x90, pitch, 100); + checkerror(Pm_Write(out, buffer, 1)); + + /* wait for reply */ + printf("Sent message, waiting for reply...\n"); + while (Pm_Read(in, buffer, 1) < 1) Pt_Sleep(10); + + printf("********** GOT THE MESSAGE, SHUTTING DOWN ************\n"); + + /* close in */ + checkerror(Pm_Close(in)); + check_ports(device_count, in_id, 'c', out_id, 'o', FALSE); + printf("Closed input %d\n", in_id); + + /* close out */ + checkerror(Pm_Close(out)); + check_ports(device_count, in_id, 'c', out_id, 'c', FALSE); + printf("Closed output %d\n", out_id); + + Pt_Sleep(1000); + /* wrap it up */ + Pm_Terminate(); + printf("Got reply and terminated...\n"); + Pt_Sleep(2000); /* 2 seconds because other is waiting 1s. */ + /* 1 more second to make sure other shuts down before test repeats. */ +} + +extern int pm_check_errors; + +void test() +{ + PmStream *out; + PmStream *in; + int out_id; + int in_id; + PmEvent buffer[1]; + PmTimestamp timestamp; + int device_count = 0; + + TIME_START; + + printf("******** INITIALIZING PORTMIDI ***********\n"); + timestamp = Pt_Time(); + Pm_Initialize(); + printf("Pm_Initialize took %dms\n", Pt_Time() - timestamp); + devices_list(); + + pm_check_errors = FALSE; /* otherwise, PM_CHECK_ERRORS, if defined, */ + /* can cause this program to report an error and exit on pmNameConflict. */ + in_id = Pm_CreateVirtualInput("portmidi", NULL, DEVICE_INFO); + pm_check_errors = TRUE; /* there should be no other errors */ + if (in_id < 0) { + printerror(in_id, "Pm_CreateVirtualInput failed..."); + test2(); + return; + } + printf("Created portmidi virtual input; this is virttest instance #1\n"); + out_id = checkerror(Pm_CreateVirtualOutput("portmidi", NULL, DRIVER_INFO)); + device_count = Pm_CountDevices(); + + checkerror(Pm_OpenInput(&in, in_id, NULL, 0, NULL, NULL)); + checkerror(Pm_OpenOutput(&out, out_id, DRIVER_INFO, OUTPUT_BUFFER_SIZE, + TIME_PROC, TIME_INFO, 0)); + printf("Created/Opened input %d and output %d\n", in_id, out_id); + Pm_SetFilter(in, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX); + /* empty the buffer after setting filter, just in case anything + got through */ + while (Pm_Read(in, buffer, 1)) ; + + /* wait for input */ + printf("Waiting for input...\n"); + while (Pm_Read(in, buffer, 1) < 1) Pt_Sleep(10); + + /* send two replies (only one would be fine) */ + checkerror(Pm_Write(out, buffer, 1)); + printf("Received input, writing output...\n"); + + /* wait 1s so receiver can get the message before we shut down */ + Pt_Sleep(1000); + printf("****** Closing everything and shutting down...\n"); + + /* expect 2 open ports */ + check_ports(device_count, in_id, 'o', out_id, 'o', TRUE); + /* close in */ + checkerror(Pm_Close(in)); + check_ports(device_count, in_id, 'c', out_id, 'o', TRUE); + + /* close out */ + checkerror(Pm_Close(out)); + check_ports(device_count, in_id, 'c', out_id, 'c', TRUE); + + /* delete in */ + checkerror(Pm_DeleteVirtualDevice(in_id)); + check_ports(device_count, in_id, 'd', out_id, 'c', TRUE); + + /* delete out */ + checkerror(Pm_DeleteVirtualDevice(out_id)); + check_ports(device_count, in_id, 'd', out_id, 'd', TRUE); + + /* we are done */ + Pm_Terminate(); +} + + +int main(int argc, char *argv[]) +{ + int i; + show_usage(); + for (i = 0; i < 3; i++) { + test(); + } + printf("finished virttest (SUCCESS). Type ENTER to quit..."); + while (getchar() != '\n') ; + return 0; +} diff --git a/3rdparty/portmidi/pm_win/README_WIN.txt b/3rdparty/portmidi/pm_win/README_WIN.txt index fb9cff1583d..77d18680783 100644 --- a/3rdparty/portmidi/pm_win/README_WIN.txt +++ b/3rdparty/portmidi/pm_win/README_WIN.txt @@ -2,7 +2,7 @@ File: PortMidi Win32 Readme Author: Belinda Thom, June 16 2002 Revised by: Roger Dannenberg, June 2002, May 2004, June 2007, Umpei Kurokawa, June 2007 - Roger Dannenberg Sep 2009 + Roger Dannenberg Sep 2009, May 2022 Contents: Using Portmidi @@ -18,187 +18,32 @@ Contents: USING PORTMIDI: ============================================================================= -Using Microsoft Visual C++ project files (provided with PortMidi), there -are two configurations of the PortMidi library. The Debug version is -intended for debugging, especially in a console application. The Debug -version enables some extra error checking and outputs some text as well -as a prompt to type ENTER so that you don't lose any debugging text when -the program exits. You can turn off this extra debugging info by taking -out the compile-time definition for DEBUG. (But leave _DEBUG, which I -think is important for compiling in Debug mode.) This debugging version also -defines PM_CHECK_ERRORS, which forces a check for error return codes from -every call to PortMidi. You can disable this checking (especially if you -want to handle error codes in your own way) by removing PM_CHECK_ERRORS -from the predefined symbols list in the Settings dialog box. +I recommend building a static library and linking with your +application. PortMidi is not large. See ../README.md for +basic compiling instructions. -PortMidi is designed to run without a console and should work perfectly -well within a graphical user interface application. The Release version -is both optimized and lacking the debugging printout code of the Debug -version. - -Read the portmidi.h file for PortMidi API details on using the PortMidi API. -See <...>\pm_test\test.c and other files in pm_test for usage examples. - -============================================================================= -TO INSTALL PORTMIDI: -============================================================================= -1) get current source from the portmedia project at SourceForge.net - -2) copy source into directory: <...>\portmidi - -============================================================================= -TO COMPILE PORTMIDI: -============================================================================= - -3) cd to or open the portmidi directory - -4) start or click on the portmidi.sln workspace (note, all Visual Studio - files are built by CMake. If you need a different version or have - problems with paths, try rebuilding the Visual Studio project files - using CMake -- See "Using other versions of visual C++" below.) - -5) the following projects exist within this workspace: - - portmidi-static, portmidi-dynamic (versions of the PortMidi library) - - test (simple midi I/O testing) - - midithread (an example illustrating low-latency MIDI processing - using a dedicated low-latency thread) - - sysex (simple sysex message I/O testing) - - latency (uses porttime to measure system latency) - - midithru (an example illustrating software MIDI THRU) - - qtest (a test of the new multicore-safe queue implementation) - - mm (allows monitoring of midi messages) - - pmjni (a dll to provide an interface to PortMidi for Java) - -6) set the Java SDK path using one of two methods: - Method 1: open portmidi/CMakeLists.txt with CMake, configure, and - generate -- this should find the Java SDK path and update your - solution and project files - Method 2: (does not require CMake): - - open the pmjni project properties - - visit Configuration Properties, C/C++, General - - find Additional Include Directories property and open the editor (...) - - at the end of the list, you will find two paths mentioning Java - - these are absolute paths to the Java SDK; you'll need to install the - Java SDK (from Sun) and update these directories in order to build - this project. - - similarly, the Linker->Input->Additional Dependencies list has a - path to the jvm.lib file, which needs to be correct(ed). - -6) use Build->Batch Build ... to build everything in the project. If a - build fails, try building again. There seem to be some missing - dependencies, so you may have to "ALL_BUILD" several times before - everything builds successfully. - -7) The settings for these projects were distributed in the zip file, so - compile should just work. - -8) run test project; use the menu that shows up from the command prompt to - test that portMidi works on your system. tests include: - - verify midi output works - - verify midi input works - -9) run other projects if you wish: sysex, latency, midithread, mm, - qtest, midithru - -10) compile the java code: - - cd pm_java - - make.bat - + If there is a problem running javac, note that you must have - a path to javac.exe on your PATH environment variable. Edit - your path (in Vista) using Control Panel > User Accounts > - User Accounts > Change my environment variables; then select - Path and click Edit... After changing, you will have to - restart the command window to see any effect. - + In Vista, you may get a warning about running - UpdateRsrcJavaExe.exe. This is called by make.bat, and you - should allow the program to run. - + Note that make.bat does not build pmjni\jportmidi_JPortMidiApi.h - because it is included in the distribution. You can rebuild it - from sources as follows: - cd pm_java - javah jportmidi.JPortMidiApi - move jportmidi_JPortMidiApi pmjni\jportmidi_JPortMidiApi.h - -11) you might wish to move pm_java/win32 to another location; run the - pmdefaults.exe program from the (entire) win32 directory to use - PmDefaults. This program let's you select default input/output - midi devices for PortMidi applications. - -============================================================================ -ABOUT CMAKE -============================================================================ - -cmake was used to generate .vcproj files. cmake embeds absolute paths -into .vcproj files, which makes the files non-portable to other systems. -To work around this problem, pm_win\clean_up_vcproj.bat can be used to -replace absolute paths with relative paths. To use it, you will need to -install gawk and set your search path to allow you to execute gawk, e.g. -my path includes "C:\Program Files\GnuWin32\bin;". You will also need to -edit pm_win\clean_up_vcproj.awk, replacing C:\Users\rbd\portmidi with -whatever absolute path cmake uses in your vcproj files. - -This is not a general or robust fix, but it seems to work with the -vcproj files currently created by CMake. - -============================================================================ -USING OTHER VERSIONS OF VISUAL C++ -============================================================================ +The Windows version has a couple of extra switches: You can define +DEBUG and MMDEBUG for a few extra messages (see the code). -You can use cmake to make Visual Studio solution and project files. -If you do not want to use the provided Version 9 project files, install -cmake, run it, set the "Where is the source code" box to your portmidi -directory, and click on Configure. A menu will allow you to choose the -Visual Studio project version you want. Click Configure once again, then -Generate, and you should be all set to open portmidi.sln. +If PM_CHECK_ERRORS is defined, PortMidi reports and exits on any +error. This requires terminal output to see, and aborts your +application, so it's only intended for quick command line programs +where you do not care to check return values and handle errors +more robustly. -============================================================================ -TO CREATE YOUR OWN PORTMIDI CLIENT APPLICATION: -============================================================================ - -NOTE: this section needs to be reviewed and tested. My suggestion would -be to copy the test project file (test.dsp) and modify it. -RBD +PortMidi is designed to run without a console and should work perfectly +well within a graphical user interface application. -The easiest way is to start a new project w/in the portMidi workspace: +Read the portmidi.h file for PortMidi API details on using the PortMidi API. +See <...>\pm_test\testio.c and other files in pm_test for usage examples. -1) To open new project: - - File->New->Projects - - Location: <...>\portmidi\<yourProjectName> - - check Add to current workspace - - select Win32 Console Application (recommended for now) - - do *NOT* select the "make dependency" box (you will explicitly do this - in the next step) - - Click OK - - Select "An Empty Project" and click Finish +There are many other programs in pm_test, including a MIDI monitor. - In Visual C++ 2005 Express Edition, - - File->New->Projects - - Location: <...>\portmidi\<yourProjectName> - - select Add to solution - - select CLR Empty project in CLR - - select Win32 Console Application in Win32 - - select Empty project in General - -2) Now this project will be the active project. Make it explicitly depend - on PortMidi dll: - - Project->Dependencies - - Click pm_dll - -3) add whatever files you wish to add to your new project, using portMidi - calls as desired (see USING PORTMIDI at top of this readme) - -4) when you include portMidi files, do so like this: - - #include "..\pm_common\portmidi.h" - - etc. - -5) build and run your project ============================================================================ DESIGN NOTES ============================================================================ -PortMidi for Win32 exists as a simple static library, -with Win32-specific code in pmwin.c and MM-specific code in pmwinmm.c. - Orderly cleanup after errors are encountered is based on a fixed order of steps and state changes to reflect each step. Here's the order: @@ -218,8 +63,7 @@ To open input: - return - return -SYSEX HANDLING -- the most complex, least exercised, and therefore most - buggy part of PortMidi (but maybe bugs are finally gone) +SYSEX HANDLING There are three cases: simple output, stream output, input Each must deal with: @@ -327,15 +171,4 @@ part of PortMidi is allowed to directly copy sysex bytes to "fill_base[*fill_offset_ptr++]" until *fill_offset_ptr reaches fill_length. See the code for details. ------------ - -Additional notes on using VS 2005 (maybe this is obsolete now?): - -1) Make sure "Configuration: All Configurations" is selected in all of the following Properties modifications! - -2) In my case the project defaulted to compiling all .c files with the C++ compiler, which was disastrous. I had to go to set Properties for each file, to wit: Expand Configuration Properties, Expand C/C++, Select Advanced, set the Compile As popup to Compile as C Code (/TC). (For better or worse, the project I inherited has a bunch of .c files that rely on C++ features, so I couldn't reliably set this the project properties level.) - -3) While you're there, make sure that the C/C++ -> General -> "Compile with Common Language Runtime support" is set to "No Common Language Runtime support" (the C compiler *can't* support CLR, but VS won't do anything useful like automatically set the two options to match)-. - -4) I never got VS precompiled header thing to work sensibly, so I took the path of least resistance and turned PCH's off for all my files. Properties -> Configuration Properties -> C/C++ -> Precompiled Headers -> Create/Use Precompiled Header popup set to "Not Using Precompiled Headers". The compiler is reasonably fast even if it has to parse all the header files, so unless someone wants to explain VS's PCHs to me, the hell with it, I say. diff --git a/3rdparty/portmidi/pm_win/clean_cmake.bat b/3rdparty/portmidi/pm_win/clean_cmake.bat deleted file mode 100644 index e9579e67d3f..00000000000 --- a/3rdparty/portmidi/pm_win/clean_cmake.bat +++ /dev/null @@ -1,6 +0,0 @@ -del /Q ..\CMakeFiles -del /Q ..\CMakeCache.txt -del /Q ..\pm_test\CMakeFiles -del /Q ..\pm_common\CMakeFiles -del /Q ..\pm_dylib\CMakeFiles - diff --git a/3rdparty/portmidi/pm_win/clean_up_vcproj.awk b/3rdparty/portmidi/pm_win/clean_up_vcproj.awk deleted file mode 100644 index a3eadfcb848..00000000000 --- a/3rdparty/portmidi/pm_win/clean_up_vcproj.awk +++ /dev/null @@ -1,70 +0,0 @@ -# gawk script to convert CMake-generated Visual Studio projects into -# stand-alone project files -# -# Roger Dannenberg, October 2009 -# -# the result uses relative path names (so you can install the project on -# any machine and use it) -# -# NOTE: to run this, you must assign base_relative to the relative path -# from the vcproj file to portmidi, e.g. base_relative=.. or base_relative=. - -BEGIN { - state = "normal"; - #=================IMPORTANT==================== - # change the following path to the path in which - # the CMakeLists.txt file resides: - base_path = "C:\\\\Users\\\\rbd\\\\portmedia\\\\portmidi"; - #============================================== - - base_path_2 = base_path; - gsub("\\\\\\\\", "/", base_path_2) - cmake_stuff = 0; # flag to print <file> ... </file> text -} -# this case removes CMake phases from project -state == "cmakelists" { - # print "IN CMAKELISTS " - file_text = file_text "\n" $0 # collect the <file> ... </file> section - if (index($0, "CMakeLists.txt") > 0) { - cmake_stuff = 1 # remember to delete this <file> ... </file> section - } - - if (index($0, "</File>") > 0) { - state = "normal"; - if (cmake_stuff == 0) { - gsub(base_path, base_relative, file_text) - gsub(base_path_2, base_relative, file_text) - print file_text; - } - cmake_stuff = 0; - }; - next -} - -# this is the normal case, not in buildPhases list -state == "normal" { - # print "NOT IN BUILD PHASES" - # take out all the absolute paths - gsub(base_path, base_relative, $0); - gsub(base_path_2, base_relative, $0); - # special processing for <file> ... </file> text: - if ($0 ~ "<File$") { - file_text = $0; - cmake_stuff = 0; # innocent (keep text) until proven guilty - state = "cmakelists"; - next # do not print this line - }; - # THIS CODE WOULD ALLOW portmidi-static and portmidi-dynamic IN - # pm_commmon. I DECIDED TO TRY PUTTING THEM IN SEPARATE DIRECTORIES - # INSTEAD. - # Use static libraries for everything except portmidi-dynamic - #if (($0 ~ "RuntimeLibrary=") && (base_relative ~ "dynamic")) { - # if ($0 ~ 2) { - # $0 = "\t\t\t\tRuntimeLibrary=\"0\""; - # } else if ($0 ~ 3) { - # $0 = "\t\t\t\tRuntimeLibrary=\"1\""; - # } - print $0; - next -} - diff --git a/3rdparty/portmidi/pm_win/clean_up_vcproj.bat b/3rdparty/portmidi/pm_win/clean_up_vcproj.bat deleted file mode 100644 index 0557876431c..00000000000 --- a/3rdparty/portmidi/pm_win/clean_up_vcproj.bat +++ /dev/null @@ -1,76 +0,0 @@ -@echo off -rem Start this program in portmidi\pm_win -cd ..\pm_common - -rename portmidi-static.vcproj portmidi-static.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. portmidi-static.vcproj-cmake > portmidi-static.vcproj -del portmidi-static.vcproj-cmake -echo portmidi-static - -rename pmjni.vcproj pmjni.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. pmjni.vcproj-cmake > pmjni.vcproj -del pmjni.vcproj-cmake -echo pmjni - -cd ../pm_dylib - -rename portmidi-dynamic.vcproj portmidi-dynamic.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. portmidi-dynamic.vcproj-cmake > portmidi-dynamic.vcproj -del portmidi-dynamic.vcproj-cmake -echo portmidi-dynamic - -cd ..\pm_test - -rename latency.vcproj latency.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. latency.vcproj-cmake > latency.vcproj -del latency.vcproj-cmake -echo latency - -rename midiclock.vcproj midiclock.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. midiclock.vcproj-cmake > midiclock.vcproj -del midiclock.vcproj-cmake -echo midiclock - -rename midithread.vcproj midithread.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. midithread.vcproj-cmake > midithread.vcproj -del midithread.vcproj-cmake -echo midithread - -rename midithru.vcproj midithru.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. midithru.vcproj-cmake > midithru.vcproj -del midithru.vcproj-cmake -echo midithru - -rename mm.vcproj mm.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. mm.vcproj-cmake > mm.vcproj -del mm.vcproj-cmake -echo mm - -rename qtest.vcproj qtest.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. qtest.vcproj-cmake > qtest.vcproj -del qtest.vcproj-cmake -echo qtest - -rename sysex.vcproj sysex.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. sysex.vcproj-cmake > sysex.vcproj -del sysex.vcproj-cmake -echo sysex - -rename test.vcproj test.vcproj-cmake -gawk -f ..\pm_win\clean_up_vcproj.awk -v base_relative=.. test.vcproj-cmake > test.vcproj -del test.vcproj-cmake - -cd .. -echo test - -rename ALL_BUILD.vcproj ALL_BUILD.vcproj-cmake -gawk -f pm_win\clean_up_vcproj.awk -v base_relative=. ALL_BUILD.vcproj-cmake > ALL_BUILD.vcproj -del ALL_BUILD.vcproj-cmake -echo ALL_BUILD - -rename ZERO_CHECK.vcproj ZERO_CHECK.vcproj-cmake -gawk -f pm_win\clean_up_vcproj.awk -v base_relative=. ZERO_CHECK.vcproj-cmake > ZERO_CHECK.vcproj -del ZERO_CHECK.vcproj-cmake -echo ZERO_CHECK - -cd pm_win diff --git a/3rdparty/portmidi/pm_win/pmwin.c b/3rdparty/portmidi/pm_win/pmwin.c index a57ed878df6..cca83be08ca 100644 --- a/3rdparty/portmidi/pm_win/pmwin.c +++ b/3rdparty/portmidi/pm_win/pmwin.c @@ -20,7 +20,6 @@ #ifdef DEBUG #include "stdio.h" #endif -#undef UNICODE #include <windows.h> /* pm_exit is called when the program exits. @@ -29,23 +28,21 @@ */ static void pm_exit(void) { pm_term(); -#ifdef DEBUG -#define STRING_MAX 80 - { - char line[STRING_MAX]; - printf("Type ENTER...\n"); - /* note, w/o this prompting, client console application can not see one - of its errors before closing. */ - fgets(line, STRING_MAX, stdin); - } -#endif } +static BOOL WINAPI ctrl_c_handler(DWORD fdwCtrlType) +{ + exit(1); /* invokes pm_exit() */ + ExitProcess(1); /* probably never called */ + return TRUE; +} + /* pm_init is the windows-dependent initialization.*/ void pm_init(void) { atexit(pm_exit); + SetConsoleCtrlHandler(ctrl_c_handler, TRUE); #ifdef DEBUG printf("registered pm_exit with atexit()\n"); #endif @@ -59,40 +56,41 @@ void pm_term(void) { } -static PmDeviceID pm_get_default_device_id(int is_input, char *key) { +static PmDeviceID pm_get_default_device_id(int is_input, const char *key) { HKEY hkey; #define PATTERN_MAX 256 char pattern[PATTERN_MAX]; - DWORD pattern_max = PATTERN_MAX; + long pattern_max = PATTERN_MAX; DWORD dwType; /* Find first input or device -- this is the default. */ PmDeviceID id = pmNoDevice; int i, j; Pm_Initialize(); /* make sure descriptors exist! */ - for (i = 0; i < pm_descriptor_index; i++) { - if (descriptors[i].pub.input == is_input) { + for (i = 0; i < pm_descriptor_len; i++) { + if (pm_descriptors[i].pub.input == is_input) { id = i; break; } } /* Look in registry for a default device name pattern. */ - if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey) != + if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey) != ERROR_SUCCESS) { return id; } - if (RegOpenKeyExA(hkey, "JavaSoft", 0, KEY_READ, &hkey) != + if (RegOpenKeyEx(hkey, "JavaSoft", 0, KEY_READ, &hkey) != ERROR_SUCCESS) { return id; } - if (RegOpenKeyExA(hkey, "Prefs", 0, KEY_READ, &hkey) != + if (RegOpenKeyEx(hkey, "Prefs", 0, KEY_READ, &hkey) != ERROR_SUCCESS) { return id; } - if (RegOpenKeyExA(hkey, "/Port/Midi", 0, KEY_READ, &hkey) != + if (RegOpenKeyEx(hkey, "/Port/Midi", 0, KEY_READ, &hkey) != ERROR_SUCCESS) { return id; } - if (RegQueryValueExA(hkey, key, NULL, &dwType, (BYTE *)pattern, &pattern_max) != + if (RegQueryValueEx(hkey, key, NULL, &dwType, (BYTE *) pattern, + (DWORD *) &pattern_max) != ERROR_SUCCESS) { return id; } @@ -118,15 +116,15 @@ static PmDeviceID pm_get_default_device_id(int is_input, char *key) { } -PmDeviceID Pm_GetDefaultInputDeviceID() { +PmDeviceID Pm_GetDefaultInputDeviceID(void) { return pm_get_default_device_id(TRUE, - (char *)"/P/M_/R/E/C/O/M/M/E/N/D/E/D_/I/N/P/U/T_/D/E/V/I/C/E"); + "/P/M_/R/E/C/O/M/M/E/N/D/E/D_/I/N/P/U/T_/D/E/V/I/C/E"); } -PmDeviceID Pm_GetDefaultOutputDeviceID() { +PmDeviceID Pm_GetDefaultOutputDeviceID(void) { return pm_get_default_device_id(FALSE, - (char *)"/P/M_/R/E/C/O/M/M/E/N/D/E/D_/O/U/T/P/U/T_/D/E/V/I/C/E"); + "/P/M_/R/E/C/O/M/M/E/N/D/E/D_/O/U/T/P/U/T_/D/E/V/I/C/E"); } diff --git a/3rdparty/portmidi/pm_win/pmwinmm.c b/3rdparty/portmidi/pm_win/pmwinmm.c index 4f31cdaca3c..dfe0255ac22 100644 --- a/3rdparty/portmidi/pm_win/pmwinmm.c +++ b/3rdparty/portmidi/pm_win/pmwinmm.c @@ -1,16 +1,12 @@ /* pmwinmm.c -- system specific definitions */ -#ifdef _MSC_VER - #pragma warning(disable: 4133) // stop warnings about implicit typecasts -#endif - #ifndef _WIN32_WINNT /* without this define, InitializeCriticalSectionAndSpinCount is * undefined. This version level means "Windows 2000 and higher" */ #define _WIN32_WINNT 0x0500 #endif -#undef UNICODE + #include "windows.h" #include "mmsystem.h" #include "portmidi.h" @@ -20,28 +16,10 @@ #include <string.h> #include "porttime.h" -#ifndef _WINDOWS_H -typedef unsigned int UINT32; -#endif - -#ifndef _WINDOWS_H -#ifdef _MSC_VER -typedef unsigned __int64 UINT64; -#else -__extension__ typedef unsigned long long UINT64; -#endif -#endif - -#ifdef PTR64 -typedef UINT64 FPTR; -#else -typedef UINT32 FPTR; -#endif - /* asserts used to verify portMidi code logic is sound; later may want something more graceful */ #include <assert.h> -#ifdef DEBUG +#ifdef MMDEBUG /* this printf stuff really important for debugging client app w/host errors. probably want to do something else besides read/write from/to console for portability, however */ @@ -56,16 +34,12 @@ typedef UINT32 FPTR; /* callback routines */ static void CALLBACK winmm_in_callback(HMIDIIN hMidiIn, - WORD wMsg, DWORD dwInstance, - DWORD dwParam1, DWORD dwParam2); + UINT wMsg, DWORD_PTR dwInstance, + DWORD_PTR dwParam1, DWORD_PTR dwParam2); static void CALLBACK winmm_streamout_callback(HMIDIOUT hmo, UINT wMsg, - DWORD dwInstance, DWORD dwParam1, - DWORD dwParam2); -#ifdef USE_SYSEX_BUFFERS -static void CALLBACK winmm_out_callback(HMIDIOUT hmo, UINT wMsg, - DWORD dwInstance, DWORD dwParam1, - DWORD dwParam2); -#endif + DWORD_PTR dwInstance, + DWORD_PTR dwParam1, + DWORD_PTR dwParam2); extern pm_fns_node pm_winmm_in_dictionary; extern pm_fns_node pm_winmm_out_dictionary; @@ -115,10 +89,6 @@ The following constants help to represent these design parameters: #define MIDIHDR_SYSEX_BUFFER_LENGTH(x) ((x) + sizeof(long)*3) /* A MIDIHDR with a sysex message is the buffer length plus the header size */ #define MIDIHDR_SYSEX_SIZE(x) (MIDIHDR_SYSEX_BUFFER_LENGTH(x) + sizeof(MIDIHDR)) -#ifdef USE_SYSEX_BUFFERS -/* Size of a MIDIHDR with a buffer contaning multiple MIDIEVENT structures */ -#define MIDIHDR_SIZE(x) ((x) + sizeof(MIDIHDR)) -#endif /* ============================================================================== @@ -135,7 +105,7 @@ MIDIOUTCAPS midi_out_mapper_caps; UINT midi_num_outputs = 0; /* per device info */ -typedef struct midiwinmm_struct { +typedef struct winmm_info_struct { union { HMIDISTRM stream; /* windows handle for stream */ HMIDIOUT out; /* windows handle for out calls */ @@ -151,13 +121,6 @@ typedef struct midiwinmm_struct { int num_buffers; /* how many buffers allocated in buffers array */ int next_buffer; /* index of next buffer to send */ HANDLE buffer_signal; /* used to wait for buffer to become free */ -#ifdef USE_SYSEX_BUFFERS - /* sysex buffers will be allocated only when - * a sysex message is sent. The size of the buffer is fixed. - */ - LPMIDIHDR sysex_buffers[NUM_SYSEX_BUFFERS]; /* pool of buffers for sysex data */ - int next_sysex_buffer; /* index of next sysexbuffer to send */ -#endif unsigned long last_time; /* last output time */ int first_message; /* flag: treat first message differently */ int sysex_mode; /* middle of sending sysex */ @@ -167,9 +130,8 @@ typedef struct midiwinmm_struct { unsigned long sync_time; /* when did we last determine delta? */ long delta; /* difference between stream time and real time */ - int error; /* host error from doing port midi call */ CRITICAL_SECTION lock; /* prevents reentrant callbacks (input only) */ -} midiwinmm_node, *midiwinmm_type; +} winmm_info_node, *winmm_info_type; /* @@ -198,9 +160,9 @@ static void pm_winmm_general_inputs(void) if (wRtn == MMSYSERR_NOERROR) { /* ignore errors here -- if pm_descriptor_max is exceeded, some devices will not be accessible. */ - pm_add_device((char *)"MMSystem", midi_in_caps[i].szPname, TRUE, - (void *)(FPTR)i, - &pm_winmm_in_dictionary); +#pragma warning(suppress: 4047) // coerce non-pointer to pointer is OK + pm_add_device("MMSystem", midi_in_caps[i].szPname, TRUE, FALSE, + (void *) (intptr_t) i, &pm_winmm_in_dictionary); } } } @@ -217,8 +179,9 @@ static void pm_winmm_mapper_input(void) (LPMIDIINCAPS) & midi_in_mapper_caps, sizeof(MIDIINCAPS)); if (wRtn == MMSYSERR_NOERROR) { - pm_add_device((char *)"MMSystem", midi_in_mapper_caps.szPname, TRUE, - (void *)(FPTR)MIDIMAPPER, &pm_winmm_in_dictionary); +#pragma warning(suppress: 4047) // coerce non-pointer to pointer is OK + pm_add_device("MMSystem", midi_in_mapper_caps.szPname, TRUE, FALSE, + (void *) (intptr_t) MIDIMAPPER, &pm_winmm_in_dictionary); } } @@ -228,7 +191,7 @@ static void pm_winmm_general_outputs(void) UINT i; DWORD wRtn; midi_num_outputs = midiOutGetNumDevs(); - midi_out_caps = pm_alloc( sizeof(MIDIOUTCAPS) * midi_num_outputs ); + midi_out_caps = pm_alloc(sizeof(MIDIOUTCAPS) * midi_num_outputs); if (midi_out_caps == NULL) { /* no error is reported -- see pm_winmm_general_inputs */ @@ -239,9 +202,9 @@ static void pm_winmm_general_outputs(void) wRtn = midiOutGetDevCaps(i, (LPMIDIOUTCAPS) & midi_out_caps[i], sizeof(MIDIOUTCAPS)); if (wRtn == MMSYSERR_NOERROR) { - pm_add_device((char *)"MMSystem", midi_out_caps[i].szPname, FALSE, - (void *)(FPTR)i, - &pm_winmm_out_dictionary); +#pragma warning(suppress: 4047) // coerce non-pointer to pointer is OK + pm_add_device("MMSystem", midi_out_caps[i].szPname, FALSE, FALSE, + (void *) (intptr_t) i, &pm_winmm_out_dictionary); } } } @@ -256,23 +219,18 @@ static void pm_winmm_mapper_output(void) wRtn = midiOutGetDevCaps((UINT) MIDIMAPPER, (LPMIDIOUTCAPS) & midi_out_mapper_caps, sizeof(MIDIOUTCAPS)); if (wRtn == MMSYSERR_NOERROR) { - pm_add_device((char *)"MMSystem", midi_out_mapper_caps.szPname, FALSE, - (void *)(FPTR)MIDIMAPPER, &pm_winmm_out_dictionary); +#pragma warning(suppress: 4047) // coerce non-pointer to pointer is OK + pm_add_device("MMSystem", midi_out_mapper_caps.szPname, FALSE, FALSE, + (void *) (intptr_t) MIDIMAPPER, &pm_winmm_out_dictionary); } } /* -========================================================================================= +============================================================================ host error handling -========================================================================================= +============================================================================ */ -static unsigned int winmm_has_host_error(PmInternal * midi) -{ - midiwinmm_type m = (midiwinmm_type)midi->descriptor; - return m->error; -} - /* str_copy_len -- like strcat, but won't overrun the destination string */ /* @@ -280,41 +238,30 @@ static unsigned int winmm_has_host_error(PmInternal * midi) */ static int str_copy_len(char *dst, char *src, int len) { + // Note: Visual C will suggest using a non-portable strncpy_s here +#pragma warning(suppress: 4996) // suppress warning for just this line strncpy(dst, src, len); /* just in case suffex is greater then len, terminate with zero */ dst[len - 1] = 0; - return strlen(dst); + return (int) strlen(dst); } -static void winmm_get_host_error(PmInternal * midi, char * msg, UINT len) +static unsigned int winmm_check_host_error(PmInternal *midi) { - /* precondition: midi != NULL */ - midiwinmm_node * m = (midiwinmm_node *) midi->descriptor; - char *hdr1 = (char *)"Host error: "; - //char *hdr2 = (char *)"Host callback error: "; - - msg[0] = 0; /* initialize result string to empty */ - - if (descriptors[midi->device_id].pub.input) { - /* input and output use different winmm API calls */ - if (m) { /* make sure there is an open device to examine */ - if (m->error != MMSYSERR_NOERROR) { - int n = str_copy_len(msg, hdr1, len); - /* read and record host error */ - midiInGetErrorText(m->error, msg + n, len - n); - //assert(err == MMSYSERR_NOERROR); - m->error = MMSYSERR_NOERROR; - } - } - } else { /* output port */ - if (m) { - if (m->error != MMSYSERR_NOERROR) { - int n = str_copy_len(msg, hdr1, len); - midiOutGetErrorText(m->error, msg + n, len - n); - //assert(err == MMSYSERR_NOERROR); - m->error = MMSYSERR_NOERROR; - } + return FALSE; +} + + +static void improve_winerr(int pm_hosterror, char *message) +{ + if (pm_hosterror == MMSYSERR_NOMEM) { + /* add explanation to Window's confusing error message */ + /* if there's room: */ + if (PM_HOST_ERROR_MSG_LEN - strlen(pm_hosterror_text) > 60) { +#pragma warning(suppress: 4996) // don't use suggested strcat_s + strcat(pm_hosterror_text, " Probably this MIDI device is open " + "in another application."); } } } @@ -339,123 +286,59 @@ static MIDIHDR *allocate_buffer(long data_size) return hdr; } -#ifdef USE_SYSEX_BUFFERS -static MIDIHDR *allocate_sysex_buffer(long data_size) -{ - /* we're actually allocating more than data_size because the buffer - * will include the MIDIEVENT header in addition to the data - */ - LPMIDIHDR hdr = (LPMIDIHDR) pm_alloc(MIDIHDR_SYSEX_SIZE(data_size)); - MIDIEVENT *evt; - if (!hdr) return NULL; - evt = (MIDIEVENT *) (hdr + 1); /* place MIDIEVENT after header */ - hdr->lpData = (LPSTR) evt; - hdr->dwFlags = 0; - hdr->dwUser = 0; - return hdr; -} -#endif -static PmError allocate_buffers(midiwinmm_type m, long data_size, long count) +static PmError allocate_buffers(winmm_info_type info, long data_size, + long count) { int i; /* buffers is an array of count pointers to MIDIHDR/MIDIEVENT struct */ - m->num_buffers = 0; /* in case no memory can be allocated */ - m->buffers = (LPMIDIHDR *) pm_alloc(sizeof(LPMIDIHDR) * count); - if (!m->buffers) return pmInsufficientMemory; - m->max_buffers = count; + info->num_buffers = 0; /* in case no memory can be allocated */ + info->buffers = (LPMIDIHDR *) pm_alloc(sizeof(LPMIDIHDR) * count); + if (!info->buffers) return pmInsufficientMemory; + info->max_buffers = count; for (i = 0; i < count; i++) { LPMIDIHDR hdr = allocate_buffer(data_size); if (!hdr) { /* free everything allocated so far and return */ - for (i = i - 1; i >= 0; i--) pm_free(m->buffers[i]); - pm_free(m->buffers); - m->max_buffers = 0; + for (i = i - 1; i >= 0; i--) pm_free(info->buffers[i]); + pm_free(info->buffers); + info->max_buffers = 0; return pmInsufficientMemory; } - m->buffers[i] = hdr; /* this may be NULL if allocation fails */ + info->buffers[i] = hdr; /* this may be NULL if allocation fails */ } - m->num_buffers = count; + info->num_buffers = count; return pmNoError; } -#ifdef USE_SYSEX_BUFFERS -static PmError allocate_sysex_buffers(midiwinmm_type m, long data_size) -{ - PmError rslt = pmNoError; - /* sysex_buffers is an array of count pointers to MIDIHDR/MIDIEVENT struct */ - int i; - for (i = 0; i < NUM_SYSEX_BUFFERS; i++) { - LPMIDIHDR hdr = allocate_sysex_buffer(data_size); - - if (!hdr) rslt = pmInsufficientMemory; - m->sysex_buffers[i] = hdr; /* this may be NULL if allocation fails */ - hdr->dwFlags = 0; /* mark as free */ - } - return rslt; -} -#endif - -#ifdef USE_SYSEX_BUFFERS -static LPMIDIHDR get_free_sysex_buffer(PmInternal *midi) -{ - LPMIDIHDR r = NULL; - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - if (!m->sysex_buffers[0]) { - if (allocate_sysex_buffers(m, SYSEX_BYTES_PER_BUFFER)) { - return NULL; - } - } - /* busy wait until we find a free buffer */ - while (TRUE) { - int i; - for (i = 0; i < NUM_SYSEX_BUFFERS; i++) { - /* cycle through buffers, modulo NUM_SYSEX_BUFFERS */ - m->next_sysex_buffer++; - if (m->next_sysex_buffer >= NUM_SYSEX_BUFFERS) m->next_sysex_buffer = 0; - r = m->sysex_buffers[m->next_sysex_buffer]; - if ((r->dwFlags & MHDR_PREPARED) == 0) goto found_sysex_buffer; - } - /* after scanning every buffer and not finding anything, block */ - if (WaitForSingleObject(m->buffer_signal, 1000) == WAIT_TIMEOUT) { -#ifdef DEBUG - printf("PortMidi warning: get_free_sysex_buffer() wait timed out after 1000ms\n"); -#endif - } - } -found_sysex_buffer: - r->dwBytesRecorded = 0; - r->dwBufferLength = 0; /* changed to correct value later */ - return r; -} -#endif static LPMIDIHDR get_free_output_buffer(PmInternal *midi) { LPMIDIHDR r = NULL; - midiwinmm_type m = (midiwinmm_type) midi->descriptor; + winmm_info_type info = (winmm_info_type) midi->api_info; while (TRUE) { int i; - for (i = 0; i < m->num_buffers; i++) { - /* cycle through buffers, modulo m->num_buffers */ - m->next_buffer++; - if (m->next_buffer >= m->num_buffers) m->next_buffer = 0; - r = m->buffers[m->next_buffer]; + for (i = 0; i < info->num_buffers; i++) { + /* cycle through buffers, modulo info->num_buffers */ + info->next_buffer++; + if (info->next_buffer >= info->num_buffers) info->next_buffer = 0; + r = info->buffers[info->next_buffer]; if ((r->dwFlags & MHDR_PREPARED) == 0) goto found_buffer; } /* after scanning every buffer and not finding anything, block */ - if (WaitForSingleObject(m->buffer_signal, 1000) == WAIT_TIMEOUT) { -#ifdef DEBUG - printf("PortMidi warning: get_free_output_buffer() wait timed out after 1000ms\n"); + if (WaitForSingleObject(info->buffer_signal, 1000) == WAIT_TIMEOUT) { +#ifdef MMDEBUG + printf("PortMidi warning: get_free_output_buffer() " + "wait timed out after 1000ms\n"); #endif /* if we're trying to send a sysex message, maybe the * message is too big and we need more message buffers. * Expand the buffer pool by 128KB using 1024-byte buffers. */ /* first, expand the buffers array if necessary */ - if (!m->buffers_expanded) { + if (!info->buffers_expanded) { LPMIDIHDR *new_buffers = (LPMIDIHDR *) pm_alloc( - (m->num_buffers + NUM_EXPANSION_BUFFERS) * - sizeof(LPMIDIHDR)); + (info->num_buffers + NUM_EXPANSION_BUFFERS) * + sizeof(LPMIDIHDR)); /* if no memory, we could return a no-memory error, but user * probably will be unprepared to deal with it. Maybe the * MIDI driver is temporarily hung so we should just wait. @@ -463,21 +346,21 @@ static LPMIDIHDR get_free_output_buffer(PmInternal *midi) */ if (!new_buffers) continue; /* copy buffers to new_buffers and replace buffers */ - memcpy(new_buffers, m->buffers, - m->num_buffers * sizeof(LPMIDIHDR)); - pm_free(m->buffers); - m->buffers = new_buffers; - m->max_buffers = m->num_buffers + NUM_EXPANSION_BUFFERS; - m->buffers_expanded = TRUE; + memcpy(new_buffers, info->buffers, + info->num_buffers * sizeof(LPMIDIHDR)); + pm_free(info->buffers); + info->buffers = new_buffers; + info->max_buffers = info->num_buffers + NUM_EXPANSION_BUFFERS; + info->buffers_expanded = TRUE; } /* next, add one buffer and return it */ - if (m->num_buffers < m->max_buffers) { + if (info->num_buffers < info->max_buffers) { r = allocate_buffer(EXPANSION_BUFFER_LEN); /* again, if there's no memory, we may not really be * dead -- maybe the system is temporarily hung and * we can just wait longer for a message buffer */ if (!r) continue; - m->buffers[m->num_buffers++] = r; + info->buffers[info->num_buffers++] = r; goto found_buffer; /* break out of 2 loops */ } /* else, we've allocated all NUM_EXPANSION_BUFFERS buffers, @@ -493,63 +376,20 @@ found_buffer: return r; } -#ifdef EXPANDING_SYSEX_BUFFERS -note: this is not working code, but might be useful if you want - to grow sysex buffers. -static PmError resize_sysex_buffer(PmInternal *midi, long old_size, long new_size) -{ - LPMIDIHDR big; - int i; - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - /* buffer must be smaller than 64k, but be also a multiple of 4 */ - if (new_size > 65520) { - if (old_size >= 65520) - return pmBufferMaxSize; - else - new_size = 65520; - } - /* allocate a bigger message */ - big = allocate_sysex_buffer(new_size); - /* printf("expand to %d bytes\n", new_size);*/ - if (!big) return pmInsufficientMemory; - m->error = midiOutPrepareHeader(m->handle.out, big, sizeof(MIDIHDR)); - if (m->error) { - pm_free(big); - return pmHostError; - } - /* make sure we're not going to overwrite any memory */ - assert(old_size <= new_size); - memcpy(big->lpData, m->hdr->lpData, old_size); - /* keep track of how many sysex bytes are in message so far */ - big->dwBytesRecorded = m->hdr->dwBytesRecorded; - big->dwBufferLength = new_size; - /* find which buffer this was, and replace it */ - for (i = 0; i < NUM_SYSEX_BUFFERS; i++) { - if (m->sysex_buffers[i] == m->hdr) { - m->sysex_buffers[i] = big; - m->sysex_buffer_size[i] = new_size; - pm_free(m->hdr); - m->hdr = big; - break; - } - } - assert(i != NUM_SYSEX_BUFFERS); - - return pmNoError; -} -#endif - /* -========================================================================================= +============================================================================ begin midi input implementation -========================================================================================= +============================================================================ */ -static PmError allocate_input_buffer(HMIDIIN h, long buffer_len) +static unsigned int allocate_input_buffer(HMIDIIN h, long buffer_len) { LPMIDIHDR hdr = allocate_buffer(buffer_len); if (!hdr) return pmInsufficientMemory; + /* note: pm_hosterror is normally a boolean, but here, we store Win + * error code. The caller must test the value for nonzero, set + * pm_hosterror_text, and then set pm_hosterror to TRUE */ pm_hosterror = midiInPrepareHeader(h, hdr, sizeof(MIDIHDR)); if (pm_hosterror) { pm_free(hdr); @@ -560,49 +400,51 @@ static PmError allocate_input_buffer(HMIDIIN h, long buffer_len) } +static winmm_info_type winmm_info_create(void) +{ + winmm_info_type info = (winmm_info_type) pm_alloc(sizeof(winmm_info_node)); + info->handle.in = NULL; + info->handle.out = NULL; + info->buffers = NULL; /* not used for input */ + info->num_buffers = 0; /* not used for input */ + info->max_buffers = 0; /* not used for input */ + info->buffers_expanded = FALSE; /* not used for input */ + info->next_buffer = 0; /* not used for input */ + info->buffer_signal = 0; /* not used for input */ + info->last_time = 0; + info->first_message = TRUE; /* not used for input */ + info->sysex_mode = FALSE; + info->sysex_word = 0; + info->sysex_byte_count = 0; + info->hdr = NULL; /* not used for input */ + info->sync_time = 0; + info->delta = 0; + return info; +} + + static PmError winmm_in_open(PmInternal *midi, void *driverInfo) { DWORD dwDevice; int i = midi->device_id; int max_sysex_len = midi->buffer_len * 4; int num_input_buffers = max_sysex_len / INPUT_SYSEX_LEN; - midiwinmm_type m; + winmm_info_type info; - dwDevice = (DWORD)(FPTR)descriptors[i].descriptor; + dwDevice = (DWORD) (intptr_t) pm_descriptors[i].descriptor; /* create system dependent device data */ - m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */ - midi->descriptor = m; - if (!m) goto no_memory; - m->handle.in = NULL; - m->buffers = NULL; /* not used for input */ - m->num_buffers = 0; /* not used for input */ - m->max_buffers = FALSE; /* not used for input */ - m->buffers_expanded = 0; /* not used for input */ - m->next_buffer = 0; /* not used for input */ - m->buffer_signal = 0; /* not used for input */ -#ifdef USE_SYSEX_BUFFERS - for (i = 0; i < NUM_SYSEX_BUFFERS; i++) - m->sysex_buffers[i] = NULL; /* not used for input */ - m->next_sysex_buffer = 0; /* not used for input */ -#endif - m->last_time = 0; - m->first_message = TRUE; /* not used for input */ - m->sysex_mode = FALSE; - m->sysex_word = 0; - m->sysex_byte_count = 0; - m->hdr = NULL; /* not used for input */ - m->sync_time = 0; - m->delta = 0; - m->error = MMSYSERR_NOERROR; - /* 4000 is based on Windows documentation -- that's the value used in the - memory manager. It's small enough that it should not hurt performance even - if it's not optimal. + info = winmm_info_create(); + midi->api_info = info; + if (!info) goto no_memory; + /* 4000 is based on Windows documentation -- that's the value used + in the memory manager. It's small enough that it should not + hurt performance even if it's not optimal. */ - InitializeCriticalSectionAndSpinCount(&m->lock, 4000); + InitializeCriticalSectionAndSpinCount(&info->lock, 4000); /* open device */ pm_hosterror = midiInOpen( - &(m->handle.in), /* input device handle */ + &(info->handle.in), /* input device handle */ dwDevice, /* device ID */ (DWORD_PTR) winmm_in_callback, /* callback address */ (DWORD_PTR) midi, /* callback instance data */ @@ -612,31 +454,34 @@ static PmError winmm_in_open(PmInternal *midi, void *driverInfo) if (num_input_buffers < MIN_INPUT_BUFFERS) num_input_buffers = MIN_INPUT_BUFFERS; for (i = 0; i < num_input_buffers; i++) { - if (allocate_input_buffer(m->handle.in, INPUT_SYSEX_LEN)) { + if (allocate_input_buffer(info->handle.in, INPUT_SYSEX_LEN)) { /* either pm_hosterror was set, or the proper return code is pmInsufficientMemory */ goto close_device; } } /* start device */ - pm_hosterror = midiInStart(m->handle.in); - if (pm_hosterror) goto reset_device; - return pmNoError; + pm_hosterror = midiInStart(info->handle.in); + if (!pm_hosterror) { + return pmNoError; + } /* undo steps leading up to the detected error */ -reset_device: + /* ignore return code (we already have an error to report) */ - midiInReset(m->handle.in); + midiInReset(info->handle.in); close_device: - midiInClose(m->handle.in); /* ignore return code */ + midiInClose(info->handle.in); /* ignore return code */ free_descriptor: - midi->descriptor = NULL; - pm_free(m); + midi->api_info = NULL; + pm_free(info); no_memory: if (pm_hosterror) { - midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, + int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); - //assert(err == MMSYSERR_NOERROR); + assert(err == MMSYSERR_NOERROR); + improve_winerr(pm_hosterror, (char *) pm_hosterror_text); + pm_hosterror = TRUE; return pmHostError; } /* if !pm_hosterror, then the error must be pmInsufficientMemory */ @@ -646,12 +491,6 @@ no_memory: to free the parameter midi */ } -static PmError winmm_in_poll(PmInternal *midi) { - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - return m->error; -} - - /* winmm_in_close -- close an open midi input device */ /* @@ -659,24 +498,24 @@ static PmError winmm_in_poll(PmInternal *midi) { */ static PmError winmm_in_close(PmInternal *midi) { - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - if (!m) return pmBadPtr; + winmm_info_type info = (winmm_info_type) midi->api_info; + if (!info) return pmBadPtr; /* device to close */ - if ((pm_hosterror = midiInStop(m->handle.in))) { - midiInReset(m->handle.in); /* try to reset and close port */ - midiInClose(m->handle.in); - } else if ((pm_hosterror = midiInReset(m->handle.in))) { - midiInClose(m->handle.in); /* best effort to close midi port */ + if ((pm_hosterror = midiInStop(info->handle.in))) { + midiInReset(info->handle.in); /* try to reset and close port */ + midiInClose(info->handle.in); + } else if ((pm_hosterror = midiInReset(info->handle.in))) { + midiInClose(info->handle.in); /* best effort to close midi port */ } else { - pm_hosterror = midiInClose(m->handle.in); + pm_hosterror = midiInClose(info->handle.in); } - midi->descriptor = NULL; - DeleteCriticalSection(&m->lock); - pm_free(m); /* delete */ + midi->api_info = NULL; + DeleteCriticalSection(&info->lock); + pm_free(info); /* delete */ if (pm_hosterror) { - midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, + int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); - //assert(err == MMSYSERR_NOERROR); + assert(err == MMSYSERR_NOERROR); return pmHostError; } return pmNoError; @@ -685,19 +524,19 @@ static PmError winmm_in_close(PmInternal *midi) /* Callback function executed via midiInput SW interrupt (via midiInOpen). */ static void FAR PASCAL winmm_in_callback( - HMIDIIN hMidiIn, /* midiInput device Handle */ - WORD wMsg, /* midi msg */ - DWORD dwInstance, /* application data */ - DWORD dwParam1, /* MIDI data */ - DWORD dwParam2) /* device timestamp (wrt most recent midiInStart) */ + HMIDIIN hMidiIn, /* midiInput device Handle */ + UINT wMsg, /* midi msg */ + DWORD_PTR dwInstance, /* application data */ + DWORD_PTR dwParam1, /* MIDI data */ + DWORD_PTR dwParam2) /* device timestamp (wrt most recent midiInStart) */ { - //static int entry = 0; - PmInternal *midi = (PmInternal *)(FPTR) dwInstance; - midiwinmm_type m = (midiwinmm_type) midi->descriptor; + static int entry = 0; + PmInternal *midi = (PmInternal *) dwInstance; + winmm_info_type info = (winmm_info_type) midi->api_info; /* NOTE: we do not just EnterCriticalSection() here because an * MIM_CLOSE message arrives when the port is closed, but then - * the m->lock has been destroyed. + * the info->lock has been destroyed. */ switch (wMsg) { @@ -708,8 +547,7 @@ static void FAR PASCAL winmm_in_callback( * hardware interrupt? -- but I've seen reentrant behavior * using a debugger, so it happens. */ - //long new_driver_time; - EnterCriticalSection(&m->lock); + EnterCriticalSection(&info->lock); /* dwParam1 is MIDI data received, packed into DWORD w/ 1st byte of message LOB; @@ -717,8 +555,6 @@ static void FAR PASCAL winmm_in_callback( in [ms] from when midiInStart called. each message is expanded to include the status byte */ - //new_driver_time = dwParam2; - if ((dwParam1 & 0x80) == 0) { /* not a status byte -- ignore it. This happened running the sysex.c test under Win2K with MidiMan USB 1x1 interface, @@ -729,20 +565,20 @@ static void FAR PASCAL winmm_in_callback( PmEvent event; if (midi->time_proc) dwParam2 = (*midi->time_proc)(midi->time_info); - event.timestamp = dwParam2; - event.message = dwParam1; + event.timestamp = (PmTimestamp)dwParam2; + event.message = (PmMessage)dwParam1; pm_read_short(midi, &event); } - LeaveCriticalSection(&m->lock); + LeaveCriticalSection(&info->lock); break; } case MIM_LONGDATA: { - MIDIHDR *lpMidiHdr = (MIDIHDR *)(FPTR)dwParam1; + MIDIHDR *lpMidiHdr = (MIDIHDR *) dwParam1; unsigned char *data = (unsigned char *) lpMidiHdr->lpData; unsigned int processed = 0; int remaining = lpMidiHdr->dwBytesRecorded; - EnterCriticalSection(&m->lock); + EnterCriticalSection(&info->lock); /* printf("midi_in_callback -- lpMidiHdr %x, %d bytes, %2x...\n", lpMidiHdr, lpMidiHdr->dwBytesRecorded, *data); */ if (midi->time_proc) @@ -751,7 +587,7 @@ static void FAR PASCAL winmm_in_callback( /* assume yes and iterate through them */ while (remaining > 0) { unsigned int amt = pm_read_bytes(midi, data + processed, - remaining, dwParam2); + remaining, (PmTimestamp)dwParam2); remaining -= amt; processed += amt; } @@ -761,24 +597,24 @@ static void FAR PASCAL winmm_in_callback( case, we do not want to send them back to the interface (if we do, the interface will not close, and Windows OS may hang). */ if (lpMidiHdr->dwBytesRecorded > 0) { - //MMRESULT rslt; + MMRESULT rslt; lpMidiHdr->dwBytesRecorded = 0; lpMidiHdr->dwFlags = 0; /* note: no error checking -- can this actually fail? */ - midiInPrepareHeader(hMidiIn, lpMidiHdr, sizeof(MIDIHDR)); - //assert(rslt == MMSYSERR_NOERROR); + rslt = midiInPrepareHeader(hMidiIn, lpMidiHdr, sizeof(MIDIHDR)); + assert(rslt == MMSYSERR_NOERROR); /* note: I don't think this can fail except possibly for * MMSYSERR_NOMEM, but the pain of reporting this * unlikely but probably catastrophic error does not seem * worth it. */ - midiInAddBuffer(hMidiIn, lpMidiHdr, sizeof(MIDIHDR)); - //assert(rslt == MMSYSERR_NOERROR); - LeaveCriticalSection(&m->lock); + rslt = midiInAddBuffer(hMidiIn, lpMidiHdr, sizeof(MIDIHDR)); + assert(rslt == MMSYSERR_NOERROR); + LeaveCriticalSection(&info->lock); } else { midiInUnprepareHeader(hMidiIn,lpMidiHdr,sizeof(MIDIHDR)); - LeaveCriticalSection(&m->lock); + LeaveCriticalSection(&info->lock); pm_free(lpMidiHdr); } break; @@ -799,15 +635,15 @@ static void FAR PASCAL winmm_in_callback( } /* -========================================================================================= +=========================================================================== begin midi output implementation -========================================================================================= +=========================================================================== */ /* begin helper routines used by midiOutStream interface */ /* add_to_buffer -- adds timestamped short msg to buffer, returns fullp */ -static int add_to_buffer(midiwinmm_type m, LPMIDIHDR hdr, +static int add_to_buffer(winmm_info_type m, LPMIDIHDR hdr, unsigned long delta, unsigned long msg) { unsigned long *ptr = (unsigned long *) @@ -823,14 +659,14 @@ static int add_to_buffer(midiwinmm_type m, LPMIDIHDR hdr, } -static PmTimestamp pm_time_get(midiwinmm_type m) +static PmTimestamp pm_time_get(winmm_info_type info) { MMTIME mmtime; - //MMRESULT wRtn; + MMRESULT wRtn; mmtime.wType = TIME_TICKS; mmtime.u.ticks = 0; - midiStreamPosition(m->handle.stream, &mmtime, sizeof(mmtime)); - //assert(wRtn == MMSYSERR_NOERROR); + wRtn = midiStreamPosition(info->handle.stream, &mmtime, sizeof(mmtime)); + assert(wRtn == MMSYSERR_NOERROR); return mmtime.u.ticks; } @@ -842,49 +678,27 @@ static PmError winmm_out_open(PmInternal *midi, void *driverInfo) { DWORD dwDevice; int i = midi->device_id; - midiwinmm_type m; + winmm_info_type info; MIDIPROPTEMPO propdata; MIDIPROPTIMEDIV divdata; int max_sysex_len = midi->buffer_len * 4; int output_buffer_len; int num_buffers; - dwDevice = (DWORD)(FPTR) descriptors[i].descriptor; - /* create system dependent device data */ - m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */ - midi->descriptor = m; - if (!m) goto no_memory; - m->handle.out = NULL; - m->buffers = NULL; - m->num_buffers = 0; - m->max_buffers = 0; - m->buffers_expanded = FALSE; - m->next_buffer = 0; -#ifdef USE_SYSEX_BUFFERS - m->sysex_buffers[0] = NULL; - m->sysex_buffers[1] = NULL; - m->next_sysex_buffer = 0; -#endif - m->last_time = 0; - m->first_message = TRUE; /* we treat first message as special case */ - m->sysex_mode = FALSE; - m->sysex_word = 0; - m->sysex_byte_count = 0; - m->hdr = NULL; - m->sync_time = 0; - m->delta = 0; - m->error = MMSYSERR_NOERROR; + dwDevice = (DWORD) (intptr_t) pm_descriptors[i].descriptor; + /* create system dependent device data */ + info = winmm_info_create(); + midi->api_info = info; + if (!info) goto no_memory; /* create a signal */ - m->buffer_signal = CreateEvent(NULL, FALSE, FALSE, NULL); - + info->buffer_signal = CreateEvent(NULL, FALSE, FALSE, NULL); /* this should only fail when there are very serious problems */ - assert(m->buffer_signal); - + assert(info->buffer_signal); /* open device */ if (midi->latency == 0) { /* use simple midi out calls */ pm_hosterror = midiOutOpen( - (LPHMIDIOUT) & m->handle.out, /* device Handle */ + (LPHMIDIOUT) & info->handle.out, /* device Handle */ dwDevice, /* device ID */ /* note: same callback fn as for StreamOpen: */ (DWORD_PTR) winmm_streamout_callback, /* callback fn */ @@ -893,7 +707,7 @@ static PmError winmm_out_open(PmInternal *midi, void *driverInfo) } else { /* use stream-based midi output (schedulable in future) */ pm_hosterror = midiStreamOpen( - &m->handle.stream, /* device Handle */ + &info->handle.stream, /* device Handle */ (LPUINT) & dwDevice, /* device ID pointer */ 1, /* reserved, must be 1 */ (DWORD_PTR) winmm_streamout_callback, @@ -910,41 +724,32 @@ static PmError winmm_out_open(PmInternal *midi, void *driverInfo) if (output_buffer_len < MIN_SIMPLE_SYSEX_LEN) output_buffer_len = MIN_SIMPLE_SYSEX_LEN; } else { - //long dur = 0; - //num_buffers = (int)(double)max((double)midi->buffer_len, (double)midi->latency / 2); - if (midi->buffer_len > (midi->latency / 2)) - { - num_buffers = midi->buffer_len; - } - else - { - num_buffers = (midi->latency / 2); - } - + long dur = 0; + num_buffers = max(midi->buffer_len, midi->latency / 2); if (num_buffers < MIN_STREAM_BUFFERS) num_buffers = MIN_STREAM_BUFFERS; output_buffer_len = STREAM_BUFFER_LEN; propdata.cbStruct = sizeof(MIDIPROPTEMPO); propdata.dwTempo = 480000; /* microseconds per quarter */ - pm_hosterror = midiStreamProperty(m->handle.stream, + pm_hosterror = midiStreamProperty(info->handle.stream, (LPBYTE) & propdata, MIDIPROP_SET | MIDIPROP_TEMPO); if (pm_hosterror) goto close_device; divdata.cbStruct = sizeof(MIDIPROPTEMPO); divdata.dwTimeDiv = 480; /* divisions per quarter */ - pm_hosterror = midiStreamProperty(m->handle.stream, + pm_hosterror = midiStreamProperty(info->handle.stream, (LPBYTE) & divdata, MIDIPROP_SET | MIDIPROP_TIMEDIV); if (pm_hosterror) goto close_device; } /* allocate buffers */ - if (allocate_buffers(m, output_buffer_len, num_buffers)) + if (allocate_buffers(info, output_buffer_len, num_buffers)) goto free_buffers; /* start device */ if (midi->latency != 0) { - pm_hosterror = midiStreamRestart(m->handle.stream); + pm_hosterror = midiStreamRestart(info->handle.stream); if (pm_hosterror != MMSYSERR_NOERROR) goto free_buffers; } return pmNoError; @@ -952,15 +757,16 @@ static PmError winmm_out_open(PmInternal *midi, void *driverInfo) free_buffers: /* buffers are freed below by winmm_out_delete */ close_device: - midiOutClose(m->handle.out); + midiOutClose(info->handle.out); free_descriptor: - midi->descriptor = NULL; + midi->api_info = NULL; winmm_out_delete(midi); /* frees buffers and m */ no_memory: if (pm_hosterror) { - midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text, + int err = midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); - //assert(err == MMSYSERR_NOERROR); + assert(err == MMSYSERR_NOERROR); + improve_winerr(pm_hosterror, (char *) pm_hosterror_text); return pmHostError; } return pmInsufficientMemory; @@ -973,50 +779,43 @@ static void winmm_out_delete(PmInternal *midi) { int i; /* delete system dependent device data */ - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - if (m) { - if (m->buffer_signal) { + winmm_info_type info = (winmm_info_type) midi->api_info; + if (info) { + if (info->buffer_signal) { /* don't report errors -- better not to stop cleanup */ - CloseHandle(m->buffer_signal); + CloseHandle(info->buffer_signal); } /* if using stream output, free buffers */ - for (i = 0; i < m->num_buffers; i++) { - if (m->buffers[i]) pm_free(m->buffers[i]); + for (i = 0; i < info->num_buffers; i++) { + if (info->buffers[i]) pm_free(info->buffers[i]); } - m->num_buffers = 0; - pm_free(m->buffers); - m->max_buffers = 0; -#ifdef USE_SYSEX_BUFFERS - /* free sysex buffers */ - for (i = 0; i < NUM_SYSEX_BUFFERS; i++) { - if (m->sysex_buffers[i]) pm_free(m->sysex_buffers[i]); - } -#endif + info->num_buffers = 0; + pm_free(info->buffers); + info->max_buffers = 0; } - midi->descriptor = NULL; - pm_free(m); /* delete */ + midi->api_info = NULL; + pm_free(info); /* delete */ } /* see comments for winmm_in_close */ static PmError winmm_out_close(PmInternal *midi) { - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - if (m->handle.out) { + winmm_info_type info = (winmm_info_type) midi->api_info; + if (info->handle.out) { /* device to close */ if (midi->latency == 0) { - pm_hosterror = midiOutClose(m->handle.out); + pm_hosterror = midiOutClose(info->handle.out); } else { - pm_hosterror = midiStreamClose(m->handle.stream); + pm_hosterror = midiStreamClose(info->handle.stream); } /* regardless of outcome, free memory */ winmm_out_delete(midi); } if (pm_hosterror) { - midiOutGetErrorText(pm_hosterror, - (char *) pm_hosterror_text, + int err = midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); - //assert(err == MMSYSERR_NOERROR); + assert(err == MMSYSERR_NOERROR); return pmHostError; } return pmNoError; @@ -1025,42 +824,53 @@ static PmError winmm_out_close(PmInternal *midi) static PmError winmm_out_abort(PmInternal *midi) { - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - m->error = MMSYSERR_NOERROR; + winmm_info_type info = (winmm_info_type) midi->api_info; /* only stop output streams */ if (midi->latency > 0) { - m->error = midiStreamStop(m->handle.stream); + pm_hosterror = midiStreamStop(info->handle.stream); + if (pm_hosterror) { + int err; + err = midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text, + PM_HOST_ERROR_MSG_LEN); + assert(err == MMSYSERR_NOERROR); + return pmHostError; + } } - return m->error ? pmHostError : pmNoError; + return pmNoError; } static PmError winmm_write_flush(PmInternal *midi, PmTimestamp timestamp) { - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - assert(m); - if (m->hdr) { - m->error = midiOutPrepareHeader(m->handle.out, m->hdr, - sizeof(MIDIHDR)); - if (m->error) { + winmm_info_type info = (winmm_info_type) midi->api_info; + assert(info); + if (info->hdr) { + pm_hosterror = midiOutPrepareHeader(info->handle.out, info->hdr, + sizeof(MIDIHDR)); + if (pm_hosterror) { /* do not send message */ } else if (midi->latency == 0) { /* As pointed out by Nigel Brown, 20Sep06, dwBytesRecorded * should be zero. This is set in get_free_sysex_buffer(). * The msg length goes in dwBufferLength in spite of what * Microsoft documentation says (or doesn't say). */ - m->hdr->dwBufferLength = m->hdr->dwBytesRecorded; - m->hdr->dwBytesRecorded = 0; - m->error = midiOutLongMsg(m->handle.out, m->hdr, sizeof(MIDIHDR)); + info->hdr->dwBufferLength = info->hdr->dwBytesRecorded; + info->hdr->dwBytesRecorded = 0; + pm_hosterror = midiOutLongMsg(info->handle.out, info->hdr, + sizeof(MIDIHDR)); } else { - m->error = midiStreamOut(m->handle.stream, m->hdr, - sizeof(MIDIHDR)); + pm_hosterror = midiStreamOut(info->handle.stream, info->hdr, + sizeof(MIDIHDR)); } midi->fill_base = NULL; - m->hdr = NULL; - if (m->error) { - m->hdr->dwFlags = 0; /* release the buffer */ + info->hdr = NULL; + if (pm_hosterror) { + int err; + info->hdr->dwFlags = 0; /* release the buffer */ + err = midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text, + PM_HOST_ERROR_MSG_LEN); + assert(err == MMSYSERR_NOERROR); return pmHostError; } } @@ -1068,98 +878,40 @@ static PmError winmm_write_flush(PmInternal *midi, PmTimestamp timestamp) } - -#ifdef GARBAGE -static PmError winmm_write_sysex_byte(PmInternal *midi, unsigned char byte) -{ - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - unsigned char *msg_buffer; - - /* at the beginning of sysex, m->hdr is NULL */ - if (!m->hdr) { /* allocate a buffer if none allocated yet */ - m->hdr = get_free_output_buffer(midi); - if (!m->hdr) return pmInsufficientMemory; - m->sysex_byte_count = 0; - } - /* figure out where to write byte */ - msg_buffer = (unsigned char *) (m->hdr->lpData); - assert(m->hdr->lpData == (char *) (m->hdr + 1)); - - /* check for overflow */ - if (m->sysex_byte_count >= m->hdr->dwBufferLength) { - /* allocate a bigger message -- double it every time */ - LPMIDIHDR big = allocate_buffer(m->sysex_byte_count * 2); - /* printf("expand to %d bytes\n", m->sysex_byte_count * 2); */ - if (!big) return pmInsufficientMemory; - m->error = midiOutPrepareHeader(m->handle.out, big, - sizeof(MIDIHDR)); - if (m->error) { - m->hdr = NULL; - return pmHostError; - } - memcpy(big->lpData, msg_buffer, m->sysex_byte_count); - msg_buffer = (unsigned char *) (big->lpData); - if (m->buffers[0] == m->hdr) { - m->buffers[0] = big; - pm_free(m->hdr); - /* printf("freed m->hdr\n"); */ - } else if (m->buffers[1] == m->hdr) { - m->buffers[1] = big; - pm_free(m->hdr); - /* printf("freed m->hdr\n"); */ - } - m->hdr = big; - } - - /* append byte to message */ - msg_buffer[m->sysex_byte_count++] = byte; - - /* see if we have a complete message */ - if (byte == MIDI_EOX) { - m->hdr->dwBytesRecorded = m->sysex_byte_count; - /* - { int i; int len = m->hdr->dwBytesRecorded; - printf("OutLongMsg %d ", len); - for (i = 0; i < len; i++) { - printf("%2x ", msg_buffer[i]); - } - } - */ - m->error = midiOutLongMsg(m->handle.out, m->hdr, sizeof(MIDIHDR)); - m->hdr = NULL; /* stop using this message buffer */ - if (m->error) return pmHostError; - } - return pmNoError; -} -#endif - - static PmError winmm_write_short(PmInternal *midi, PmEvent *event) { - midiwinmm_type m = (midiwinmm_type) midi->descriptor; + winmm_info_type info = (winmm_info_type) midi->api_info; PmError rslt = pmNoError; - assert(m); + assert(info); if (midi->latency == 0) { /* use midiOut interface, ignore timestamps */ - m->error = midiOutShortMsg(m->handle.out, event->message); - if (m->error) rslt = pmHostError; + pm_hosterror = midiOutShortMsg(info->handle.out, event->message); + if (pm_hosterror) { + int err; + info->hdr->dwFlags = 0; /* release the buffer */ + err = midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text, + PM_HOST_ERROR_MSG_LEN); + assert(err == MMSYSERR_NOERROR); + return pmHostError; + } } else { /* use midiStream interface -- pass data through buffers */ unsigned long when = event->timestamp; unsigned long delta; int full; if (when == 0) when = midi->now; /* when is in real_time; translate to intended stream time */ - when = when + m->delta + midi->latency; + when = when + info->delta + midi->latency; /* make sure we don't go backward in time */ - if (when < m->last_time) when = m->last_time; - delta = when - m->last_time; - m->last_time = when; + if (when < info->last_time) when = info->last_time; + delta = when - info->last_time; + info->last_time = when; /* before we insert any data, we must have a buffer */ - if (m->hdr == NULL) { + if (info->hdr == NULL) { /* stream interface: buffers allocated when stream is opened */ - m->hdr = get_free_output_buffer(midi); + info->hdr = get_free_output_buffer(midi); } - full = add_to_buffer(m, m->hdr, delta, event->message); + full = add_to_buffer(info, info->hdr, delta, event->message); + /* note: winmm_write_flush sets pm_hosterror etc. on host error */ if (full) rslt = winmm_write_flush(midi, when); } return rslt; @@ -1169,7 +921,7 @@ static PmError winmm_write_short(PmInternal *midi, PmEvent *event) #ifndef winmm_begin_sysex static PmError winmm_begin_sysex(PmInternal *midi, PmTimestamp timestamp) { - midiwinmm_type m = (midiwinmm_type) midi->descriptor; + winmm_info_type m = (winmm_info_type) midi->api_info; PmError rslt = pmNoError; if (midi->latency == 0) { @@ -1188,9 +940,9 @@ static PmError winmm_end_sysex(PmInternal *midi, PmTimestamp timestamp) * what happens if we exit early and don't finish the sysex msg * and clean up */ - midiwinmm_type m = (midiwinmm_type) midi->descriptor; + winmm_info_type info = (winmm_info_type) midi->api_info; PmError rslt = pmNoError; - LPMIDIHDR hdr = m->hdr; + LPMIDIHDR hdr = info->hdr; if (!hdr) return rslt; /* something bad happened earlier, do not report an error because it would have been reported (at least) once already */ @@ -1200,15 +952,15 @@ static PmError winmm_end_sysex(PmInternal *midi, PmTimestamp timestamp) if (midi->latency == 0) { #ifdef DEBUG_PRINT_BEFORE_SENDING_SYSEX /* DEBUG CODE: */ - { int i; int len = m->hdr->dwBufferLength; + { int i; int len = info->hdr->dwBufferLength; printf("OutLongMsg %d ", len); for (i = 0; i < len; i++) { - printf("%2x ", (unsigned char) (m->hdr->lpData[i])); + printf("%2x ", (unsigned char) (info->hdr->lpData[i])); } } #endif } else { - /* Using stream interface. There are accumulated bytes in m->hdr + /* Using stream interface. There are accumulated bytes in info->hdr to send using midiStreamOut */ /* add bytes recorded to MIDIEVENT length, but don't @@ -1228,16 +980,15 @@ static PmError winmm_write_byte(PmInternal *midi, unsigned char byte, { /* write a sysex byte */ PmError rslt = pmNoError; - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - LPMIDIHDR hdr = m->hdr; + winmm_info_type info = (winmm_info_type) midi->api_info; + LPMIDIHDR hdr = info->hdr; unsigned char *msg_buffer; - assert(m); + assert(info); if (!hdr) { - m->hdr = hdr = get_free_output_buffer(midi); + info->hdr = hdr = get_free_output_buffer(midi); assert(hdr); - midi->fill_base = (unsigned char *)(FPTR) m->hdr->lpData; - midi->fill_offset_ptr = (uint32_t *)&(hdr->dwBytesRecorded); - + midi->fill_base = (unsigned char *) info->hdr->lpData; + midi->fill_offset_ptr = (uint32_t *) &(hdr->dwBytesRecorded); /* when buffer fills, Pm_WriteSysEx will revert to calling * pmwin_write_byte, which expect to have space, so leave * one byte free for pmwin_write_byte. Leave another byte @@ -1250,11 +1001,11 @@ static PmError winmm_write_byte(PmInternal *midi, unsigned char byte, unsigned long *ptr; if (when == 0) when = midi->now; /* when is in real_time; translate to intended stream time */ - when = when + m->delta + midi->latency; + when = when + info->delta + midi->latency; /* make sure we don't go backward in time */ - if (when < m->last_time) when = m->last_time; - delta = when - m->last_time; - m->last_time = when; + if (when < info->last_time) when = info->last_time; + delta = when - info->last_time; + info->last_time = when; ptr = (unsigned long *) hdr->lpData; *ptr++ = delta; @@ -1276,31 +1027,10 @@ static PmError winmm_write_byte(PmInternal *midi, unsigned char byte, return rslt; } -#ifdef EXPANDING_SYSEX_BUFFERS -note: this code is here as an aid in case you want sysex buffers - to expand to hold large messages completely. If so, you - will want to change SYSEX_BYTES_PER_BUFFER above to some - variable that remembers the buffer size. A good place to - put this value would be in the hdr->dwUser field. - - rslt = resize_sysex_buffer(midi, m->sysex_byte_count, - m->sysex_byte_count * 2); - - if (rslt == pmBufferMaxSize) /* if the buffer can't be resized */ -#endif -#ifdef EXPANDING_SYSEX_BUFFERS - int bytesRecorded = hdr->dwBytesRecorded; /* this field gets wiped out, so we'll save it */ - rslt = resize_sysex_buffer(midi, bytesRecorded, 2 * bytesRecorded); - hdr->dwBytesRecorded = bytesRecorded; - - if (rslt == pmBufferMaxSize) /* if buffer can't be resized */ -#endif - - static PmTimestamp winmm_synchronize(PmInternal *midi) { - midiwinmm_type m; + winmm_info_type info; unsigned long pm_stream_time_2; unsigned long real_time; unsigned long pm_stream_time; @@ -1309,60 +1039,30 @@ static PmTimestamp winmm_synchronize(PmInternal *midi) if (midi->latency == 0) return 0; /* figure out the time */ - m = (midiwinmm_type) midi->descriptor; - pm_stream_time_2 = pm_time_get(m); + info = (winmm_info_type) midi->api_info; + pm_stream_time_2 = pm_time_get(info); do { /* read real_time between two reads of stream time */ pm_stream_time = pm_stream_time_2; real_time = (*midi->time_proc)(midi->time_info); - pm_stream_time_2 = pm_time_get(m); + pm_stream_time_2 = pm_time_get(info); /* repeat if more than 1ms elapsed */ } while (pm_stream_time_2 > pm_stream_time + 1); - m->delta = pm_stream_time - real_time; - m->sync_time = real_time; + info->delta = pm_stream_time - real_time; + info->sync_time = real_time; return real_time; } -#ifdef USE_SYSEX_BUFFERS -/* winmm_out_callback -- recycle sysex buffers */ -static void CALLBACK winmm_out_callback(HMIDIOUT hmo, UINT wMsg, - DWORD dwInstance, DWORD dwParam1, - DWORD dwParam2) -{ - PmInternal *midi = (PmInternal *) dwInstance; - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - LPMIDIHDR hdr = (LPMIDIHDR) dwParam1; - int err = 0; /* set to 0 so that no buffer match will also be an error */ - - /* Future optimization: eliminate UnprepareHeader calls -- they aren't - necessary; however, this code uses the prepared-flag to indicate which - buffers are free, so we need to do something to flag empty buffers if - we leave them prepared - */ - /* - printf("out_callback: hdr %x, wMsg %x, MOM_DONE %x\n", - hdr, wMsg, MOM_DONE); - */ - if (wMsg == MOM_DONE) { - MMRESULT ret = midiOutUnprepareHeader(m->handle.out, hdr, - sizeof(MIDIHDR)); - assert(ret == MMSYSERR_NOERROR); - } - /* notify waiting sender that a buffer is available */ - err = SetEvent(m->buffer_signal); - assert(err); /* false -> error */ -} -#endif /* winmm_streamout_callback -- unprepare (free) buffer header */ static void CALLBACK winmm_streamout_callback(HMIDIOUT hmo, UINT wMsg, - DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) + DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { - PmInternal *midi = (PmInternal *)(FPTR) dwInstance; - LPMIDIHDR hdr = (LPMIDIHDR)(FPTR) dwParam1; - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - //int err; + PmInternal *midi = (PmInternal *) dwInstance; + winmm_info_type info = (winmm_info_type) midi->api_info; + LPMIDIHDR hdr = (LPMIDIHDR) dwParam1; + int err; /* Even if an error is pending, I think we should unprepare msgs and signal their arrival @@ -1370,20 +1070,20 @@ static void CALLBACK winmm_streamout_callback(HMIDIOUT hmo, UINT wMsg, /* printf("streamout_callback: hdr %x, wMsg %x, MOM_DONE %x\n", hdr, wMsg, MOM_DONE); */ if (wMsg == MOM_DONE) { - midiOutUnprepareHeader(m->handle.out, hdr, + MMRESULT ret = midiOutUnprepareHeader(info->handle.out, hdr, sizeof(MIDIHDR)); - //assert(ret == MMSYSERR_NOERROR); + assert(ret == MMSYSERR_NOERROR); } /* signal client in case it is blocked waiting for buffer */ - SetEvent(m->buffer_signal); - //assert(err); /* false -> error */ + err = SetEvent(info->buffer_signal); + assert(err); /* false -> error */ } /* -========================================================================================= +=========================================================================== begin exported functions -========================================================================================= +=========================================================================== */ #define winmm_in_abort pm_fail_fn @@ -1398,9 +1098,8 @@ pm_fns_node pm_winmm_in_dictionary = { winmm_in_open, winmm_in_abort, winmm_in_close, - winmm_in_poll, - winmm_has_host_error, - winmm_get_host_error + success_poll, + winmm_check_host_error }; pm_fns_node pm_winmm_out_dictionary = { @@ -1408,15 +1107,14 @@ pm_fns_node pm_winmm_out_dictionary = { winmm_begin_sysex, winmm_end_sysex, winmm_write_byte, - winmm_write_short, /* short realtime message */ + /* short realtime message: */ winmm_write_short, winmm_write_flush, winmm_synchronize, winmm_out_open, winmm_out_abort, winmm_out_close, none_poll, - winmm_has_host_error, - winmm_get_host_error + winmm_check_host_error }; @@ -1445,28 +1143,21 @@ void pm_winmm_init( void ) void pm_winmm_term( void ) { int i; -#ifdef DEBUG - char msg[PM_HOST_ERROR_MSG_LEN]; +#ifdef MMDEBUG int doneAny = 0; printf("pm_winmm_term called\n"); #endif - for (i = 0; i < pm_descriptor_index; i++) { - PmInternal * midi = descriptors[i].internalDescriptor; + for (i = 0; i < pm_descriptor_len; i++) { + PmInternal *midi = pm_descriptors[i].pm_internal; if (midi) { - midiwinmm_type m = (midiwinmm_type) midi->descriptor; - if (m->handle.out) { + winmm_info_type info = (winmm_info_type) midi->api_info; + if (info->handle.out) { /* close next open device*/ -#ifdef DEBUG +#ifdef MMDEBUG if (doneAny == 0) { printf("begin closing open devices...\n"); doneAny = 1; } - /* report any host errors; this EXTEREMELY useful when - trying to debug client app */ - if (winmm_has_host_error(midi)) { - winmm_get_host_error(midi, msg, PM_HOST_ERROR_MSG_LEN); - printf("%s\n", msg); - } #endif /* close all open ports */ (*midi->dictionary->close)(midi); @@ -1481,11 +1172,11 @@ void pm_winmm_term( void ) pm_free(midi_out_caps); midi_out_caps = NULL; } -#ifdef DEBUG +#ifdef MMDEBUG if (doneAny) { printf("warning: devices were left open. They have been closed.\n"); } printf("pm_winmm_term exiting\n"); #endif - pm_descriptor_index = 0; + pm_descriptor_len = 0; } diff --git a/3rdparty/portmidi/pm_win/pmwinmm.h b/3rdparty/portmidi/pm_win/pmwinmm.h index 94742001bcd..a429ca1afb9 100644 --- a/3rdparty/portmidi/pm_win/pmwinmm.h +++ b/3rdparty/portmidi/pm_win/pmwinmm.h @@ -1,4 +1,4 @@ -/* midiwin32.h -- system-specific definitions */ +/* pmwinmm.h -- system-specific definitions for windows multimedia API */ void pm_winmm_init( void ); void pm_winmm_term( void ); diff --git a/3rdparty/portmidi/pm_win/static.cmake b/3rdparty/portmidi/pm_win/static.cmake index ebad662aeb4..88a115c9228 100644 --- a/3rdparty/portmidi/pm_win/static.cmake +++ b/3rdparty/portmidi/pm_win/static.cmake @@ -1,4 +1,12 @@ # static.cmake -- change flags to link with static runtime libraries +# +# Even when BUILD_SHARED_LIBS is OFF, CMake specifies linking wtih +# multithread DLL, so you give inconsistent linking instructions +# resulting in warning messages from MS Visual Studio. If you want +# a static binary, I've found this approach works to eliminate +# warnings and make everything static: +# +# Changes /MD (multithread DLL) to /MT (multithread static) if(MSVC) foreach(flag_var diff --git a/3rdparty/portmidi/portmidi.sln b/3rdparty/portmidi/portmidi.sln deleted file mode 100644 index e5521924d12..00000000000 --- a/3rdparty/portmidi/portmidi.sln +++ /dev/null @@ -1,147 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", ".\ALL_BUILD.vcproj", "{E1C2664B-91BB-4D4F-868C-433164F81101}" - ProjectSection(ProjectDependencies) = postProject - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - {41D78CBF-B04B-4561-BA4A-AC238C40633D} = {41D78CBF-B04B-4561-BA4A-AC238C40633D} - {9B448D22-EC7E-4BD8-A552-B268D843CC3C} = {9B448D22-EC7E-4BD8-A552-B268D843CC3C} - {EED7440D-04E3-4948-92DB-C85B4ADB1D82} = {EED7440D-04E3-4948-92DB-C85B4ADB1D82} - {80193DD1-2C02-4A4C-BDF8-49623AD6F556} = {80193DD1-2C02-4A4C-BDF8-49623AD6F556} - {EAADABB5-83D6-4669-98F8-6CDBE6AFD2BF} = {EAADABB5-83D6-4669-98F8-6CDBE6AFD2BF} - {87B548BD-F5CE-4D1F-9181-390966AC5855} = {87B548BD-F5CE-4D1F-9181-390966AC5855} - {7283FAD1-7415-4061-A19A-FF5C7BCE9306} = {7283FAD1-7415-4061-A19A-FF5C7BCE9306} - {2985D5DA-D91E-44E0-924B-E612B6AA33F6} = {2985D5DA-D91E-44E0-924B-E612B6AA33F6} - {2204E68C-5C1F-440E-8CE6-7E273D4F6AD1} = {2204E68C-5C1F-440E-8CE6-7E273D4F6AD1} - {71B9BC6E-7B40-4FBC-BC7F-4372AF03D0FD} = {71B9BC6E-7B40-4FBC-BC7F-4372AF03D0FD} - {0BEACB8B-4058-41A4-A9DE-1B1FB650B21A} = {0BEACB8B-4058-41A4-A9DE-1B1FB650B21A} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", ".\ZERO_CHECK.vcproj", "{28779535-7541-4FF5-AC12-FAFD66E894EC}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "latency", "pm_test\latency.vcproj", "{41D78CBF-B04B-4561-BA4A-AC238C40633D}" - ProjectSection(ProjectDependencies) = postProject - {2985D5DA-D91E-44E0-924B-E612B6AA33F6} = {2985D5DA-D91E-44E0-924B-E612B6AA33F6} - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "midiclock", "pm_test\midiclock.vcproj", "{9B448D22-EC7E-4BD8-A552-B268D843CC3C}" - ProjectSection(ProjectDependencies) = postProject - {2985D5DA-D91E-44E0-924B-E612B6AA33F6} = {2985D5DA-D91E-44E0-924B-E612B6AA33F6} - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "midithread", "pm_test\midithread.vcproj", "{EED7440D-04E3-4948-92DB-C85B4ADB1D82}" - ProjectSection(ProjectDependencies) = postProject - {2985D5DA-D91E-44E0-924B-E612B6AA33F6} = {2985D5DA-D91E-44E0-924B-E612B6AA33F6} - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "midithru", "pm_test\midithru.vcproj", "{80193DD1-2C02-4A4C-BDF8-49623AD6F556}" - ProjectSection(ProjectDependencies) = postProject - {2985D5DA-D91E-44E0-924B-E612B6AA33F6} = {2985D5DA-D91E-44E0-924B-E612B6AA33F6} - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mm", "pm_test\mm.vcproj", "{EAADABB5-83D6-4669-98F8-6CDBE6AFD2BF}" - ProjectSection(ProjectDependencies) = postProject - {2985D5DA-D91E-44E0-924B-E612B6AA33F6} = {2985D5DA-D91E-44E0-924B-E612B6AA33F6} - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pmjni", "pm_common\pmjni.vcproj", "{87B548BD-F5CE-4D1F-9181-390966AC5855}" - ProjectSection(ProjectDependencies) = postProject - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "portmidi-dynamic", "pm_dylib\portmidi-dynamic.vcproj", "{7283FAD1-7415-4061-A19A-FF5C7BCE9306}" - ProjectSection(ProjectDependencies) = postProject - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "portmidi-static", "pm_common\portmidi-static.vcproj", "{2985D5DA-D91E-44E0-924B-E612B6AA33F6}" - ProjectSection(ProjectDependencies) = postProject - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtest", "pm_test\qtest.vcproj", "{2204E68C-5C1F-440E-8CE6-7E273D4F6AD1}" - ProjectSection(ProjectDependencies) = postProject - {2985D5DA-D91E-44E0-924B-E612B6AA33F6} = {2985D5DA-D91E-44E0-924B-E612B6AA33F6} - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sysex", "pm_test\sysex.vcproj", "{71B9BC6E-7B40-4FBC-BC7F-4372AF03D0FD}" - ProjectSection(ProjectDependencies) = postProject - {2985D5DA-D91E-44E0-924B-E612B6AA33F6} = {2985D5DA-D91E-44E0-924B-E612B6AA33F6} - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "pm_test\test.vcproj", "{0BEACB8B-4058-41A4-A9DE-1B1FB650B21A}" - ProjectSection(ProjectDependencies) = postProject - {2985D5DA-D91E-44E0-924B-E612B6AA33F6} = {2985D5DA-D91E-44E0-924B-E612B6AA33F6} - {28779535-7541-4FF5-AC12-FAFD66E894EC} = {28779535-7541-4FF5-AC12-FAFD66E894EC} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E1C2664B-91BB-4D4F-868C-433164F81101}.Debug|Win32.ActiveCfg = Debug|Win32 - {E1C2664B-91BB-4D4F-868C-433164F81101}.Release|Win32.ActiveCfg = Release|Win32 - {28779535-7541-4FF5-AC12-FAFD66E894EC}.Debug|Win32.ActiveCfg = Debug|Win32 - {28779535-7541-4FF5-AC12-FAFD66E894EC}.Debug|Win32.Build.0 = Debug|Win32 - {28779535-7541-4FF5-AC12-FAFD66E894EC}.Release|Win32.ActiveCfg = Release|Win32 - {28779535-7541-4FF5-AC12-FAFD66E894EC}.Release|Win32.Build.0 = Release|Win32 - {41D78CBF-B04B-4561-BA4A-AC238C40633D}.Debug|Win32.ActiveCfg = Debug|Win32 - {41D78CBF-B04B-4561-BA4A-AC238C40633D}.Debug|Win32.Build.0 = Debug|Win32 - {41D78CBF-B04B-4561-BA4A-AC238C40633D}.Release|Win32.ActiveCfg = Release|Win32 - {41D78CBF-B04B-4561-BA4A-AC238C40633D}.Release|Win32.Build.0 = Release|Win32 - {9B448D22-EC7E-4BD8-A552-B268D843CC3C}.Debug|Win32.ActiveCfg = Debug|Win32 - {9B448D22-EC7E-4BD8-A552-B268D843CC3C}.Debug|Win32.Build.0 = Debug|Win32 - {9B448D22-EC7E-4BD8-A552-B268D843CC3C}.Release|Win32.ActiveCfg = Release|Win32 - {9B448D22-EC7E-4BD8-A552-B268D843CC3C}.Release|Win32.Build.0 = Release|Win32 - {EED7440D-04E3-4948-92DB-C85B4ADB1D82}.Debug|Win32.ActiveCfg = Debug|Win32 - {EED7440D-04E3-4948-92DB-C85B4ADB1D82}.Debug|Win32.Build.0 = Debug|Win32 - {EED7440D-04E3-4948-92DB-C85B4ADB1D82}.Release|Win32.ActiveCfg = Release|Win32 - {EED7440D-04E3-4948-92DB-C85B4ADB1D82}.Release|Win32.Build.0 = Release|Win32 - {80193DD1-2C02-4A4C-BDF8-49623AD6F556}.Debug|Win32.ActiveCfg = Debug|Win32 - {80193DD1-2C02-4A4C-BDF8-49623AD6F556}.Debug|Win32.Build.0 = Debug|Win32 - {80193DD1-2C02-4A4C-BDF8-49623AD6F556}.Release|Win32.ActiveCfg = Release|Win32 - {80193DD1-2C02-4A4C-BDF8-49623AD6F556}.Release|Win32.Build.0 = Release|Win32 - {EAADABB5-83D6-4669-98F8-6CDBE6AFD2BF}.Debug|Win32.ActiveCfg = Debug|Win32 - {EAADABB5-83D6-4669-98F8-6CDBE6AFD2BF}.Debug|Win32.Build.0 = Debug|Win32 - {EAADABB5-83D6-4669-98F8-6CDBE6AFD2BF}.Release|Win32.ActiveCfg = Release|Win32 - {EAADABB5-83D6-4669-98F8-6CDBE6AFD2BF}.Release|Win32.Build.0 = Release|Win32 - {87B548BD-F5CE-4D1F-9181-390966AC5855}.Debug|Win32.ActiveCfg = Debug|Win32 - {87B548BD-F5CE-4D1F-9181-390966AC5855}.Debug|Win32.Build.0 = Debug|Win32 - {87B548BD-F5CE-4D1F-9181-390966AC5855}.Release|Win32.ActiveCfg = Release|Win32 - {87B548BD-F5CE-4D1F-9181-390966AC5855}.Release|Win32.Build.0 = Release|Win32 - {7283FAD1-7415-4061-A19A-FF5C7BCE9306}.Debug|Win32.ActiveCfg = Debug|Win32 - {7283FAD1-7415-4061-A19A-FF5C7BCE9306}.Debug|Win32.Build.0 = Debug|Win32 - {7283FAD1-7415-4061-A19A-FF5C7BCE9306}.Release|Win32.ActiveCfg = Release|Win32 - {7283FAD1-7415-4061-A19A-FF5C7BCE9306}.Release|Win32.Build.0 = Release|Win32 - {2985D5DA-D91E-44E0-924B-E612B6AA33F6}.Debug|Win32.ActiveCfg = Debug|Win32 - {2985D5DA-D91E-44E0-924B-E612B6AA33F6}.Debug|Win32.Build.0 = Debug|Win32 - {2985D5DA-D91E-44E0-924B-E612B6AA33F6}.Release|Win32.ActiveCfg = Release|Win32 - {2985D5DA-D91E-44E0-924B-E612B6AA33F6}.Release|Win32.Build.0 = Release|Win32 - {2204E68C-5C1F-440E-8CE6-7E273D4F6AD1}.Debug|Win32.ActiveCfg = Debug|Win32 - {2204E68C-5C1F-440E-8CE6-7E273D4F6AD1}.Debug|Win32.Build.0 = Debug|Win32 - {2204E68C-5C1F-440E-8CE6-7E273D4F6AD1}.Release|Win32.ActiveCfg = Release|Win32 - {2204E68C-5C1F-440E-8CE6-7E273D4F6AD1}.Release|Win32.Build.0 = Release|Win32 - {71B9BC6E-7B40-4FBC-BC7F-4372AF03D0FD}.Debug|Win32.ActiveCfg = Debug|Win32 - {71B9BC6E-7B40-4FBC-BC7F-4372AF03D0FD}.Debug|Win32.Build.0 = Debug|Win32 - {71B9BC6E-7B40-4FBC-BC7F-4372AF03D0FD}.Release|Win32.ActiveCfg = Release|Win32 - {71B9BC6E-7B40-4FBC-BC7F-4372AF03D0FD}.Release|Win32.Build.0 = Release|Win32 - {0BEACB8B-4058-41A4-A9DE-1B1FB650B21A}.Debug|Win32.ActiveCfg = Debug|Win32 - {0BEACB8B-4058-41A4-A9DE-1B1FB650B21A}.Debug|Win32.Build.0 = Debug|Win32 - {0BEACB8B-4058-41A4-A9DE-1B1FB650B21A}.Release|Win32.ActiveCfg = Release|Win32 - {0BEACB8B-4058-41A4-A9DE-1B1FB650B21A}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/3rdparty/portmidi/portmidi_cdt.zip b/3rdparty/portmidi/portmidi_cdt.zip Binary files differdeleted file mode 100644 index eaa2d7970cb..00000000000 --- a/3rdparty/portmidi/portmidi_cdt.zip +++ /dev/null diff --git a/3rdparty/portmidi/porttime/porttime-VC8.vcproj b/3rdparty/portmidi/porttime/porttime-VC8.vcproj deleted file mode 100644 index 9a4562495b2..00000000000 --- a/3rdparty/portmidi/porttime/porttime-VC8.vcproj +++ /dev/null @@ -1,225 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="8.00" - Name="porttime" - ProjectGUID="{338224B8-D575-408D-BACF-95C557B429BE}" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Release|Win32" - OutputDirectory=".\Release" - IntermediateDirectory=".\Release" - ConfigurationType="4" - InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="false" - CharacterSet="2" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - InlineFunctionExpansion="1" - PreprocessorDefinitions="WIN32;NDEBUG;_LIB" - StringPooling="true" - RuntimeLibrary="0" - EnableFunctionLevelLinking="true" - PrecompiledHeaderFile=".\Release/porttime.pch" - AssemblerListingLocation=".\Release/" - ObjectFile=".\Release/" - ProgramDataBaseFileName=".\Release/" - WarningLevel="3" - SuppressStartupBanner="true" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="NDEBUG" - Culture="1033" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - OutputFile=".\Release\porttime.lib" - SuppressStartupBanner="true" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - SuppressStartupBanner="true" - OutputFile=".\Release/porttime.bsc" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Debug|Win32" - OutputDirectory=".\Debug" - IntermediateDirectory=".\Debug" - ConfigurationType="4" - InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="false" - CharacterSet="2" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - PreprocessorDefinitions="_LIB;WIN32;_DEBUG" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="1" - PrecompiledHeaderFile=".\Debug/porttime.pch" - AssemblerListingLocation=".\Debug/" - ObjectFile=".\Debug/" - ProgramDataBaseFileName=".\Debug/" - WarningLevel="3" - SuppressStartupBanner="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG" - Culture="1033" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - OutputFile=".\Debug\porttime.lib" - SuppressStartupBanner="true" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - SuppressStartupBanner="true" - OutputFile=".\Debug/porttime.bsc" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" - > - <File - RelativePath="porttime.c" - > - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - PreprocessorDefinitions="" - /> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCLCompilerTool" - PreprocessorDefinitions="" - /> - </FileConfiguration> - </File> - <File - RelativePath="ptwinmm.c" - > - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - PreprocessorDefinitions="" - /> - </FileConfiguration> - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCLCompilerTool" - PreprocessorDefinitions="" - /> - </FileConfiguration> - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl" - > - <File - RelativePath="porttime.h" - > - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/porttime/porttime.dsp b/3rdparty/portmidi/porttime/porttime.dsp deleted file mode 100644 index 2771842af31..00000000000 --- a/3rdparty/portmidi/porttime/porttime.dsp +++ /dev/null @@ -1,104 +0,0 @@ -# Microsoft Developer Studio Project File - Name="porttime" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=porttime - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "porttime.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "porttime.mak" CFG="porttime - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "porttime - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "porttime - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "porttime - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ELSEIF "$(CFG)" == "porttime - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_LIB" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "USE_DLL_FOR_CLEANUP" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ENDIF - -# Begin Target - -# Name "porttime - Win32 Release" -# Name "porttime - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\porttime.c -# End Source File -# Begin Source File - -SOURCE=.\ptwinmm.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\porttime.h -# End Source File -# End Group -# End Target -# End Project diff --git a/3rdparty/portmidi/porttime/porttime.h b/3rdparty/portmidi/porttime/porttime.h index f5ffd5c1f49..29d93dc2c59 100644 --- a/3rdparty/portmidi/porttime/porttime.h +++ b/3rdparty/portmidi/porttime/porttime.h @@ -1,4 +1,4 @@ -/* porttime.h -- portable interface to millisecond timer */ +/** @file porttime.h portable interface to millisecond timer. */ /* CHANGE LOG FOR PORTTIME 10-Jun-03 Mark Nelson & RBD @@ -25,8 +25,16 @@ extern "C" { #endif #ifndef PMEXPORT +#ifdef _WINDLL +#define PMEXPORT __declspec(dllexport) +#else #define PMEXPORT #endif +#endif + +/** @defgroup grp_porttime PortTime: Millisecond Timer + @{ +*/ typedef enum { ptNoError = 0, /* success */ @@ -34,55 +42,57 @@ typedef enum { ptAlreadyStarted, /* cannot start timer because it is already started */ ptAlreadyStopped, /* cannot stop timer because it is already stopped */ ptInsufficientMemory /* memory could not be allocated */ -} PtError; - +} PtError; /**< @brief @enum PtError PortTime error code; a common return type. + * No error is indicated by zero; errors are indicated by < 0. + */ +/** real time or time offset in milliseconds. */ typedef int32_t PtTimestamp; -typedef void (PtCallback)( PtTimestamp timestamp, void *userData ); +/** a function that gets a current time */ +typedef void (PtCallback)(PtTimestamp timestamp, void *userData); -/* - Pt_Start() starts a real-time service. +/** start a real-time clock service. - resolution is the timer resolution in ms. The time will advance every - resolution ms. + @param resolution the timer resolution in ms. The time will advance every + \p resolution ms. - callback is a function pointer to be called every resolution ms. + @param callback a function pointer to be called every resolution ms. - userData is passed to callback as a parameter. + @param userData is passed to \p callback as a parameter. - return value: - Upon success, returns ptNoError. See PtError for other values. + @return #ptNoError on success. See #PtError for other values. */ PMEXPORT PtError Pt_Start(int resolution, PtCallback *callback, void *userData); -/* - Pt_Stop() stops the timer. +/** stop the timer. - return value: - Upon success, returns ptNoError. See PtError for other values. + @return #ptNoError on success. See #PtError for other values. */ PMEXPORT PtError Pt_Stop(void); -/* - Pt_Started() returns true iff the timer is running. +/** test if the timer is running. + + @return TRUE or FALSE */ PMEXPORT int Pt_Started(void); -/* - Pt_Time() returns the current time in ms. +/** get the current time in ms. + + @return the current time */ PMEXPORT PtTimestamp Pt_Time(void); -/* - Pt_Sleep() pauses, allowing other threads to run. +/** pauses the current thread, allowing other threads to run. - duration is the length of the pause in ms. The true duration + @param duration the length of the pause in ms. The true duration of the pause may be rounded to the nearest or next clock tick - as determined by resolution in Pt_Start(). + as determined by resolution in #Pt_Start(). */ PMEXPORT void Pt_Sleep(int32_t duration); +/** @} */ + #ifdef __cplusplus } #endif diff --git a/3rdparty/portmidi/porttime/porttime.vcproj b/3rdparty/portmidi/porttime/porttime.vcproj deleted file mode 100644 index a386cce6257..00000000000 --- a/3rdparty/portmidi/porttime/porttime.vcproj +++ /dev/null @@ -1,184 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="PortTime" - ProjectGUID="{338224B8-D575-408D-BACF-95C557B429BE}" - TargetFrameworkVersion="131072" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Release|Win32" - OutputDirectory="$(ConfigurationName)" - IntermediateDirectory="$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="false" - CharacterSet="2" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - InlineFunctionExpansion="1" - PreprocessorDefinitions="WIN32;NDEBUG;_LIB" - StringPooling="true" - RuntimeLibrary="0" - EnableFunctionLevelLinking="true" - PrecompiledHeaderFile=".\$(OutDir)\porttime.pch" - AssemblerListingLocation=".\$(OutDir)\" - ObjectFile=".\$(OutDir)\" - ProgramDataBaseFileName=".\$(OutDir)\" - WarningLevel="3" - SuppressStartupBanner="true" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="NDEBUG" - Culture="1033" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - OutputFile=".\$(OutDir)\porttime.lib" - SuppressStartupBanner="true" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - SuppressStartupBanner="true" - OutputFile=".\$(OutDir)\porttime.bsc" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Debug|Win32" - OutputDirectory="$(ConfigurationName)" - IntermediateDirectory="$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="false" - CharacterSet="2" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - PreprocessorDefinitions="_LIB;WIN32;_DEBUG" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - PrecompiledHeaderFile=".\$(OutDir)\porttime.pch" - AssemblerListingLocation=".\$(OutDir)\" - ObjectFile=".\$(OutDir)\" - ProgramDataBaseFileName=".\$(OutDir)\" - WarningLevel="3" - SuppressStartupBanner="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG" - Culture="1033" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - OutputFile=".\$(OutDir)\porttime.lib" - SuppressStartupBanner="true" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - SuppressStartupBanner="true" - OutputFile=".\$(OutDir)\porttime.bsc" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <File - RelativePath=".\porttime.c" - > - </File> - <File - RelativePath=".\porttime.h" - > - </File> - <File - RelativePath=".\ptwinmm.c" - > - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/3rdparty/portmidi/porttime/pthaiku.cpp b/3rdparty/portmidi/porttime/pthaiku.cpp new file mode 100644 index 00000000000..9d8de14fd3d --- /dev/null +++ b/3rdparty/portmidi/porttime/pthaiku.cpp @@ -0,0 +1,88 @@ +// pthaiku.cpp - portable timer implementation for Haiku + +#include "porttime.h" +#include <Looper.h> +#include <MessageRunner.h> +#include <OS.h> + +namespace { + const uint32 timerMessage = 'PTTM'; + + struct TimerLooper : BLooper { + TimerLooper() : BLooper() { + } + + + virtual void MessageReceived(BMessage *message) + { + PtCallback *callback; + void *userData; + if (message->what == timerMessage && message->FindPointer("callback", (void**)&callback) == B_OK && message->FindPointer("userData", &userData) == B_OK) { + (*callback)(Pt_Time(), userData); + } + BLooper::MessageReceived(message); + } + }; + + bool time_started_flag = false; + bigtime_t time_offset; + TimerLooper *timerLooper; + BMessageRunner *timerRunner; +} + +extern "C" { + PtError Pt_Start(int resolution, PtCallback *callback, void *userData) + { + if (time_started_flag) return ptAlreadyStarted; + time_offset = system_time(); + if (callback) { + timerLooper = new TimerLooper; + timerLooper->Run(); + BMessenger target(timerLooper); + BMessage message(timerMessage); + message.AddPointer("callback", (void*)callback); + message.AddPointer("userData", userData); + bigtime_t interval = resolution * 1000; + timerRunner = new BMessageRunner(target, &message, interval); + if(timerRunner->InitCheck() != B_OK) { + delete timerRunner; + timerRunner = NULL; + timerLooper->PostMessage(B_QUIT_REQUESTED); + timerLooper = NULL; + return ptHostError; + } + } + time_started_flag = true; + return ptNoError; + } + + + PtError Pt_Stop() + { + if (!time_started_flag) return ptAlreadyStopped; + time_started_flag = false; + delete timerRunner; + timerRunner = NULL; + timerLooper->PostMessage(B_QUIT_REQUESTED); + timerLooper = NULL; + return ptNoError; + } + + + int Pt_Started() + { + return time_started_flag; + } + + + PtTimestamp Pt_Time() + { + return (system_time() - time_offset) / 1000; + } + + + void Pt_Sleep(int32_t duration) + { + snooze(duration * 1000); + } +} diff --git a/3rdparty/portmidi/porttime/ptlinux.c b/3rdparty/portmidi/porttime/ptlinux.c index c58107c36ad..7302e212311 100644 --- a/3rdparty/portmidi/porttime/ptlinux.c +++ b/3rdparty/portmidi/porttime/ptlinux.c @@ -29,7 +29,7 @@ CHANGE LOG #include <unistd.h> #include <sys/types.h> #include "porttime.h" -#include "sys/time.h" +#include "time.h" #include "sys/resource.h" #include "sys/timeb.h" #include "pthread.h" @@ -38,7 +38,7 @@ CHANGE LOG #define FALSE 0 static int time_started_flag = FALSE; -static struct timeval time_offset = {0, 0}; +static struct timespec time_offset = {0, 0}; static pthread_t pt_thread_pid; static int pt_thread_created = FALSE; @@ -79,7 +79,8 @@ static void *Pt_CallbackProc(void *p) PtError Pt_Start(int resolution, PtCallback *callback, void *userData) { if (time_started_flag) return ptNoError; - gettimeofday(&time_offset, NULL); /* need this set before process runs */ + /* need this set before process runs: */ + clock_gettime(CLOCK_MONOTONIC_RAW, &time_offset); if (callback) { int res; pt_callback_parameters *parms = (pt_callback_parameters *) @@ -99,7 +100,7 @@ PtError Pt_Start(int resolution, PtCallback *callback, void *userData) } -PtError Pt_Stop() +PtError Pt_Stop(void) { /* printf("Pt_Stop called\n"); */ pt_callback_proc_id++; @@ -112,20 +113,20 @@ PtError Pt_Stop() } -int Pt_Started() +int Pt_Started(void) { return time_started_flag; } -PtTimestamp Pt_Time() +PtTimestamp Pt_Time(void) { - long seconds, milliseconds; - struct timeval now; - gettimeofday(&now, NULL); + long seconds, ms; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC_RAW, &now); seconds = now.tv_sec - time_offset.tv_sec; - milliseconds = now.tv_usec - time_offset.tv_usec; - return seconds * 1000 + milliseconds; + ms = (now.tv_nsec - time_offset.tv_nsec) / 1000000; /* round down */ + return seconds * 1000 + ms; } @@ -133,6 +134,3 @@ void Pt_Sleep(int32_t duration) { usleep(duration * 1000); } - - - diff --git a/3rdparty/portmidi/porttime/ptmacosx_cf.c b/3rdparty/portmidi/porttime/ptmacosx_cf.c index 3eb0de12f82..1bc9658d216 100644 --- a/3rdparty/portmidi/porttime/ptmacosx_cf.c +++ b/3rdparty/portmidi/porttime/ptmacosx_cf.c @@ -111,7 +111,7 @@ PtError Pt_Start(int resolution, PtCallback *callback, void *userData) } -PtError Pt_Stop() +PtError Pt_Stop(void) { printf("Pt_Stop called\n"); @@ -121,13 +121,13 @@ PtError Pt_Stop() } -int Pt_Started() +int Pt_Started(void) { return time_started_flag; } -PtTimestamp Pt_Time() +PtTimestamp Pt_Time(void) { CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); return (PtTimestamp) ((now - startTime) * 1000.0); diff --git a/3rdparty/portmidi/porttime/ptmacosx_mach.c b/3rdparty/portmidi/porttime/ptmacosx_mach.c index f4fec09d4c4..bc6a1a01084 100644 --- a/3rdparty/portmidi/porttime/ptmacosx_mach.c +++ b/3rdparty/portmidi/porttime/ptmacosx_mach.c @@ -4,20 +4,29 @@ #include <stdio.h> #include <CoreAudio/HostTime.h> -#include <mach/mach.h> -#include <mach/mach_error.h> -#include <mach/mach_time.h> -#include <mach/clock.h> +#import <mach/mach.h> +#import <mach/mach_error.h> +#import <mach/mach_time.h> +#import <mach/clock.h> #include <unistd.h> +#include <AvailabilityMacros.h> #include "porttime.h" #include "sys/time.h" #include "pthread.h" -#if !defined NSEC_PER_MSEC -#define NSEC_PER_MSEC 1000000ull +#ifndef NSEC_PER_MSEC +#define NSEC_PER_MSEC 1000000 +#endif +#define THREAD_IMPORTANCE 63 + +// QOS headers are available as of macOS 10.10 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 +#include "sys/qos.h" +#define HAVE_APPLE_QOS 1 +#else +#undef HAVE_APPLE_QOS #endif -#define THREAD_IMPORTANCE 30 static int time_started_flag = FALSE; static UInt64 start_time; @@ -47,7 +56,7 @@ static void *Pt_CallbackProc(void *p) (thread_policy_t)&extendedPolicy, THREAD_EXTENDED_POLICY_COUNT); if (error != KERN_SUCCESS) { - mach_error((char *)"Couldn't set thread timeshare policy", error); + mach_error("Couldn't set thread timeshare policy", error); } precedencePolicy.importance = THREAD_IMPORTANCE; @@ -55,22 +64,65 @@ static void *Pt_CallbackProc(void *p) (thread_policy_t)&precedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); if (error != KERN_SUCCESS) { - mach_error((char *)"Couldn't set thread precedence policy", error); + mach_error("Couldn't set thread precedence policy", error); } + // Most important, set real-time constraints. + + // Define the guaranteed and max fraction of time for the audio thread. + // These "duty cycle" values can range from 0 to 1. A value of 0.5 + // means the scheduler would give half the time to the thread. + // These values have empirically been found to yield good behavior. + // Good means that audio performance is high and other threads won't starve. + const double kGuaranteedAudioDutyCycle = 0.75; + const double kMaxAudioDutyCycle = 0.85; + + // Define constants determining how much time the audio thread can + // use in a given time quantum. All times are in milliseconds. + + // About 128 frames @44.1KHz + const double kTimeQuantum = 2.9; + + // Time guaranteed each quantum. + const double kAudioTimeNeeded = kGuaranteedAudioDutyCycle * kTimeQuantum; + + // Maximum time each quantum. + const double kMaxTimeAllowed = kMaxAudioDutyCycle * kTimeQuantum; + // Get the conversion factor from milliseconds to absolute time + // which is what the time-constraints call needs. + mach_timebase_info_data_t tb_info; + mach_timebase_info(&tb_info); + double ms_to_abs_time = + ((double)tb_info.denom / (double)tb_info.numer) * 1000000; + + thread_time_constraint_policy_data_t time_constraints; + time_constraints.period = (uint32_t)(kTimeQuantum * ms_to_abs_time); + time_constraints.computation = (uint32_t)(kAudioTimeNeeded * ms_to_abs_time); + time_constraints.constraint = (uint32_t)(kMaxTimeAllowed * ms_to_abs_time); + time_constraints.preemptible = 0; + + error = thread_policy_set(mach_thread_self(), + THREAD_TIME_CONSTRAINT_POLICY, + (thread_policy_t)&time_constraints, + THREAD_TIME_CONSTRAINT_POLICY_COUNT); + if (error != KERN_SUCCESS) { + mach_error("Couldn't set thread precedence policy", error); + } + /* to kill a process, just increment the pt_callback_proc_id */ - /* printf("pt_callback_proc_id %d, id %d\n", pt_callback_proc_id, parameters->id); */ + /* printf("pt_callback_proc_id %d, id %d\n", pt_callback_proc_id, + parameters->id); */ while (pt_callback_proc_id == parameters->id) { /* wait for a multiple of resolution ms */ UInt64 wait_time; int delay = mytime++ * parameters->resolution - Pt_Time(); - PtTimestamp timestamp; + PtTimestamp timestamp; if (delay < 0) delay = 0; wait_time = AudioConvertNanosToHostTime((UInt64)delay * NSEC_PER_MSEC); wait_time += AudioGetCurrentHostTime(); - error = mach_wait_until(wait_time); - timestamp = Pt_Time(); + mach_wait_until(wait_time); + timestamp = Pt_Time(); (*(parameters->callback))(timestamp, parameters->userData); } free(parameters); @@ -93,7 +145,26 @@ PtError Pt_Start(int resolution, PtCallback *callback, void *userData) parms->resolution = resolution; parms->callback = callback; parms->userData = userData; + +#ifdef HAVE_APPLE_QOS + pthread_attr_t qosAttribute; + pthread_attr_init(&qosAttribute); + pthread_attr_set_qos_class_np(&qosAttribute, + QOS_CLASS_USER_INTERACTIVE, 0); + + res = pthread_create(&pt_thread_pid, &qosAttribute, Pt_CallbackProc, + parms); +#else res = pthread_create(&pt_thread_pid, NULL, Pt_CallbackProc, parms); +#endif + + struct sched_param sp; + memset(&sp, 0, sizeof(struct sched_param)); + sp.sched_priority = sched_get_priority_max(SCHED_RR); + if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == -1) { + return ptHostError; + } + if (res != 0) return ptHostError; } @@ -102,7 +173,7 @@ PtError Pt_Start(int resolution, PtCallback *callback, void *userData) } -PtError Pt_Stop() +PtError Pt_Stop(void) { /* printf("Pt_Stop called\n"); */ pt_callback_proc_id++; @@ -112,13 +183,13 @@ PtError Pt_Stop() } -int Pt_Started() +int Pt_Started(void) { return time_started_flag; } -PtTimestamp Pt_Time() +PtTimestamp Pt_Time(void) { UInt64 clock_time, nsec_time; clock_time = AudioGetCurrentHostTime() - start_time; diff --git a/3rdparty/portmidi/porttime/ptwinmm.c b/3rdparty/portmidi/porttime/ptwinmm.c index 17675bd6c6a..05f5c74eea3 100644 --- a/3rdparty/portmidi/porttime/ptwinmm.c +++ b/3rdparty/portmidi/porttime/ptwinmm.c @@ -38,7 +38,7 @@ PMEXPORT PtError Pt_Start(int resolution, PtCallback *callback, void *userData) } -PMEXPORT PtError Pt_Stop() +PMEXPORT PtError Pt_Stop(void) { if (!time_started_flag) return ptAlreadyStopped; if (time_callback && timer_id) { @@ -52,13 +52,13 @@ PMEXPORT PtError Pt_Stop() } -PMEXPORT int Pt_Started() +PMEXPORT int Pt_Started(void) { return time_started_flag; } -PMEXPORT PtTimestamp Pt_Time() +PMEXPORT PtTimestamp Pt_Time(void) { return timeGetTime() - time_offset; } |