Placed full code of portmidi in 3rdparty folder (nw)

This commit is contained in:
Miodrag Milanovic 2015-01-10 16:58:11 +01:00
parent d103debef2
commit 1273e97e73
154 changed files with 28278 additions and 7066 deletions

128
3rdparty/portmidi/ALL_BUILD.vcproj vendored Normal file
View File

@ -0,0 +1,128 @@
<?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=\&quot;Debug\&quot;"
AssemblerListingLocation="Debug"
ObjectFile="$(IntDir)\"
/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories=".\pm_common;.\porttime;"
PreprocessorDefinitions="CMAKE_INTDIR=\&quot;Debug\&quot;"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="CMAKE_INTDIR=\&quot;Debug\&quot;"
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=\&quot;Release\&quot;"
AssemblerListingLocation="Release"
ObjectFile="$(IntDir)\"
/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories=".\pm_common;.\porttime;"
PreprocessorDefinitions="CMAKE_INTDIR=\&quot;Release\&quot;"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="CMAKE_INTDIR=\&quot;Release\&quot;"
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>

192
3rdparty/portmidi/CHANGELOG.txt vendored Normal file
View File

@ -0,0 +1,192 @@
/* CHANGELOG FOR PORTMIDI
*
* 19Oct09 Roger Dannenberg
* - Changes dynamic library names from portmidi_d to portmidi to
* be backward-compatible with programs expecting a library by
* the old name.
*
* 04Oct09 Roger Dannenberg
* - Converted to using Cmake.
* - Renamed static and dynamic library files to portmidi_s and portmidi_d
* - Eliminated VC9 and VC8 files (went back to simply test.vcproj, etc.,
* use Cmake to switch from the provided VC9 files to VC8 or other)
* - Many small changes to prepare for 64-bit architectures (but only
* tested on 32-bit machines)
*
* 16Jun09 Roger Dannenberg
* - Started using Microsoft Visual C++ Version 9 (Express). Converted
* all *-VC9.vcproj file to *.vcproj and renamed old project files to
* *-VC8.proj. Previously, output from VC9 went to special VC9 files,
* that breaks any program or script looking for output in release or
* debug files, so now both compiler version output to the same folders.
* Now, debug version uses static linking with debug DLL runtime, and
* release version uses static linking with statically linked runtime.
* Converted to Inno Setup and worked on scripts to make things build
* properly, especially pmdefaults.
*
* 02Jan09 Roger Dannenberg
* - Created Java interface and wrote PmDefaults application to set
* values for Pm_GetDefaultInputDeviceID() and
* Pm_GetDefaultOutputDeviceID(). Other fixes.
*
* 19Jun08 Roger Dannenberg and Austin Sung
* - Removed USE_DLL_FOR_CLEANUP -- Windows 2000 through Vista seem to be
* fixed now, and can recover if MIDI ports are left open
* - Various other minor patches
*
* 17Jan07 Roger Dannenberg
* - Lots more help for Common Lisp user in pm_cl
* - Minor fix to eliminate a compiler warning
* - Went back to single library in OS X for both portmidi and porttime
*
* 16Jan07 Roger Dannenberg
* - OOPS! fixed bug where short messages all had zero data
* - Makefile.osx static library build now makes universal (i386 + ppc)
* binaries
*
* 15Jan07 Roger Dannenberg
* - multiple rewrites of sysex handling code to take care of
* error-handling, embedded messages, message filtering,
* driver bugs, and host limitations.
* - fixed windows to use dwBufferLength rather than
* dwBytesRecorded for long buffer output (fix by Nigel Brown)
* - Win32 MME code always appends an extra zero to long buffer
* output to work around a problem with earlier versions of Midi Yoke
* - Added mm, a command line Midi Monitor to pm_test suite
* - Revised copyright notice to match PortAudio/MIT license (requests
* are moved out of the license proper and into a separate paragraph)
*
* 18Oct06 Roger Dannenberg
* - replace FIFO in pmutil with Light Pipe-based multiprocessor-safe alg.
* - replace FIFO in portmidi.c with PmQueue from pmutil
*
* 07Oct06 cpr & Roger Dannenberg
* - overhaul of CoreMIDI input to handle running status and multiple
* - messages per packet, with additional error detection
* - added Leigh Smith and Rick Taube support for Common Lisp and
* - dynamic link libraries in OSX
* - initialize static global seq = NULL in pmlinuxalsa.c
*
* 05Sep06 Sebastien Frippiat
* - check if (ALSA) seq exists before closing it in pm_linuxalsa_term()
*
* 05Sep06 Andreas Micheler and Cecilio
* - fixed memory leak by freeing someo objects in pm_winmm_term()
* - and another leak by freeing descriptors in Pm_Terminate()
*
* 23Aug06 RBD
* - various minor fixes
*
* 04Nov05 Olivier Tristan
* - changes to OS X to properly retrieve real device name on CoreMidi
*
* 19Jul05 Roger Dannenberg
* - included pmBufferMaxSize in Pm_GetErrorText()
*
* 23Mar05 Torgier Strand Henriksen
* - cleaner termination of porttime thread under Linux
*
* 15Nov04 Ben Allison
* - sysex output now uses one buffer/message and reallocates buffer
* - if needed
* - filters expanded for many message types and channels
* - detailed changes are as follows:
* ------------- in pmwinmm.c --------------
* - new #define symbol: OUTPUT_BYTES_PER_BUFFER
* - change SYSEX_BYTES_PER_BUFFER to 1024
* - added MIDIHDR_BUFFER_LENGTH(x) to correctly count midihdr buffer length
* - change MIDIHDR_SIZE(x) to (MIDIHDR_BUFFER_LENGTH(x) + sizeof(MIDIHDR))
* - change allocate_buffer to use new MIDIHDR_BUFFER_LENGTH macro
* - new macros for MIDIHDR_SYSEX_SIZE and MIDIHDR_SYSEX_BUFFER_LENGTH
* - similar to above, but counts appropriately for sysex messages
* - added the following members to midiwinmm_struct for sysex data:
* - LPMIDIHDR *sysex_buffers; ** pool of buffers for sysex data **
* - int num_sysex_buffers; ** how many sysex buffers **
* - int next_sysex_buffer; ** index of next sysexbuffer to send **
* - HANDLE sysex_buffer_signal; ** to wait for free sysex buffer **
* - duplicated allocate_buffer, alocate_buffers and get_free_output_buffer
* - into equivalent sysex_buffer form
* - changed winmm_in_open to initialize new midiwinmm_struct members and
* - to use the new allocate_sysex_buffer() function instead of
* - allocate_buffer()
* - changed winmm_out_open to initialize new members, create sysex buffer
* - signal, and allocate 2 sysex buffers
* - changed winmm_out_delete to free sysex buffers and shut down the sysex
* - buffer signal
* - create new function resize_sysex_buffer which resizes m->hdr to the
* - passed size, and corrects the midiwinmm_struct accordingly.
* - changed winmm_write_byte to use new resize_sysex_buffer function,
* - if resize fails, write current buffer to output and continue
* - changed winmm_out_callback to use buffer_signal or sysex_buffer_signal
* - depending on which buffer was finished
* ------------- in portmidi.h --------------
* - added pmBufferMaxSize to PmError to indicate that the buffer would be
* - too large for the underlying API
* - added additional filters
* - added prototype, documentation, and helper macro for Pm_SetChannelMask
* ------------- in portmidi.c --------------
* - added pm_status_filtered() and pm_realtime_filtered() functions to
* separate filtering logic from buffer logic in pm_read_short
* - added Pm_SetChannelMask function
* - added pm_channel_filtered() function
* ------------- in pminternal.h --------------
* - added member to PortMidiStream for channel mask
*
* 25May04 RBD
* - removed support for MIDI THRU
* - moved filtering from Pm_Read to pm_enqueue to avoid buffer ovfl
* - extensive work on Mac OS X port, especially sysex and error handling
*
* 18May04 RBD
* - removed side-effects from assert() calls. Now you can disable assert().
* - no longer check pm_hosterror everywhere, fixing a bug where an open
* failure could cause a write not to work on a previously opened port
* until you call Pm_GetHostErrorText().
* 16May04 RBD and Chris Roberts
* - Some documentation wordsmithing in portmidi.h
* - Dynamically allocate port descriptor structures
* - Fixed parameter error in midiInPrepareBuffer and midiInAddBuffer.
*
* 09Oct03 RBD
* - Changed Thru handling. Now the client does all the work and the client
* must poll or read to keep thru messages flowing.
*
* 31May03 RBD
* - Fixed various bugs.
* - Added linux ALSA support with help from Clemens Ladisch
* - Added Mac OS X support, implemented by Jon Parise, updated and
* integrated by Andrew Zeldis and Zico Kolter
* - Added latency program to build histogram of system latency using PortTime.
*
* 30Jun02 RBD Extensive rewrite of sysex handling. It works now.
* Extensive reworking of error reporting and error text -- no
* longer use dictionary call to delete data; instead, Pm_Open
* and Pm_Close clean up before returning an error code, and
* error text is saved in a system-independent location.
* Wrote sysex.c to test sysex message handling.
*
* 15Jun02 BCT changes:
* - Added pmHostError text handling.
* - For robustness, check PortMidi stream args not NULL.
* - Re-C-ANSI-fied code (changed many C++ comments to C style)
* - Reorganized code in pmwinmm according to input/output functionality (made
* cleanup handling easier to reason about)
* - Fixed Pm_Write calls (portmidi.h says these should not return length but Pm_Error)
* - Cleaned up memory handling (now system specific data deleted via dictionary
* call in PortMidi, allows client to query host errors).
* - Added explicit asserts to verify various aspects of pmwinmm implementation behaves as
* logic implies it should. Specifically: verified callback routines not reentrant and
* all verified status for all unchecked Win32 MMedia API calls perform successfully
* - Moved portmidi initialization and clean-up routines into DLL to fix Win32 MMedia API
* bug (i.e. if devices not explicitly closed, must reboot to debug application further).
* With this change, clients no longer need explicitly call Pm_Initialize, Pm_Terminate, or
* explicitly Pm_Close open devices when using WinMM version of PortMidi.
*
* 23Jan02 RBD Fixed bug in pmwinmm.c thru handling
*
* 21Jan02 RBD Added tests in Pm_OpenInput() and Pm_OpenOutput() to prevent
* opening an input as output and vice versa.
* Added comments and documentation.
* Implemented Pm_Terminate().
*
*/

77
3rdparty/portmidi/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,77 @@
# 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)
include_directories(pm_common porttime)
add_subdirectory(pm_common)
add_subdirectory(pm_test)
add_subdirectory(pm_dylib)
# Cannot figure out how to make an xcode Java application with CMake
add_subdirectory(pm_java)

1472
3rdparty/portmidi/Doxyfile vendored Normal file

File diff suppressed because it is too large Load Diff

84
3rdparty/portmidi/README.txt vendored Normal file
View File

@ -0,0 +1,84 @@
README for PortMidi
Roger B. Dannenberg
VERSION: please use "svn info" to get info.
Documentation for PortMidi is found in pm_common/portmidi.h.
Additional documentation:
- 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)
---------- some notes on the design of PortMidi ----------
POINTERS VS DEVICE NUMBERS
When you open a MIDI port, PortMidi allocates a structure to
maintain the state of the open device. Since every device is
also listed in a table, you might think it would be simpler to
use the table index rather than a pointer to identify a device.
This would also help with error checking (it's hard to make
sure a pointer is valid). PortMidi's design parallels that of
PortAudio.
ERROR HANDLING
Error handling turned out to be much more complicated than expected.
PortMidi functions return error codes that the caller can check.
In addition, errors may occur asynchronously due to MIDI input.
However, for Windows, there are virtually no errors that can
occur if the code is correct and not passing bogus values. One
exception is an error that the system is out of memory, but my
guess is that one is unlikely to recover gracefully from that.
Therefore, all errors in callbacks are guarded by assert(), which
means not guarded at all in release configurations.
Ordinarily, the caller checks for an error code. If the error is
system-dependent, pmHostError is returned and the caller can
call Pm_GetHostErrorText to get a text description of the error.
Host error codes are system-specific and are recorded in the
system-specific data allocated for each open MIDI port.
However, if an error occurs on open or close,
we cannot store the error with the device because there will be
no device data (assuming PortMidi cleans up after devices that
are not open). For open and close, we will convert the error
to text, copy it to a global string, and set pm_hosterror, a
global flag.
Similarly, whenever a Read or Write operation returns pmHostError,
the corresponding error string is copied to a global string
and pm_hosterror is set. This makes getting error strings
simple and uniform, although it does cost a string copy and some
overhead even if the user does not want to look at the error data.
The system-specific Read, Write, Poll, etc. implementations should
check for asynchronous errors and return immediately if one is
found so that these get reported. This happens in the Mac OS X
code, where lots of things are happening in callbacks, but again,
in Windows, there are no error codes recorded in callbacks.
DEBUGGING
If you are building a console application for research, we suggest
compiling with the option PM_CHECK_ERRORS. This will 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.
The Windows version (and perhaps others) also offers a DEBUG
compile-time option. See README_WIN.txt.

128
3rdparty/portmidi/ZERO_CHECK.vcproj vendored Normal file
View File

@ -0,0 +1,128 @@
<?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=\&quot;Debug\&quot;"
AssemblerListingLocation="Debug"
ObjectFile="$(IntDir)\"
/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories=".\pm_common;.\porttime;"
PreprocessorDefinitions="CMAKE_INTDIR=\&quot;Debug\&quot;"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="CMAKE_INTDIR=\&quot;Debug\&quot;"
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=\&quot;Release\&quot;"
AssemblerListingLocation="Release"
ObjectFile="$(IntDir)\"
/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories=".\pm_common;.\porttime;"
PreprocessorDefinitions="CMAKE_INTDIR=\&quot;Release\&quot;"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="CMAKE_INTDIR=\&quot;Release\&quot;"
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>

40
3rdparty/portmidi/license.txt vendored Normal file
View File

@ -0,0 +1,40 @@
/*
* PortMidi Portable Real-Time MIDI Library
*
* license.txt -- a copy of the PortMidi copyright notice and license information
*
* 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
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights 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 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 text above constitutes the entire PortMidi license; however,
* the PortMusic community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/

104
3rdparty/portmidi/pm_cl/README_CL.txt vendored Normal file
View File

@ -0,0 +1,104 @@
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)

View File

@ -0,0 +1,384 @@
;;; **********************************************************************
;;; 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*)

112
3rdparty/portmidi/pm_cl/test-no-cm.lisp vendored Normal file
View File

@ -0,0 +1,112 @@
;; 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)

View File

@ -0,0 +1,128 @@
# pm_common
# set the build directory for libportmidi.a to be in portmidi, not in
# portmidi/pm_common
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)
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)
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)
# /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})
# define the jni library
include_directories(${JAVA_INCLUDE_PATHS})
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")
# 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)

View File

@ -30,51 +30,51 @@ void pm_free(void *ptr);
/* if an error occurs while opening or closing a midi stream, set these: */
extern int pm_hosterror;
extern char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN];
struct pm_internal_struct;
/* these do not use PmInternal because it is not defined yet... */
typedef PmError (*pm_write_short_fn)(struct pm_internal_struct *midi,
PmEvent *buffer);
typedef PmError (*pm_write_short_fn)(struct pm_internal_struct *midi,
PmEvent *buffer);
typedef PmError (*pm_begin_sysex_fn)(struct pm_internal_struct *midi,
PmTimestamp timestamp);
PmTimestamp timestamp);
typedef PmError (*pm_end_sysex_fn)(struct pm_internal_struct *midi,
PmTimestamp timestamp);
PmTimestamp timestamp);
typedef PmError (*pm_write_byte_fn)(struct pm_internal_struct *midi,
unsigned char byte, PmTimestamp timestamp);
unsigned char byte, PmTimestamp timestamp);
typedef PmError (*pm_write_realtime_fn)(struct pm_internal_struct *midi,
PmEvent *buffer);
PmEvent *buffer);
typedef PmError (*pm_write_flush_fn)(struct pm_internal_struct *midi,
PmTimestamp timestamp);
PmTimestamp timestamp);
typedef PmTimestamp (*pm_synchronize_fn)(struct pm_internal_struct *midi);
/* pm_open_fn should clean up all memory and close the device if any part
of the open fails */
typedef PmError (*pm_open_fn)(struct pm_internal_struct *midi,
void *driverInfo);
void *driverInfo);
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);
unsigned int len);
typedef unsigned int (*pm_has_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_flush_fn write_flush; /* send any accumulated but unsent data */
pm_synchronize_fn synchronize; /* synchronize portmidi 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
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_flush_fn write_flush; /* send any accumulated but unsent data */
pm_synchronize_fn synchronize; /* synchronize portmidi 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
pm_host_error_fn host_error; /* provide text readable host error message
for device (clears and resets) */
} pm_fns_node, *pm_fns_type;
@ -83,12 +83,12 @@ typedef struct {
extern pm_fns_node pm_none_dictionary;
typedef struct {
PmDeviceInfo pub; /* some portmidi state also saved in here (for autmatic
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
void *descriptor; /* ID number passed to win32 multimedia API open */
void *internalDescriptor; /* points to PmInternal device, allows automatic
device closing */
pm_fns_type dictionary;
pm_fns_type dictionary;
} descriptor_node, *descriptor_type;
extern int pm_descriptor_max;
@ -98,67 +98,67 @@ extern int pm_descriptor_index;
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 descriptors) */
short write_flag; /* MIDI_IN, or MIDI_OUT */
PmTimeProcPtr time_proc; /* where to get the time */
void *time_info; /* pass this to get_time() */
int32_t buffer_len; /* how big is the buffer or queue? */
PmQueue *queue;
PmTimeProcPtr time_proc; /* where to get the time */
void *time_info; /* pass this to get_time() */
int32_t buffer_len; /* how big is the buffer or queue? */
PmQueue *queue;
int32_t latency; /* time delay in ms between timestamps and actual output */
/* set to zero to get immediate, simple blocking output */
/* if latency is zero, timestamps will be ignored; */
/* if midi input device, this field ignored */
int sysex_in_progress; /* when sysex status is seen, this flag becomes
int32_t latency; /* time delay in ms between timestamps and actual output */
/* set to zero to get immediate, simple blocking output */
/* if latency is zero, timestamps will be ignored; */
/* if midi input device, this field ignored */
int sysex_in_progress; /* when sysex status is seen, this flag becomes
* true until EOX is seen. When true, new data is appended to the
* stream of outgoing bytes. When overflow occurs, sysex data is
* stream of outgoing bytes. When overflow occurs, sysex data is
* dropped (until an EOX or non-real-timei status byte is seen) so
* that, if the overflow condition is cleared, we don't start
* that, if the overflow condition is cleared, we don't start
* sending data from the middle of a sysex message. If a sysex
* message is filtered, sysex_in_progress is false, causing the
* message to be dropped. */
PmMessage sysex_message; /* buffer for 4 bytes of sysex data */
int sysex_message_count; /* how many bytes in sysex_message so far */
PmMessage sysex_message; /* buffer for 4 bytes of sysex data */
int sysex_message_count; /* how many bytes in sysex_message so far */
int32_t filters; /* flags that filter incoming message classes */
int32_t channel_mask; /* filter incoming messages based on channel */
PmTimestamp last_msg_time; /* timestamp of last message */
PmTimestamp sync_time; /* time of last synchronization */
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 */
/* 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,
* but this does not count time in the driver, so I don't know if it is
* important
*/
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 */
int32_t filters; /* flags that filter incoming message classes */
int32_t channel_mask; /* filter incoming messages based on channel */
PmTimestamp last_msg_time; /* timestamp of last message */
PmTimestamp sync_time; /* time of last synchronization */
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 */
/* 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,
* but this does not count time in the driver, so I don't know if it is
* important
*/
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 */
} PmInternal;
/* defined by system specific implementation, e.g. pmwinmm, used by PortMidi */
void pm_init(void);
void pm_term(void);
void pm_init(void);
void pm_term(void);
/* defined by portMidi, used by pmwinmm */
PmError none_write_short(PmInternal *midi, PmEvent *buffer);
PmError none_write_byte(PmInternal *midi, unsigned char byte,
PmTimestamp timestamp);
PmError none_write_byte(PmInternal *midi, unsigned char byte,
PmTimestamp timestamp);
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);
pm_fns_type dictionary);
uint32_t pm_read_bytes(PmInternal *midi, const unsigned char *data, int len,
PmTimestamp timestamp);
PmTimestamp timestamp);
void pm_read_short(PmInternal *midi, PmEvent *event);
#define none_write_flush pm_fail_timestamp_fn
@ -168,10 +168,11 @@ void pm_read_short(PmInternal *midi, PmEvent *event);
#define MIDI_REALTIME_MASK 0xf8
#define is_real_time(msg) \
((Pm_MessageStatus(msg) & MIDI_REALTIME_MASK) == MIDI_REALTIME_MASK)
((Pm_MessageStatus(msg) & MIDI_REALTIME_MASK) == MIDI_REALTIME_MASK)
int pm_find_default_device(char *pattern, int is_input);
#ifdef __cplusplus
}
#endif

161
3rdparty/portmidi/pm_common/pmjni.vcproj vendored Normal file
View File

@ -0,0 +1,161 @@
<?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;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
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=\&quot;Debug\&quot;,pmjni_EXPORTS"
AssemblerListingLocation="Debug"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="../Debug/pmjni.pdb"
/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories="..\pm_common;..\porttime;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\&quot;Debug\&quot;,pmjni_EXPORTS"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\&quot;Debug\&quot;,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 &quot;C:\Program Files\Java\jdk1.6.0_16\include\..\lib\jvm.lib&quot; "
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;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
CompileAs="1"
ExceptionHandling="0"
InlineFunctionExpansion="2"
Optimization="2"
RuntimeLibrary="0"
WarningLevel="3"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;,pmjni_EXPORTS"
AssemblerListingLocation="Release"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="../Release/pmjni.pdb"
/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories="..\pm_common;..\porttime;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;,pmjni_EXPORTS"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;,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 &quot;C:\Program Files\Java\jdk1.6.0_16\include\..\lib\jvm.lib&quot; "
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>

284
3rdparty/portmidi/pm_common/pmutil.c vendored Normal file
View File

@ -0,0 +1,284 @@
/* pmutil.c -- some helpful utilities for building midi
applications that use PortMidi
*/
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "portmidi.h"
#include "pmutil.h"
#include "pminternal.h"
#ifdef WIN32
#define bzero(addr, siz) memset(addr, 0, siz)
#endif
// #define QUEUE_DEBUG 1
#ifdef QUEUE_DEBUG
#include "stdio.h"
#endif
typedef struct {
long head;
long tail;
long len;
long overflow;
int32_t msg_size; /* number of int32_t in a message including extra word */
int32_t peek_overflow;
int32_t *buffer;
int32_t *peek;
int32_t peek_flag;
} PmQueueRep;
PMEXPORT PmQueue *Pm_QueueCreate(long num_msgs, int32_t bytes_per_msg)
{
int32_t int32s_per_msg =
(int32_t) (((bytes_per_msg + sizeof(int32_t) - 1) &
~(sizeof(int32_t) - 1)) / sizeof(int32_t));
PmQueueRep *queue = (PmQueueRep *) pm_alloc(sizeof(PmQueueRep));
if (!queue) /* memory allocation failed */
return NULL;
/* need extra word per message for non-zero encoding */
queue->len = num_msgs * (int32s_per_msg + 1);
queue->buffer = (int32_t *) pm_alloc(queue->len * sizeof(int32_t));
bzero(queue->buffer, queue->len * sizeof(int32_t));
if (!queue->buffer) {
pm_free(queue);
return NULL;
} else { /* allocate the "peek" buffer */
queue->peek = (int32_t *) pm_alloc(int32s_per_msg * sizeof(int32_t));
if (!queue->peek) {
/* free everything allocated so far and return */
pm_free(queue->buffer);
pm_free(queue);
return NULL;
}
}
bzero(queue->buffer, queue->len * sizeof(int32_t));
queue->head = 0;
queue->tail = 0;
/* msg_size is in words */
queue->msg_size = int32s_per_msg + 1; /* note extra word is counted */
queue->overflow = FALSE;
queue->peek_overflow = FALSE;
queue->peek_flag = FALSE;
return queue;
}
PMEXPORT PmError Pm_QueueDestroy(PmQueue *q)
{
PmQueueRep *queue = (PmQueueRep *) q;
/* arg checking */
if (!queue || !queue->buffer || !queue->peek)
return pmBadPtr;
pm_free(queue->peek);
pm_free(queue->buffer);
pm_free(queue);
return pmNoError;
}
PMEXPORT PmError Pm_Dequeue(PmQueue *q, void *msg)
{
long head;
PmQueueRep *queue = (PmQueueRep *) q;
int i;
int32_t *msg_as_int32 = (int32_t *) msg;
/* arg checking */
if (!queue)
return pmBadPtr;
/* a previous peek operation encountered an overflow, but the overflow
* has not yet been reported to client, so do it now. No message is
* returned, but on the next call, we will return the peek buffer.
*/
if (queue->peek_overflow) {
queue->peek_overflow = FALSE;
return pmBufferOverflow;
}
if (queue->peek_flag) {
memcpy(msg, queue->peek, (queue->msg_size - 1) * sizeof(int32_t));
queue->peek_flag = FALSE;
return pmGotData;
}
head = queue->head;
/* if writer overflows, it writes queue->overflow = tail+1 so that
* when the reader gets to that position in the buffer, it can
* return the overflow condition to the reader. The problem is that
* at overflow, things have wrapped around, so tail == head, and the
* reader will detect overflow immediately instead of waiting until
* it reads everything in the buffer, wrapping around again to the
* point where tail == head. So the condition also checks that
* queue->buffer[head] is zero -- if so, then the buffer is now
* empty, and we're at the point in the msg stream where overflow
* occurred. It's time to signal overflow to the reader. If
* queue->buffer[head] is non-zero, there's a message there and we
* should read all the way around the buffer before signalling overflow.
* There is a write-order dependency here, but to fail, the overflow
* field would have to be written while an entire buffer full of
* writes are still pending. I'm assuming out-of-order writes are
* possible, but not that many.
*/
if (queue->overflow == head + 1 && !queue->buffer[head]) {
queue->overflow = 0; /* non-overflow condition */
return pmBufferOverflow;
}
/* test to see if there is data in the queue -- test from back
* to front so if writer is simultaneously writing, we don't
* waste time discovering the write is not finished
*/
for (i = queue->msg_size - 1; i >= 0; i--) {
if (!queue->buffer[head + i]) {
return pmNoData;
}
}
memcpy(msg, (char *) &queue->buffer[head + 1],
sizeof(int32_t) * (queue->msg_size - 1));
/* fix up zeros */
i = queue->buffer[head];
while (i < queue->msg_size) {
int32_t j;
i--; /* msg does not have extra word so shift down */
j = msg_as_int32[i];
msg_as_int32[i] = 0;
i = j;
}
/* signal that data has been removed by zeroing: */
bzero((char *) &queue->buffer[head], sizeof(int32_t) * queue->msg_size);
/* update head */
head += queue->msg_size;
if (head == queue->len) head = 0;
queue->head = head;
return pmGotData; /* success */
}
PMEXPORT PmError Pm_SetOverflow(PmQueue *q)
{
PmQueueRep *queue = (PmQueueRep *) q;
long tail;
/* arg checking */
if (!queue)
return pmBadPtr;
/* no more enqueue until receiver acknowledges overflow */
if (queue->overflow) return pmBufferOverflow;
tail = queue->tail;
queue->overflow = tail + 1;
return pmBufferOverflow;
}
PMEXPORT PmError Pm_Enqueue(PmQueue *q, void *msg)
{
PmQueueRep *queue = (PmQueueRep *) q;
long tail;
int i;
int32_t *src = (int32_t *) msg;
int32_t *ptr;
int32_t *dest;
int rslt;
if (!queue)
return pmBadPtr;
/* no more enqueue until receiver acknowledges overflow */
if (queue->overflow) return pmBufferOverflow;
rslt = Pm_QueueFull(q);
/* already checked above: if (rslt == pmBadPtr) return rslt; */
tail = queue->tail;
if (rslt) {
queue->overflow = tail + 1;
return pmBufferOverflow;
}
/* queue is has room for message, and overflow flag is cleared */
ptr = &queue->buffer[tail];
dest = ptr + 1;
for (i = 1; i < queue->msg_size; i++) {
int32_t j = src[i - 1];
if (!j) {
*ptr = i;
ptr = dest;
} else {
*dest = j;
}
dest++;
}
*ptr = i;
tail += queue->msg_size;
if (tail == queue->len) tail = 0;
queue->tail = tail;
return pmNoError;
}
PMEXPORT int Pm_QueueEmpty(PmQueue *q)
{
PmQueueRep *queue = (PmQueueRep *) q;
return (!queue) || /* null pointer -> return "empty" */
(queue->buffer[queue->head] == 0 && !queue->peek_flag);
}
PMEXPORT int Pm_QueueFull(PmQueue *q)
{
long tail;
int i;
PmQueueRep *queue = (PmQueueRep *) q;
/* arg checking */
if (!queue)
return pmBadPtr;
tail = queue->tail;
/* test to see if there is space in the queue */
for (i = 0; i < queue->msg_size; i++) {
if (queue->buffer[tail + i]) {
return TRUE;
}
}
return FALSE;
}
PMEXPORT void *Pm_QueuePeek(PmQueue *q)
{
PmError rslt;
int32_t temp;
PmQueueRep *queue = (PmQueueRep *) q;
/* arg checking */
if (!queue)
return NULL;
if (queue->peek_flag) {
return queue->peek;
}
/* this is ugly: if peek_overflow is set, then Pm_Dequeue()
* returns immediately with pmBufferOverflow, but here, we
* want Pm_Dequeue() to really check for data. If data is
* there, we can return it
*/
temp = queue->peek_overflow;
queue->peek_overflow = FALSE;
rslt = Pm_Dequeue(q, queue->peek);
queue->peek_overflow = temp;
if (rslt == 1) {
queue->peek_flag = TRUE;
return queue->peek;
} else if (rslt == pmBufferOverflow) {
/* when overflow is indicated, the queue is empty and the
* first message that was dropped by Enqueue (signalling
* pmBufferOverflow to its caller) would have been the next
* message in the queue. Pm_QueuePeek will return NULL, but
* remember that an overflow occurred. (see Pm_Dequeue)
*/
queue->peek_overflow = TRUE;
}
return NULL;
}

View File

@ -1,5 +1,5 @@
/* pmutil.h -- some helpful utilities for building midi
applications that use PortMidi
/* pmutil.h -- some helpful utilities for building midi
applications that use PortMidi
*/
#ifdef __cplusplus
@ -17,18 +17,18 @@ typedef void PmQueue;
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/,
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
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.
separate cache lines or prevent thrashing on cache lines.
However, this algorithm differs by doing inserts/removals in
units of messages rather than units of machine words. Some
performance improvement might be obtained by not clearing data
@ -40,20 +40,20 @@ typedef void PmQueue;
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.
*/
PMEXPORT PmQueue *Pm_QueueCreate(long num_msgs, int32_t bytes_per_msg);
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
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);
@ -61,7 +61,7 @@ PMEXPORT PmError Pm_Dequeue(PmQueue *queue, void *msg);
/*
Pm_Enqueue() inserts one item into the queue, copying it from msg.
Returns pmNoError if successful and pmBufferOverflow if the queue was
Returns 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);
@ -73,11 +73,11 @@ PMEXPORT PmError Pm_Enqueue(PmQueue *queue, void *msg);
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
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.
returns false, then Pm_Enqueue() is guaranteed to succeed.
Error conditions: Pm_QueueFull() returns pmBadPtr if queue is NULL.
Pm_QueueEmpty() returns FALSE if queue is NULL.
@ -91,12 +91,12 @@ PMEXPORT int Pm_QueueEmpty(PmQueue *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_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.
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
@ -106,14 +106,14 @@ PMEXPORT int Pm_QueueEmpty(PmQueue *queue);
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
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
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

View File

@ -0,0 +1,179 @@
<?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;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
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=\&quot;Debug\&quot;,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;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\&quot;Debug\&quot;,portmidi_dynamic_EXPORTS"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\&quot;Debug\&quot;,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;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
CompileAs="1"
ExceptionHandling="0"
InlineFunctionExpansion="2"
Optimization="2"
RuntimeLibrary="2"
WarningLevel="3"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;,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;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;,portmidi_dynamic_EXPORTS"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;,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="&quot;C:\Program Files\CMake 2.6\bin\cmake.exe&quot; -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;&quot;C:\Program Files\CMake 2.6\share\cmake-2.6\Modules\FindJNI.cmake&quot;;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="&quot;C:\Program Files\CMake 2.6\bin\cmake.exe&quot; -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;&quot;C:\Program Files\CMake 2.6\share\cmake-2.6\Modules\FindJNI.cmake&quot;;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>

View File

@ -0,0 +1,141 @@
<?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;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
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=\&quot;Debug\&quot;"
AssemblerListingLocation="Debug"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="../Debug/portmidi_s.pdb"
/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories="..\pm_common;..\porttime;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\&quot;Debug\&quot;"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\&quot;Debug\&quot;"
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;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
CompileAs="1"
ExceptionHandling="0"
InlineFunctionExpansion="2"
Optimization="2"
RuntimeLibrary="0"
WarningLevel="3"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;"
AssemblerListingLocation="Release"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="../Release/portmidi_s.pdb"
/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories="..\pm_common;..\porttime;&quot;C:\Program Files\Java\jdk1.6.0_16\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_16\include\win32&quot;;"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;"
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>

1137
3rdparty/portmidi/pm_common/portmidi.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -33,20 +33,20 @@ extern "C" {
*/
/*
* The text above constitutes the entire PortMidi license; however,
* The text above constitutes the entire PortMidi license; however,
* the PortMusic community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* requested that these non-binding requests be included along with the
* license above.
*/
/* CHANGELOG FOR PORTMIDI
* (see ../CHANGELOG.txt)
*
* NOTES ON HOST ERROR REPORTING:
* 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
@ -54,27 +54,27 @@ extern "C" {
* 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
* 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
* 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
* 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
* a) host error
* b) host error during callback
* These can occur w/midi input or output devices. (b) can only happen
* 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
@ -84,7 +84,7 @@ extern "C" {
* 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
* 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,
@ -97,7 +97,7 @@ extern "C" {
#include <stdint.h>
#else
#ifndef INT32_DEFINED
// rather than having users install a special .h file for windows,
// 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;
@ -106,17 +106,17 @@ typedef unsigned int uint32_t;
#endif
#endif
//#ifdef _WINDLL
//#define PMEXPORT __declspec(dllexport)
//#else
#define PMEXPORT
//#endif
#ifdef _WINDLL
#define PMEXPORT __declspec(dllexport)
#else
#define PMEXPORT
#endif
#ifndef FALSE
#define FALSE 0
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#define TRUE 1
#endif
/* default size of buffers for sysex transmission: */
@ -124,26 +124,26 @@ typedef unsigned int uint32_t;
/** 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 */
pmHostError = -10000,
pmInvalidDeviceId, /** out of range or
* output device when input is requested or
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 */
pmHostError = -10000,
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
pmInsufficientMemory,
pmBufferTooSmall,
pmBufferOverflow,
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 */
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() */
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;
/**
@ -169,11 +169,11 @@ typedef void PortMidiStream;
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().
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
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.
*/
@ -181,19 +181,19 @@ PMEXPORT int Pm_HasHostError( PortMidiStream * stream );
/** Translate portmidi error number into human readable message.
These strings are constants (set at compile time) so client has
These strings are constants (set at compile time) so client has
no need to allocate storage
*/
PMEXPORT const char *Pm_GetErrorText( PmError errnum );
/** 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.
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
#define PM_HOST_ERROR_MSG_LEN 256u /* any host error msg will occupy less
than this number of characters */
/**
@ -205,12 +205,12 @@ PMEXPORT void Pm_GetHostErrorText(char * msg, unsigned int len);
typedef int PmDeviceID;
#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 */
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 */
} PmDeviceInfo;
@ -221,24 +221,24 @@ 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
java.util.prefs.Preferences.userRoot().node("/PortMidi"); the
preference is set by calling
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
the underlying software system or API used by PortMdi to access
devices and name is the name of the device. These correspond to
devices and name is the name of the device. These correspond to
the interf and name fields of a PmDeviceInfo. (Currently supported
interfaces are "MMSystem" for Win32, "ALSA" for Linux, and
interfaces are "MMSystem" for Win32, "ALSA" for Linux, and
"CoreMIDI" for OS X, so in fact, there is no choice of interface.)
In "interf, name", the strings are actually substrings of
the full interface and name strings. For example, the preference
In "interf, name", the strings are actually substrings of
the full interface and name strings. For example, the preference
"Core, Sport" will match a device with interface "CoreMIDI"
and name "In USB MidiSport 1x1". It will also match "CoreMIDI"
and "In USB MidiSport 2x2". The devices are enumerated in device
@ -248,14 +248,14 @@ 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
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 the PC,
On Linux,
On Linux,
*/
PMEXPORT PmDeviceID Pm_GetDefaultInputDeviceID( void );
@ -271,7 +271,7 @@ 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
@{
*/
@ -306,18 +306,18 @@ PMEXPORT const PmDeviceInfo* Pm_GetDeviceInfo( PmDeviceID id );
outputDriverInfo is never required for correct operation. If not used
outputDriverInfo should be NULL.
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.
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.)
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
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
@ -325,7 +325,7 @@ PMEXPORT const PmDeviceInfo* Pm_GetDeviceInfo( PmDeviceID id );
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
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,
@ -351,20 +351,20 @@ PMEXPORT const PmDeviceInfo* Pm_GetDeviceInfo( PmDeviceID id );
*/
PMEXPORT PmError Pm_OpenInput( PortMidiStream** stream,
PmDeviceID inputDevice,
void *inputDriverInfo,
int32_t bufferSize,
PmTimeProcPtr time_proc,
void *time_info );
PmDeviceID inputDevice,
void *inputDriverInfo,
int32_t bufferSize,
PmTimeProcPtr time_proc,
void *time_info );
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 );
/** @} */
/**
\defgroup grp_events_filters Events and Filters Handling
@ -384,7 +384,7 @@ PMEXPORT PmError Pm_OpenOutput( PortMidiStream** stream,
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)
@ -404,7 +404,7 @@ PMEXPORT PmError Pm_OpenOutput( PortMidiStream** stream,
#define PM_FILT_RESET (1 << 0x0F)
/** filter all real-time messages */
#define PM_FILT_REALTIME (PM_FILT_ACTIVE | PM_FILT_SYSEX | PM_FILT_CLOCK | \
PM_FILT_PLAY | PM_FILT_UNDEFINED | PM_FILT_RESET | PM_FILT_TICK)
PM_FILT_PLAY | PM_FILT_UNDEFINED | PM_FILT_RESET | PM_FILT_TICK)
/** filter note-on and note-off (0x90-0x9F and 0x80-0x8F */
#define PM_FILT_NOTE ((1 << 0x19) | (1 << 0x18))
/** filter channel aftertouch (most midi controllers use this) (0xD0-0xDF)*/
@ -443,7 +443,7 @@ PMEXPORT PmError Pm_SetFilter( PortMidiStream* stream, int32_t filters );
Multiple channels should be OR'd together, like
Pm_SetChannelMask(Pm_Channel(10) | Pm_Channel(11))
Note that channels are numbered 0 to 15 (not 1 to 16). Most
Note that channels are numbered 0 to 15 (not 1 to 16). Most
synthesizer and interfaces number channels starting at 1, but
PortMidi numbers channels starting at 0.
@ -460,10 +460,10 @@ PMEXPORT PmError Pm_SetChannelMask(PortMidiStream *stream, int mask);
any time.
*/
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
(PortMidi attempts to close open streams when the application
exits -- this is particularly difficult under Windows.)
*/
PMEXPORT PmError Pm_Close( PortMidiStream* stream );
@ -473,22 +473,22 @@ PMEXPORT PmError Pm_Close( PortMidiStream* stream );
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
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
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
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
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.
*/
PmError Pm_Synchronize( PortMidiStream* stream );
@ -498,13 +498,13 @@ PmError Pm_Synchronize( PortMidiStream* stream );
Pm_Message() encodes 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_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))
((((data2) << 16) & 0xFF0000) | \
(((data1) << 8) & 0xFF00) | \
((status) & 0xFF))
#define Pm_MessageStatus(msg) ((msg) & 0xFF)
#define Pm_MessageData1(msg) (((msg) >> 8) & 0xFF)
#define Pm_MessageData2(msg) (((msg) >> 16) & 0xFF)
@ -516,71 +516,71 @@ typedef int32_t PmMessage; /**< see PmEvent */
structure carrying 4 bytes of the message, i.e. only the first
PmEvent carries the status byte.
Note that MIDI allows nested messages: the so-called "real-time" MIDI
messages can be inserted into the MIDI byte stream at any location,
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
messages used mainly for timing (see the MIDI spec). PortMidi retains
the order of non-real-time MIDI messages on both input and output, but
messages used mainly for timing (see the MIDI spec). PortMidi retains
the order of non-real-time MIDI messages on both input and output, but
it does not specify exactly how real-time messages are processed. This
is particulary problematic for MIDI input, because the input parser
must either prepare to buffer an unlimited number of sysex message
bytes or to buffer an unlimited number of real-time messages that
is particulary problematic for MIDI input, because the input parser
must either prepare to buffer an unlimited number of sysex message
bytes or to buffer an unlimited number of real-time messages that
arrive embedded in a long sysex message. To simplify things, the input
parser is allowed to pass real-time MIDI messages embedded within a
sysex message, and it is up to the client to detect, process, and
parser is allowed to pass real-time MIDI messages embedded within a
sysex message, and it is up to the client to detect, process, and
remove these messages as they arrive.
When receiving sysex messages, the sysex message is terminated
by either an EOX status byte (anywhere in the 4 byte messages) or
by a non-real-time status byte in the low order byte of the message.
If you get a non-real-time status byte but there was no EOX byte, it
If you get a non-real-time status byte but there was no EOX byte, it
means the sysex message was somehow truncated. This is not
considered an error; e.g., a missing EOX can result from the user
disconnecting a MIDI cable during sysex transmission.
A real-time message can occur within a sysex message. A real-time
message will always occupy a full PmEvent with the status byte in
A real-time message can occur within a sysex message. A real-time
message will always occupy a full PmEvent with the status byte in
the low-order byte of the PmEvent message field. (This implies that
the byte-order of sysex bytes and real-time message bytes may not
be preserved -- for example, if a real-time message arrives after
3 bytes of a sysex message, the real-time message will be delivered
first. The first word of the sysex message will be delivered only
after the 4th byte arrives, filling the 4-byte PmEvent message field.
The timestamp field is observed when the output port is opened with
a non-zero latency. A timestamp of zero means "use the current time",
which in turn means to deliver the message with a delay of
latency (the latency parameter used when opening the output port.)
Do not expect PortMidi to sort data according to timestamps --
messages should be sent in the correct order, and timestamps MUST
Do not expect PortMidi to sort data according to timestamps --
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
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.
On input, the timestamp ideally denotes the arrival time of the
status byte of the message. The first timestamp on sysex message
data will be valid. Subsequent timestamps may denote
when message bytes were actually received, or they may be simply
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.
On input, the timestamp ideally denotes the arrival time of the
status byte of the message. The first timestamp on sysex message
data will be valid. Subsequent timestamps may denote
when message bytes were actually received, or they may be simply
copies of the first timestamp.
Timestamps for nested messages: If a real-time message arrives in
the middle of some other message, it is enqueued immediately with
the timestamp corresponding to its arrival time. The interrupted
non-real-time message or 4-byte packet of sysex data will be enqueued
Timestamps for nested messages: If a real-time message arrives in
the middle of some other message, it is enqueued immediately with
the timestamp corresponding to its arrival time. The interrupted
non-real-time message or 4-byte packet of sysex data will be enqueued
later. The timestamp of interrupted data will be equal to that of
the interrupting real-time message to insure that timestamps are
non-decreasing.
*/
typedef struct {
PmMessage message;
PmTimestamp timestamp;
PmMessage message;
PmTimestamp timestamp;
} PmEvent;
/**
/**
@}
*/
/** \defgroup grp_io Reading and Writing Midi Messages
@ -588,19 +588,19 @@ typedef struct {
*/
/**
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,
of events read. Result is a non-negative number unless an error occurs,
in which case a PmError value will be returned.
Buffer Overflow
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
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
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 buffer managed by PortMidi will be flushed when an overflow
@ -613,20 +613,20 @@ typedef struct {
PMEXPORT int Pm_Read( PortMidiStream *stream, PmEvent *buffer, int32_t length );
/**
Pm_Poll() tests whether input is available,
Pm_Poll() tests whether input is available,
returning TRUE, FALSE, or an error value.
*/
PMEXPORT PmError Pm_Poll( PortMidiStream *stream);
/**
/**
Pm_Write() writes midi data from a buffer. This may contain:
- short messages
or
- 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.
Use Pm_WriteSysEx() to write a sysex message stored as a contiguous
Use Pm_WriteSysEx() to write a sysex message stored as a contiguous
array of bytes.
Sysex data may contain embedded real-time messages.
@ -635,7 +635,7 @@ PMEXPORT PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, int32_t leng
/**
Pm_WriteShort() writes a timestamped non-system-exclusive midi message.
Messages are delivered in order as received, and timestamps must be
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.)
*/

20
3rdparty/portmidi/pm_csharp/README.txt vendored Normal file
View File

@ -0,0 +1,20 @@
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. :-)

View File

@ -0,0 +1,40 @@
#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)];

View File

@ -0,0 +1,31 @@
========================================================================
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.
/////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,5 @@
// 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"

View File

@ -0,0 +1,7 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#pragma once

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,63 @@
// 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

View File

@ -0,0 +1,6 @@
// This is the main DLL file.
#include "stdafx.h"
#include "pm_managed.h"

View File

@ -0,0 +1,53 @@
// 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));
}
};
}

View File

@ -0,0 +1,260 @@
<?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>

View File

@ -0,0 +1,3 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by app.rc

View File

@ -0,0 +1,127 @@
# 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)

11
3rdparty/portmidi/pm_dylib/README.txt vendored Normal file
View File

@ -0,0 +1,11 @@
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.

View File

@ -0,0 +1,158 @@
<?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=\&quot;Debug\&quot;,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=\&quot;Debug\&quot;,portmidi_dynamic_EXPORTS"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\&quot;Debug\&quot;,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=\&quot;Release\&quot;,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=\&quot;Release\&quot;,portmidi_dynamic_EXPORTS"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;,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>

View File

@ -0,0 +1,47 @@
# pm_java
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

BIN
3rdparty/portmidi/pm_java/JavaExe.exe vendored Normal file

Binary file not shown.

48
3rdparty/portmidi/pm_java/README.txt vendored Normal file
View File

@ -0,0 +1,48 @@
README.txt
Roger B. Dannenberg
16 Jun 2009
This directory was 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)
For Mac OS X, you should build the PmDefaults application in Xcode.
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.
---- 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
I found this page by visiting http://software.techrepublic.com.com and
searching in the "Software" category for "JavaExe"
JavaExe works by placing the JavaExe.exe file in the directory with the
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.

Binary file not shown.

View File

@ -0,0 +1,539 @@
package jportmidi;
/* PortMidi is a general class intended for any Java program using
the PortMidi library. It encapsulates JPortMidiApi with a more
object-oriented interface. A single PortMidi object can manage
up to one input stream and one output stream.
This class is not safely callable from multiple threads. It
is the client's responsibility to periodically call the Poll
method which checks for midi input and handles it.
*/
import jportmidi.*;
import jportmidi.JPortMidiApi.*;
public class JPortMidi {
// timecode to send message immediately
public final int NOW = 0;
// midi codes
public final int MIDI_NOTE_OFF = 0x80;
public final int MIDI_NOTE_ON = 0x90;
public final int CTRL_ALL_OFF = 123;
public final int MIDI_PITCH_BEND = 0xE0;
public final int MIDI_CLOCK = 0xF8;
public final int MIDI_CONTROL = 0xB0;
public final int MIDI_PROGRAM = 0xC0;
public final int MIDI_START = 0xFA;
public final int MIDI_STOP = 0xFC;
public final int MIDI_POLY_TOUCH = 0xA0;
public final int MIDI_TOUCH = 0xD0;
// error code -- cannot refresh device list while stream is open:
public final int pmStreamOpen = -5000;
public final int pmOutputNotOpen = -4999;
// access to JPortMidiApi is through a single, global instance
private static JPortMidiApi pm;
// a reference count tracks how many objects have it open
private static int pmRefCount = 0;
private static int openCount = 0;
public int error; // user can check here for error codes
private PortMidiStream input;
private PortMidiStream output;
private PmEvent buffer;
protected int timestamp; // remember timestamp from incoming messages
protected boolean trace = false; // used to print midi msgs for debugging
public JPortMidi() throws JPortMidiException {
if (pmRefCount == 0) {
pm = new JPortMidiApi();
pmRefCount++;
System.out.println("Calling Pm_Initialize");
checkError(pm.Pm_Initialize());
System.out.println("Called Pm_Initialize");
}
buffer = new PmEvent();
}
public boolean getTrace() { return trace; }
// set the trace flag and return previous value
public boolean setTrace(boolean flag) {
boolean previous = trace;
trace = flag;
return previous;
}
// WARNING: you must not call this if any devices are open
public void refreshDeviceLists()
throws JPortMidiException
{
if (openCount > 0) {
throw new JPortMidiException(pmStreamOpen,
"RefreshDeviceLists called while stream is open");
}
checkError(pm.Pm_Terminate());
checkError(pm.Pm_Initialize());
}
// there is no control over when/whether this is called, but it seems
// to be a good idea to close things when this object is collected
public void finalize() {
if (input != null) {
error = pm.Pm_Close(input);
}
if (input != null) {
int rslt = pm.Pm_Close(output);
// we may lose an error code from closing output, but don't
// lose any real error from closing input...
if (error == pm.pmNoError) error = rslt;
}
pmRefCount--;
if (pmRefCount == 0) {
error = pm.Pm_Terminate();
}
}
int checkError(int err) throws JPortMidiException
{
// note that Pm_Read and Pm_Write return positive result values
// which are not errors, so compare with >=
if (err >= pm.pmNoError) return err;
if (err == pm.pmHostError) {
throw new JPortMidiException(err, pm.Pm_GetHostErrorText());
} else {
throw new JPortMidiException(err, pm.Pm_GetErrorText(err));
}
}
// ******** ACCESS TO TIME ***********
public void timeStart(int resolution) throws JPortMidiException {
checkError(pm.Pt_TimeStart(resolution));
}
public void timeStop() throws JPortMidiException {
checkError(pm.Pt_TimeStop());
}
public int timeGet() {
return pm.Pt_Time();
}
public boolean timeStarted() {
return pm.Pt_TimeStarted();
}
// ******* QUERY DEVICE INFORMATION *********
public int countDevices() throws JPortMidiException {
return checkError(pm.Pm_CountDevices());
}
public int getDefaultInputDeviceID() throws JPortMidiException {
return checkError(pm.Pm_GetDefaultInputDeviceID());
}
public int getDefaultOutputDeviceID() throws JPortMidiException {
return checkError(pm.Pm_GetDefaultOutputDeviceID());
}
public String getDeviceInterf(int i) {
return pm.Pm_GetDeviceInterf(i);
}
public String getDeviceName(int i) {
return pm.Pm_GetDeviceName(i);
}
public boolean getDeviceInput(int i) {
return pm.Pm_GetDeviceInput(i);
}
public boolean getDeviceOutput(int i) {
return pm.Pm_GetDeviceOutput(i);
}
// ********** MIDI INTERFACE ************
public boolean isOpenInput() {
return input != null;
}
public void openInput(int inputDevice, int bufferSize)
throws JPortMidiException
{
openInput(inputDevice, "", bufferSize);
}
public void openInput(int inputDevice, String inputDriverInfo, int bufferSize)
throws JPortMidiException
{
if (isOpenInput()) pm.Pm_Close(input);
else input = new PortMidiStream();
if (trace) {
System.out.println("openInput " + getDeviceName(inputDevice));
}
checkError(pm.Pm_OpenInput(input, inputDevice,
inputDriverInfo, bufferSize));
// if no exception, then increase count of open streams
openCount++;
}
public boolean isOpenOutput() {
return output != null;
}
public void openOutput(int outputDevice, int bufferSize, int latency)
throws JPortMidiException
{
openOutput(outputDevice, "", bufferSize, latency);
}
public void openOutput(int outputDevice, String outputDriverInfo,
int bufferSize, int latency) throws JPortMidiException {
if (isOpenOutput()) pm.Pm_Close(output);
else output = new PortMidiStream();
if (trace) {
System.out.println("openOutput " + getDeviceName(outputDevice));
}
checkError(pm.Pm_OpenOutput(output, outputDevice, outputDriverInfo,
bufferSize, latency));
// if no exception, then increase count of open streams
openCount++;
}
public void setFilter(int filters) throws JPortMidiException {
if (input == null) return; // no effect if input not open
checkError(pm.Pm_SetFilter(input, filters));
}
public void setChannelMask(int mask) throws JPortMidiException {
if (input == null) return; // no effect if input not open
checkError(pm.Pm_SetChannelMask(input, mask));
}
public void abort() throws JPortMidiException {
if (output == null) return; // no effect if output not open
checkError(pm.Pm_Abort(output));
}
// In keeping with the idea that this class represents an input and output,
// there are separate Close methods for input and output streams, avoiding
// the need for clients to ever deal directly with a stream object
public void closeInput() throws JPortMidiException {
if (input == null) return; // no effect if input not open
checkError(pm.Pm_Close(input));
input = null;
openCount--;
}
public void closeOutput() throws JPortMidiException {
if (output == null) return; // no effect if output not open
checkError(pm.Pm_Close(output));
output = null;
openCount--;
}
// Poll should be called by client to process input messages (if any)
public void poll() throws JPortMidiException {
if (input == null) return; // does nothing until input is opened
while (true) {
int rslt = pm.Pm_Read(input, buffer);
checkError(rslt);
if (rslt == 0) return; // no more messages
handleMidiIn(buffer);
}
}
public void writeShort(int when, int msg) throws JPortMidiException {
if (output == null)
throw new JPortMidiException(pmOutputNotOpen,
"Output stream not open");
if (trace) {
System.out.println("writeShort: " + Integer.toHexString(msg));
}
checkError(pm.Pm_WriteShort(output, when, msg));
}
public void writeSysEx(int when, byte msg[]) throws JPortMidiException {
if (output == null)
throw new JPortMidiException(pmOutputNotOpen,
"Output stream not open");
if (trace) {
System.out.print("writeSysEx: ");
for (int i = 0; i < msg.length; i++) {
System.out.print(Integer.toHexString(msg[i]));
}
System.out.print("\n");
}
checkError(pm.Pm_WriteSysEx(output, when, msg));
}
public int midiChanMessage(int chan, int status, int data1, int data2) {
return (((data2 << 16) & 0xFF0000) |
((data1 << 8) & 0xFF00) |
(status & 0xF0) |
(chan & 0xF));
}
public int midiMessage(int status, int data1, int data2) {
return ((((data2) << 16) & 0xFF0000) |
(((data1) << 8) & 0xFF00) |
((status) & 0xFF));
}
public void midiAllOff(int channel) throws JPortMidiException {
midiAllOff(channel, NOW);
}
public void midiAllOff(int chan, int when) throws JPortMidiException {
writeShort(when, midiChanMessage(chan, MIDI_CONTROL, CTRL_ALL_OFF, 0));
}
public void midiPitchBend(int chan, int value) throws JPortMidiException {
midiPitchBend(chan, value, NOW);
}
public void midiPitchBend(int chan, int value, int when)
throws JPortMidiException {
writeShort(when,
midiChanMessage(chan, MIDI_PITCH_BEND, value, value >> 7));
}
public void midiClock() throws JPortMidiException {
midiClock(NOW);
}
public void midiClock(int when) throws JPortMidiException {
writeShort(when, midiMessage(MIDI_CLOCK, 0, 0));
}
public void midiControl(int chan, int control, int value)
throws JPortMidiException {
midiControl(chan, control, value, NOW);
}
public void midiControl(int chan, int control, int value, int when)
throws JPortMidiException {
writeShort(when, midiChanMessage(chan, MIDI_CONTROL, control, value));
}
public void midiNote(int chan, int pitch, int vel)
throws JPortMidiException {
midiNote(chan, pitch, vel, NOW);
}
public void midiNote(int chan, int pitch, int vel, int when)
throws JPortMidiException {
writeShort(when, midiChanMessage(chan, MIDI_NOTE_ON, pitch, vel));
}
public void midiProgram(int chan, int program)
throws JPortMidiException {
midiProgram(chan, program, NOW);
}
public void midiProgram(int chan, int program, int when)
throws JPortMidiException {
writeShort(when, midiChanMessage(chan, MIDI_PROGRAM, program, 0));
}
public void midiStart()
throws JPortMidiException {
midiStart(NOW);
}
public void midiStart(int when)
throws JPortMidiException {
writeShort(when, midiMessage(MIDI_START, 0, 0));
}
public void midiStop()
throws JPortMidiException {
midiStop(NOW);
}
public void midiStop(int when)
throws JPortMidiException {
writeShort(when, midiMessage(MIDI_STOP, 0, 0));
}
public void midiPolyTouch(int chan, int key, int value)
throws JPortMidiException {
midiPolyTouch(chan, key, value, NOW);
}
public void midiPolyTouch(int chan, int key, int value, int when)
throws JPortMidiException {
writeShort(when, midiChanMessage(chan, MIDI_POLY_TOUCH, key, value));
}
public void midiTouch(int chan, int value)
throws JPortMidiException {
midiTouch(chan, value, NOW);
}
public void midiTouch(int chan, int value, int when)
throws JPortMidiException {
writeShort(when, midiChanMessage(chan, MIDI_TOUCH, value, 0));
}
// ****** now we implement the message handlers ******
// an array for incoming sysex messages that can grow.
// The downside is that after getting a message, we
private byte sysexBuffer[] = null;
private int sysexBufferIndex = 0;
void sysexBufferReset() {
sysexBufferIndex = 0;
if (sysexBuffer == null) sysexBuffer = new byte[256];
}
void sysexBufferCheck() {
if (sysexBuffer.length < sysexBufferIndex + 4) {
byte bigger[] = new byte[sysexBuffer.length * 2];
for (int i = 0; i < sysexBufferIndex; i++) {
bigger[i] = sysexBuffer[i];
}
sysexBuffer = bigger;
}
// now we have space to write some bytes
}
// call this to insert Sysex and EOX status bytes
// call sysexBufferAppendBytes to insert anything else
void sysexBufferAppendStatus(byte status) {
sysexBuffer[sysexBufferIndex++] = status;
}
void sysexBufferAppendBytes(int msg, int len) {
for (int i = 0; i < len; i++) {
byte b = (byte) msg;
if ((msg & 0x80) != 0) {
if (b == 0xF7) { // end of sysex
sysexBufferAppendStatus(b);
sysex(sysexBuffer, sysexBufferIndex);
return;
}
// recursively handle embedded real-time messages
PmEvent buffer = new PmEvent();
buffer.timestamp = timestamp;
buffer.message = b;
handleMidiIn(buffer);
} else {
sysexBuffer[sysexBufferIndex++] = b;
}
msg = msg >> 8;
}
}
void sysexBegin(int msg) {
sysexBufferReset(); // start from 0, we have at least 256 bytes now
sysexBufferAppendStatus((byte) (msg & 0xFF)); // first byte is special
sysexBufferAppendBytes(msg >> 8, 3); // process remaining bytes
}
public void handleMidiIn(PmEvent buffer)
{
if (trace) {
System.out.println("handleMidiIn: " +
Integer.toHexString(buffer.message));
}
// rather than pass timestamps to every handler, where typically
// timestamps are ignored, just save the timestamp as a member
// variable where methods can access it if they want it
timestamp = buffer.timestamp;
int status = buffer.message & 0xFF;
if (status < 0x80) {
sysexBufferCheck(); // make enough space
sysexBufferAppendBytes(buffer.message, 4); // process 4 bytes
return;
}
int command = status & 0xF0;
int channel = status & 0x0F;
int data1 = (buffer.message >> 8) & 0xFF;
int data2 = (buffer.message >> 16) & 0xFF;
switch (command) {
case MIDI_NOTE_OFF:
noteOff(channel, data1, data2); break;
case MIDI_NOTE_ON:
if (data2 > 0) {
noteOn(channel, data1, data2); break;
} else {
noteOff(channel, data1);
}
break;
case MIDI_CONTROL:
control(channel, data1, data2); break;
case MIDI_POLY_TOUCH:
polyTouch(channel, data1, data2); break;
case MIDI_TOUCH:
touch(channel, data1); break;
case MIDI_PITCH_BEND:
pitchBend(channel, (data1 + (data2 << 7)) - 8192); break;
case MIDI_PROGRAM:
program(channel, data1); break;
case 0xF0:
switch (channel) {
case 0: sysexBegin(buffer.message); break;
case 1: mtcQuarterFrame(data1);
case 2: songPosition(data1 + (data2 << 7)); break;
case 3: songSelect(data1); break;
case 4: /* unused */ break;
case 5: /* unused */ break;
case 6: tuneRequest(); break;
case 7: sysexBufferAppendBytes(buffer.message, buffer.message); break;
case 8: clock(); break;
case 9: tick(); break;
case 0xA: clockStart(); break;
case 0xB: clockContinue(); break;
case 0xC: clockStop(); break;
case 0xD: /* unused */ break;
case 0xE: activeSense(); break;
case 0xF: reset(); break;
}
}
}
// the value ranges from +8181 to -8192. The interpretation is
// synthesizer dependent. Often the range is +/- one whole step
// (two semitones), but the range is usually adjustable within
// the synthesizer.
void pitchBend(int channel, int value) { return; }
void control(int channel, int control, int value) { return; }
void noteOn(int channel, int pitch, int velocity) { return; }
// you can handle velocity in note-off if you want, but the default
// is to drop the velocity and call the simpler NoteOff handler
void noteOff(int channel, int pitch, int velocity) {
noteOff(channel, pitch);
}
// if the subclass wants to implement NoteOff with velocity, it
// should override the following to make sure all NoteOffs are handled
void noteOff(int channel, int pitch) { return; }
void program(int channel, int program) { return; }
// the byte array may be bigger than the message, length tells how
// many bytes in the array are part of the message
void sysex(byte[] msg, int length) { return; }
void polyTouch(int channel, int key, int value) { return; }
void touch(int channel, int value) { return; }
void mtcQuarterFrame(int value) { return; }
// the value is a 14-bit integer representing 16th notes
void songPosition(int value) { return; }
void songSelect(int value) { return; }
void tuneRequest() { return; }
void clock() { return; } // represents 1/24th of a quarter note
void tick() { return; } // represents 10ms
void clockStart() { return; }
void clockStop() { return; }
void clockContinue() { return; }
void activeSense() { return; }
void reset() { return; }
}

View File

@ -0,0 +1,117 @@
package jportmidi;
public class JPortMidiApi {
public static class PortMidiStream {
private long address;
}
public static class PmEvent {
public int message;
public int timestamp;
}
// PmError bindings
public final int pmNoError = 0;
public final int pmNoData = 0;
public final int pmGotData = -1;
public final int pmHostError = -10000;
public final int pmInvalidDeviceId = -9999;
public final int pmInsufficientMemory = -9998;
public final int pmBufferTooSmall = -9997;
public final int pmBufferOverflow = -9996;
public final int pmBadPtr = -9995;
public final int pmBadData = -9994;
public final int pmInternalError = -9993;
public final int pmBufferMaxSize = -9992;
static public native int Pm_Initialize();
static public native int Pm_Terminate();
static public native int Pm_HasHostError(PortMidiStream stream);
static public native String Pm_GetErrorText(int errnum);
static public native String Pm_GetHostErrorText();
final int pmNoDevice = -1;
static public native int Pm_CountDevices();
static public native int Pm_GetDefaultInputDeviceID();
static public native int Pm_GetDefaultOutputDeviceID();
static public native String Pm_GetDeviceInterf(int i);
static public native String Pm_GetDeviceName(int i);
static public native boolean Pm_GetDeviceInput(int i);
static public native boolean Pm_GetDeviceOutput(int i);
static public native int Pm_OpenInput(PortMidiStream stream,
int inputDevice,
String inputDriverInfo,
int bufferSize);
static public native int Pm_OpenOutput(PortMidiStream stream,
int outputDevice,
String outnputDriverInfo,
int bufferSize,
int latency);
final static public int PM_FILT_ACTIVE = (1 << 0x0E);
final static public int PM_FILT_SYSEX = (1 << 0x00);
final static public int PM_FILT_CLOCK = (1 << 0x08);
final static public int PM_FILT_PLAY =
(1 << 0x0A) | (1 << 0x0C) | (1 << 0x0B);
final static public int PM_FILT_TICK = (1 << 0x09);
final static public int PM_FILT_FD = (1 << 0x0D);
final static public int PM_FILT_UNDEFINED = PM_FILT_FD;
final static public int PM_FILT_RESET = (1 << 0x0F);
final static public int PM_FILT_REALTIME =
PM_FILT_ACTIVE | PM_FILT_SYSEX | PM_FILT_CLOCK;
final static public int PM_FILT_NOTE = (1 << 0x19) | (1 << 0x18);
final static public int PM_FILT_CHANNEL_AFTERTOUCH = (1 << 0x1D);
final static public int PM_FILT_POLY_AFTERTOUCH = (1 << 0x1A);
final static public int PM_FILT_AFTERTOUCH =
(PM_FILT_CHANNEL_AFTERTOUCH | PM_FILT_POLY_AFTERTOUCH);
final static public int PM_FILT_PROGRAM = (1 << 0x1C);
final static public int PM_FILT_CONTROL = (1 << 0x1B);
final static public int PM_FILT_PITCHBEND = (1 << 0x1E);
final static public int PM_FILT_MTC = (1 << 0x01);
final static public int PM_FILT_SONG_POSITION = (1 << 0x02);
final static public int PM_FILT_SONG_SELECT = (1 << 0x03);
final static public int PM_FILT_TUNE = (1 << 0x06);
final static public int PM_FILT_SYSTEMCOMMON =
(PM_FILT_MTC | PM_FILT_SONG_POSITION |
PM_FILT_SONG_SELECT | PM_FILT_TUNE);
static public native int Pm_SetFilter(PortMidiStream stream, int filters);
static public int Pm_Channel(int channel) { return 1 << channel; }
final static public native int Pm_SetChannelMask(PortMidiStream stream,
int mask);
final static public native int Pm_Abort(PortMidiStream stream);
final static public native int Pm_Close(PortMidiStream stream);
static public int Pm_Message(int status, int data1, int data2) {
return (((data2 << 16) & 0xFF0000) |
((data1 << 8) & 0xFF00) |
(status & 0xFF));
}
static public int Pm_MessageStatus(int msg) {
return msg & 0xFF;
}
static public int Pm_MessageData1(int msg) {
return (msg >> 8) & 0xFF;
}
static public int Pm_MessageData2(int msg) {
return (msg >> 16) & 0xFF;
}
// only supports reading one buffer at a time
static public native int Pm_Read(PortMidiStream stream, PmEvent buffer);
static public native int Pm_Poll(PortMidiStream stream);
// only supports writing one buffer at a time
static public native int Pm_Write(PortMidiStream stream, PmEvent buffer);
static public native int Pm_WriteShort(PortMidiStream stream,
int when, int msg);
static public native int Pm_WriteSysEx(PortMidiStream stream,
int when, byte msg[]);
public final int ptNoError = 0;
public final int ptAlreadyStarted = -10000;
public final int ptAlreadyStopped = -9999;
public final int PtInsufficientMemory = -9998;
static public native int Pt_TimeStart(int resolution);
static public native int Pt_TimeStop();
static public native int Pt_Time();
static public native boolean Pt_TimeStarted();
static {
System.out.println("Loading pmjni");
System.loadLibrary("pmjni");
System.out.println("done loading pmjni");
}
}

View File

@ -0,0 +1,12 @@
// JPortMidiException -- thrown by JPortMidi methods
package jportmidi;
public class JPortMidiException extends Exception {
public int error = 0;
public JPortMidiException(int err, String msg) {
super(msg);
error = err;
}
}

26
3rdparty/portmidi/pm_java/mac-make.sh vendored Normal file
View File

@ -0,0 +1,26 @@
# 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"

47
3rdparty/portmidi/pm_java/make.bat vendored Normal file
View File

@ -0,0 +1,47 @@
@echo off
rem Compile the java PortMidi interface classes.
javac jportmidi/*.java
rem Compile the pmdefaults application.
javac -classpath . pmdefaults/*.java
rem Temporarily copy the portmusic_logo.png file here to add to the jar file.
copy pmdefaults\portmusic_logo.png . > nul
rem Create a directory to hold the distribution.
mkdir win32
rem Attempt to copy the interface DLL to the distribution directory.
if exist "..\release\pmjni.dll" goto have-dll
echo "ERROR: pmjni.dll not found!"
exit /b 1
:have-dll
copy "..\release\pmjni.dll" win32\pmjni.dll > nul
rem Create a java archive (jar) file of the distribution.
jar cmf pmdefaults\manifest.txt win32\pmdefaults.jar pmdefaults\*.class portmusic_logo.png jportmidi\*.class
rem Clean up the temporary image file now that it is in the jar file.
del portmusic_logo.png
rem Copy the java execution code obtained from
rem http://devwizard.free.fr/html/en/JavaExe.html to the distribution
rem directory. The copy also renames the file to our desired executable
rem name.
copy JavaExe.exe win32\pmdefaults.exe > nul
rem Integrate the icon into the executable using UpdateRsrcJavaExe from
rem http://devwizard.free.fr
UpdateRsrcJavaExe -run -exe=win32\pmdefaults.exe -ico=pmdefaults\pmdefaults.ico
rem Copy the 32-bit windows read me file to the distribution directory.
copy pmdefaults\readme-win32.txt win32\README.txt > nul
rem Copy the license file to the distribution directory.
copy pmdefaults\pmdefaults-license.txt win32\license.txt > nul
echo "You can run pmdefaults.exe in win32"

View File

@ -0,0 +1,44 @@
; 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

View File

@ -0,0 +1,11 @@
// PmDefaults -- a small application to set PortMIDI default input/output
package pmdefaults;
public class PmDefaults {
public static void main(String[] args) {
System.out.println("starting main");
new PmDefaultsFrame("PortMIDI Setup");
}
}

View File

@ -0,0 +1,428 @@
// PmDefaults -- a small application to set PortMIDI default input/output
/* Implementation notes:
This program uses PortMidi to enumerate input and output devices and also
to send output messages to test output devices and
to receive input messages to test input devices.
*/
package pmdefaults;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math.*;
import jportmidi.*;
import jportmidi.JPortMidiApi.*;
import java.util.ArrayList;
import java.util.prefs.*;
import java.net.*;
public class PmDefaultsFrame extends JFrame
implements ActionListener, ComponentListener {
// This class extends JPortMidi in order to override midi input handling
// In this case, midi input simply blinks the activity light
public class JPM extends JPortMidi {
ActivityLight light;
PmDefaultsFrame frame;
int lightTime;
boolean lightState;
int now; // current time in ms
final int HALF_BLINK_PERIOD = 250; // ms
public JPM(ActivityLight al, PmDefaultsFrame df)
throws JPortMidiException {
light = al;
frame = df;
lightTime = 0;
lightState = false; // meaning "off"
now = 0;
}
public void poll(int ms) throws JPortMidiException {
// blink the light. lightState is initially false (off).
// to blink the light, set lightState to true and lightTime
// to now + 0.25s; turn on light
// now > ligntTime && lightState => set lightTime = now + 0.25s;
// set lightState = false
// turn off light
// light can be blinked again when now > lightTime && !lightState
now = ms;
if (now > lightTime && lightState) {
lightTime = now + HALF_BLINK_PERIOD;
lightState = false;
light.setState(false);
}
super.poll();
}
public void handleMidiIn(PmEvent buffer) {
System.out.println("midi in: now " + now +
" lightTime " + lightTime +
" lightState " + lightState);
if (now > lightTime && !lightState) {
lightState = true;
lightTime = now + HALF_BLINK_PERIOD;
light.setState(true);
}
}
}
public class ActivityLight extends JPanel {
Color color;
final Color OFF_COLOR = Color.BLACK;
final Color ON_COLOR = Color.GREEN;
ActivityLight() {
super();
Dimension size = new Dimension(50, 25);
setMaximumSize(size);
setPreferredSize(size);
setMinimumSize(size);
color = OFF_COLOR;
System.out.println("ActivityLight " + getSize());
}
public void setState(boolean on) {
color = (on ? ON_COLOR : OFF_COLOR);
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g); // paint background
g.setColor(color);
int x = (getWidth() / 2) - 5;
int y = (getHeight() / 2) - 5;
g.fillOval(x, y, 10, 10);
g.setColor(OFF_COLOR);
g.drawOval(x, y, 10, 10);
}
}
private JLabel inputLabel;
private JComboBox inputSelection;
// inputIds maps from the index of an item in inputSelection to the
// device ID. Used to open the selected device.
private ArrayList<Integer> inputIds;
private ActivityLight inputActivity;
private JLabel outputLabel;
private JComboBox outputSelection;
// analogous to inputIds, outputIds maps selection index to device ID
private ArrayList<Integer> outputIds;
private JButton testButton;
private JButton refreshButton;
private JButton updateButton;
private JButton closeButton;
private JLabel logo;
private JPM jpm;
private Timer timer;
public void componentResized(ComponentEvent e) {
System.out.println(e);
if (e.getComponent() == this) {
Insets insets = getInsets();
Dimension dim = getSize();
layoutComponents(dim.width - insets.left - insets.right,
dim.height - insets.top - insets.bottom);
}
}
public void componentMoved(ComponentEvent e) {
System.out.println(e);
}
public void componentHidden(ComponentEvent e) {
System.out.println(e);
}
public void componentShown(ComponentEvent e) {
System.out.println(e);
}
PmDefaultsFrame(String title) {
super(title);
initComponents();
System.out.println("initComponents returned\n");
pack(); // necessary before calling getInsets();
// initially, only width matters to layout:
layoutComponents(550, 300);
System.out.println("after layout, pref " + getPreferredSize());
// now, based on layout-computed preferredSize, set the Frame size
Insets insets = getInsets();
Dimension dim = getPreferredSize();
dim.width += (insets.left + insets.right);
dim.height += (insets.top + insets.bottom);
setSize(dim);
System.out.println("size" + getPreferredSize());
addComponentListener(this);
timer = new Timer(50 /* ms */, this);
timer.addActionListener(this);
try {
jpm = new JPM(inputActivity, this);
jpm.setTrace(true);
loadDeviceChoices();
timer.start(); // don't start timer if there's an error
} catch(JPortMidiException e) {
System.out.println(e);
}
}
void openInputSelection() {
int id = inputSelection.getSelectedIndex();
if (id < 0) return; // nothing selected
id = (Integer) (inputIds.get(id)); // map to device ID
// openInput will close any previously open input stream
try {
jpm.openInput(id, 100); // buffer size hopes to avoid overflow
} catch(JPortMidiException e) {
System.out.println(e);
}
}
// make a string to put into preferences describing this device
String makePrefName(int id) {
String name = jpm.getDeviceName(id);
String interf = jpm.getDeviceInterf(id);
// the syntax requires comma-space separator (see portmidi.h)
return interf + ", " + name;
}
public void savePreferences() {
Preferences prefs = Preferences.userRoot().node("/PortMidi");
int id = outputSelection.getSelectedIndex();
if (id >= 0) {
String prefName = makePrefName(outputIds.get(id));
System.out.println("output pref: " + prefName);
prefs.put("PM_RECOMMENDED_OUTPUT_DEVICE", prefName);
}
id = inputSelection.getSelectedIndex();
if (id >= 0) {
String prefName = makePrefName(inputIds.get(id));
System.out.println("input pref: " + prefName);
prefs.put("PM_RECOMMENDED_INPUT_DEVICE", prefName);
}
try {
prefs.flush();
} catch(BackingStoreException e) {
System.out.println(e);
}
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
try {
if (source == timer) {
jpm.poll(jpm.timeGet());
} else if (source == refreshButton) {
if (jpm.isOpenInput()) jpm.closeInput();
if (jpm.isOpenOutput()) jpm.closeOutput();
jpm.refreshDeviceLists();
loadDeviceChoices();
} else if (source == updateButton) {
savePreferences();
} else if (source == closeButton) {
if (jpm.isOpenInput()) jpm.closeInput();
if (jpm.isOpenOutput()) jpm.closeOutput();
} else if (source == testButton) {
sendTestMessages();
} else if (source == inputSelection) {
// close previous selection and open new one
openInputSelection();
} else if (source == outputSelection) {
jpm.closeOutput(); // remains closed until Test button reopens
}
} catch(JPortMidiException ex) {
System.out.println(ex);
}
};
private void layoutComponents(int width, int height) {
// I tried to do this with various layout managers, but failed
// It seems pretty straightforward to just compute locations and
// sizes.
int gap = 2; // pixel separation between components
int indent = 20;
int y = gap;
// inputLabel goes in upper left
inputLabel.setLocation(0, y);
inputLabel.setSize(inputLabel.getPreferredSize());
// inputSelection goes below and indented, width based on panel
y += inputLabel.getHeight() + gap;
inputSelection.setLocation(indent, y);
// size of inputSelection must leave room at right for inputButton
// (in fact, inputActivity goes there, but we'll make inputSelection
// and outputSelection the same size, based on leaving room for
// testButton, which is larger than inputActivity.)
Dimension dim = inputSelection.getPreferredSize();
Dimension dimButton = testButton.getPreferredSize();
// make button and selection the same height so they align
dim.height = dimButton.height = Math.max(dim.height, dimButton.height);
// make selection width as wide as possible
dim.width = width - indent - dimButton.width - gap;
inputSelection.setSize(dim);
// inputActivity goes to the right of inputSelection
inputActivity.setLocation(indent + dim.width + gap, y);
// square size to match the height of inputSelection
inputActivity.setSize(dim.height, dim.height);
// outputLabel goes below
y += dim.height + gap;
outputLabel.setLocation(0, y);
outputLabel.setSize(outputLabel.getPreferredSize());
// outputSelection is like inputSelection
y += outputLabel.getHeight() + gap;
outputSelection.setLocation(indent, y);
outputSelection.setSize(dim);
// testButton is like inputActivity
testButton.setLocation(indent + dim.width + gap, y);
testButton.setSize(dimButton);
System.out.println("button " + dimButton + " selection " + dim);
// refreshButton is below
y += dim.height + gap;
dim = refreshButton.getPreferredSize();
refreshButton.setLocation(indent, y);
refreshButton.setSize(dim);
// updateButton to right of refreshButton
int x = indent + dim.width + gap;
updateButton.setLocation(x, y);
dim = updateButton.getPreferredSize();
updateButton.setSize(dim);
// closeButton to right of updateButton
x += dim.width + gap;
closeButton.setLocation(x, y);
dim = closeButton.getPreferredSize();
closeButton.setSize(dim);
// place logo centered at bottom
y += dim.height + gap;
logo.setLocation((width - logo.getWidth()) / 2,
height - gap - logo.getHeight());
// set overall size
y += logo.getHeight() + gap;
System.out.println("computed best size " + width + ", " + y);
setPreferredSize(new Dimension(width, y));
}
private void initComponents() {
Container wholePanel = getContentPane();
wholePanel.setLayout(null);
setLayout(null);
inputLabel = new JLabel();
inputLabel.setText("Default Input");
wholePanel.add(inputLabel);
inputSelection = new JComboBox();
inputSelection.addActionListener(this);
inputSelection.setLocation(20, 30);
inputSelection.setSize(inputSelection.getPreferredSize());
System.out.println("Adding inputSelection to panel");
wholePanel.add(inputSelection);
inputIds = new ArrayList<Integer>();
inputActivity = new ActivityLight();
wholePanel.add(inputActivity);
outputLabel = new JLabel();
outputLabel.setText("Default Output");
wholePanel.add(outputLabel);
outputSelection = new JComboBox();
outputSelection.addActionListener(this);
wholePanel.add(outputSelection);
testButton = new JButton();
testButton.setText("Test");
testButton.addActionListener(this);
wholePanel.add(testButton);
outputIds = new ArrayList<Integer>();
refreshButton = new JButton();
refreshButton.setText("Refresh Device Lists");
System.out.println("refresh " + refreshButton.getPreferredSize());
System.out.println(getLayout());
refreshButton.addActionListener(this);
wholePanel.add(refreshButton);
updateButton = new JButton();
updateButton.setText("Update Preferences");
updateButton.setSize(refreshButton.getPreferredSize());
updateButton.addActionListener(this);
wholePanel.add(updateButton);
closeButton = new JButton();
closeButton.setText("Close/Release Ports");
closeButton.setSize(refreshButton.getPreferredSize());
closeButton.addActionListener(this);
wholePanel.add(closeButton);
// load the logo from the jar file (on Linux and Windows)
ClassLoader cldr = this.getClass().getClassLoader();
ImageIcon icon;
URL logoURL = cldr.getResource("portmusic_logo.png");
if (logoURL == null) {
// on Mac, load from bundle
icon = new ImageIcon("portmusic_logo.png");
} else {
icon = new ImageIcon(logoURL);
}
logo = new JLabel(icon);
logo.setSize(logo.getPreferredSize());
wholePanel.add(logo);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
void loadDeviceChoices() throws JPortMidiException {
// initialize and load combo boxes with device descriptions
int n = jpm.countDevices();
inputSelection.removeAllItems();
inputIds.clear();
outputSelection.removeAllItems();
outputIds.clear();
for (int i = 0; i < n; i++) {
String interf = jpm.getDeviceInterf(i);
String name = jpm.getDeviceName(i);
System.out.println("name " + name);
String selection = name + " [" + interf + "]";
if (jpm.getDeviceInput(i)) {
inputIds.add(i);
inputSelection.addItem(selection);
} else {
outputIds.add(i);
outputSelection.addItem(selection);
}
}
}
void sendTestMessages() {
try {
if (!jpm.isOpenOutput()) {
int id = outputSelection.getSelectedIndex();
if (id < 0) return; // nothing selected
id = (Integer) (outputIds.get(id));
System.out.println("calling openOutput");
jpm.openOutput(id, 10, 10);
}
jpm.midiNote(0, 67, 100); // send an A (440)
jpm.midiNote(0, 67, 0, jpm.timeGet() + 500);
} catch(JPortMidiException e) {
System.out.println(e);
}
}
}

View File

@ -0,0 +1,21 @@
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().
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
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

View File

@ -0,0 +1 @@
Main-Class: pmdefaults/PmDefaults

View File

@ -0,0 +1 @@
java -jar /usr/share/java/pmdefaults.jar > /dev/null

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

View File

@ -0,0 +1,37 @@
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
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights 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 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 text above constitutes the entire PortMidi license; however,
the PortMusic community also makes the following non-binding requests:
Any person wishing to distribute modifications to the Software is
requested to send the modifications to the original developer so that
they can be incorporated into the canonical version. It is also
requested that these non-binding requests be included along with the
license above.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

View File

@ -0,0 +1,11 @@
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.

View File

@ -0,0 +1,293 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jportmidi_JPortMidiApi */
#ifndef _Included_jportmidi_JPortMidiApi
#define _Included_jportmidi_JPortMidiApi
#ifdef __cplusplus
extern "C" {
#endif
#undef jportmidi_JPortMidiApi_PM_FILT_ACTIVE
#define jportmidi_JPortMidiApi_PM_FILT_ACTIVE 16384L
#undef jportmidi_JPortMidiApi_PM_FILT_SYSEX
#define jportmidi_JPortMidiApi_PM_FILT_SYSEX 1L
#undef jportmidi_JPortMidiApi_PM_FILT_CLOCK
#define jportmidi_JPortMidiApi_PM_FILT_CLOCK 256L
#undef jportmidi_JPortMidiApi_PM_FILT_PLAY
#define jportmidi_JPortMidiApi_PM_FILT_PLAY 7168L
#undef jportmidi_JPortMidiApi_PM_FILT_TICK
#define jportmidi_JPortMidiApi_PM_FILT_TICK 512L
#undef jportmidi_JPortMidiApi_PM_FILT_FD
#define jportmidi_JPortMidiApi_PM_FILT_FD 8192L
#undef jportmidi_JPortMidiApi_PM_FILT_UNDEFINED
#define jportmidi_JPortMidiApi_PM_FILT_UNDEFINED 8192L
#undef jportmidi_JPortMidiApi_PM_FILT_RESET
#define jportmidi_JPortMidiApi_PM_FILT_RESET 32768L
#undef jportmidi_JPortMidiApi_PM_FILT_REALTIME
#define jportmidi_JPortMidiApi_PM_FILT_REALTIME 16641L
#undef jportmidi_JPortMidiApi_PM_FILT_NOTE
#define jportmidi_JPortMidiApi_PM_FILT_NOTE 50331648L
#undef jportmidi_JPortMidiApi_PM_FILT_CHANNEL_AFTERTOUCH
#define jportmidi_JPortMidiApi_PM_FILT_CHANNEL_AFTERTOUCH 536870912L
#undef jportmidi_JPortMidiApi_PM_FILT_POLY_AFTERTOUCH
#define jportmidi_JPortMidiApi_PM_FILT_POLY_AFTERTOUCH 67108864L
#undef jportmidi_JPortMidiApi_PM_FILT_AFTERTOUCH
#define jportmidi_JPortMidiApi_PM_FILT_AFTERTOUCH 603979776L
#undef jportmidi_JPortMidiApi_PM_FILT_PROGRAM
#define jportmidi_JPortMidiApi_PM_FILT_PROGRAM 268435456L
#undef jportmidi_JPortMidiApi_PM_FILT_CONTROL
#define jportmidi_JPortMidiApi_PM_FILT_CONTROL 134217728L
#undef jportmidi_JPortMidiApi_PM_FILT_PITCHBEND
#define jportmidi_JPortMidiApi_PM_FILT_PITCHBEND 1073741824L
#undef jportmidi_JPortMidiApi_PM_FILT_MTC
#define jportmidi_JPortMidiApi_PM_FILT_MTC 2L
#undef jportmidi_JPortMidiApi_PM_FILT_SONG_POSITION
#define jportmidi_JPortMidiApi_PM_FILT_SONG_POSITION 4L
#undef jportmidi_JPortMidiApi_PM_FILT_SONG_SELECT
#define jportmidi_JPortMidiApi_PM_FILT_SONG_SELECT 8L
#undef jportmidi_JPortMidiApi_PM_FILT_TUNE
#define jportmidi_JPortMidiApi_PM_FILT_TUNE 64L
#undef jportmidi_JPortMidiApi_PM_FILT_SYSTEMCOMMON
#define jportmidi_JPortMidiApi_PM_FILT_SYSTEMCOMMON 78L
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_Initialize
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Initialize
(JNIEnv *, jclass);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_Terminate
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Terminate
(JNIEnv *, jclass);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_HasHostError
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1HasHostError
(JNIEnv *, jclass, jobject);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_GetErrorText
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetErrorText
(JNIEnv *, jclass, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_GetHostErrorText
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetHostErrorText
(JNIEnv *, jclass);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_CountDevices
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1CountDevices
(JNIEnv *, jclass);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_GetDefaultInputDeviceID
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDefaultInputDeviceID
(JNIEnv *, jclass);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_GetDefaultOutputDeviceID
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDefaultOutputDeviceID
(JNIEnv *, jclass);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_GetDeviceInterf
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceInterf
(JNIEnv *, jclass, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_GetDeviceName
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceName
(JNIEnv *, jclass, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_GetDeviceInput
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceInput
(JNIEnv *, jclass, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_GetDeviceOutput
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceOutput
(JNIEnv *, jclass, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_OpenInput
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;ILjava/lang/String;I)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1OpenInput
(JNIEnv *, jclass, jobject, jint, jstring, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_OpenOutput
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;ILjava/lang/String;II)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1OpenOutput
(JNIEnv *, jclass, jobject, jint, jstring, jint, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_SetFilter
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;I)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1SetFilter
(JNIEnv *, jclass, jobject, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_SetChannelMask
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;I)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1SetChannelMask
(JNIEnv *, jclass, jobject, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_Abort
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Abort
(JNIEnv *, jclass, jobject);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_Close
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Close
(JNIEnv *, jclass, jobject);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_Read
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;Ljportmidi/JPortMidiApi/PmEvent;)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Read
(JNIEnv *, jclass, jobject, jobject);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_Poll
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Poll
(JNIEnv *, jclass, jobject);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_Write
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;Ljportmidi/JPortMidiApi/PmEvent;)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Write
(JNIEnv *, jclass, jobject, jobject);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_WriteShort
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;II)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1WriteShort
(JNIEnv *, jclass, jobject, jint, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pm_WriteSysEx
* Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;I[B)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1WriteSysEx
(JNIEnv *, jclass, jobject, jint, jbyteArray);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pt_TimeStart
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStart
(JNIEnv *, jclass, jint);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pt_TimeStop
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStop
(JNIEnv *, jclass);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pt_Time
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1Time
(JNIEnv *, jclass);
/*
* Class: jportmidi_JPortMidiApi
* Method: Pt_TimeStarted
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStarted
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
/* Header for class jportmidi_JPortMidiApi_PmEvent */
#ifndef _Included_jportmidi_JPortMidiApi_PmEvent
#define _Included_jportmidi_JPortMidiApi_PmEvent
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
/* Header for class jportmidi_JPortMidiApi_PortMidiStream */
#ifndef _Included_jportmidi_JPortMidiApi_PortMidiStream
#define _Included_jportmidi_JPortMidiApi_PortMidiStream
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,225 @@
<?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="&quot;$(SolutionDir)\pm_common&quot;;&quot;$(SolutionDir)\porttime&quot;;&quot;$(ProjectDir)&quot;;&quot;E:\Program Files\Java\jdk1.5.0_14\include&quot;;&quot;E:\Program Files\Java\jdk1.5.0_14\include\win32&quot;"
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="&quot;$(SolutionDir)\pm_common&quot;;&quot;$(SolutionDir)\porttime&quot;;&quot;$(ProjectDir)&quot;;&quot;E:\Program Files\Java\jdk1.5.0_14\include&quot;;&quot;E:\Program Files\Java\jdk1.5.0_14\include\win32&quot;"
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>

354
3rdparty/portmidi/pm_java/pmjni/pmjni.c vendored Normal file
View File

@ -0,0 +1,354 @@
#include "portmidi.h"
#include "porttime.h"
#include "jportmidi_JportMidiApi.h"
#include <stdio.h>
// these macros assume JNIEnv *env is declared and valid:
//
#define CLASS(c, obj) jclass c = (*env)->GetObjectClass(env, obj)
#define ADDRESS_FID(fid, c) \
jfieldID fid = (*env)->GetFieldID(env, c, "address", "J")
// Uses Java Long (64-bit) to make sure there is room to store a
// pointer. Cast this to a C long (either 32 or 64 bit) to match
// 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))
// 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)
/*
* Method: Pm_Initialize
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Initialize
(JNIEnv *env, jclass cl)
{
return Pm_Initialize();
}
/*
* Method: Pm_Terminate
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Terminate
(JNIEnv *env, jclass cl)
{
return Pm_Terminate();
}
/*
* Method: Pm_HasHostError
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1HasHostError
(JNIEnv *env, jclass cl, jobject jstream)
{
CLASS(c, jstream);
ADDRESS_FID(fid, c);
return Pm_HasHostError(PMSTREAM(jstream, fid));
}
/*
* Method: Pm_GetErrorText
*/
JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetErrorText
(JNIEnv *env, jclass cl, jint i)
{
return (*env)->NewStringUTF(env, Pm_GetErrorText(i));
}
/*
* Method: Pm_GetHostErrorText
*/
JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetHostErrorText
(JNIEnv *env, jclass cl)
{
char msg[PM_HOST_ERROR_MSG_LEN];
Pm_GetHostErrorText(msg, PM_HOST_ERROR_MSG_LEN);
return (*env)->NewStringUTF(env, msg);
}
/*
* Method: Pm_CountDevices
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1CountDevices
(JNIEnv *env, jclass cl)
{
return Pm_CountDevices();
}
/*
* Method: Pm_GetDefaultInputDeviceID
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDefaultInputDeviceID
(JNIEnv *env, jclass cl)
{
return Pm_GetDefaultInputDeviceID();
}
/*
* Method: Pm_GetDefaultOutputDeviceID
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDefaultOutputDeviceID
(JNIEnv *env, jclass cl)
{
return Pm_GetDefaultOutputDeviceID();
}
/*
* Method: Pm_GetDeviceInterf
*/
JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceInterf
(JNIEnv *env, jclass cl, jint i)
{
const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
if (!info) return NULL;
return (*env)->NewStringUTF(env, info->interf);
}
/*
* Method: Pm_GetDeviceName
*/
JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceName
(JNIEnv *env, jclass cl, jint i)
{
const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
if (!info) return NULL;
return (*env)->NewStringUTF(env, info->name);
}
/*
* Method: Pm_GetDeviceInput
*/
JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceInput
(JNIEnv *env, jclass cl, jint i)
{
const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
if (!info) return (jboolean) 0;
return (jboolean) info->input;
}
/*
* Method: Pm_GetDeviceOutput
*/
JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceOutput
(JNIEnv *env, jclass cl, jint i)
{
const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
if (!info) return (jboolean) 0;
return (jboolean) info->output;
}
/*
* Method: Pm_OpenInput
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1OpenInput
(JNIEnv *env, jclass cl,
jobject jstream, jint index, jstring extras, jint bufsiz)
{
PmError rslt;
PortMidiStream *stream;
CLASS(c, jstream);
ADDRESS_FID(fid, c);
rslt = Pm_OpenInput(&stream, index, NULL, bufsiz, NULL, NULL);
SET_PMSTREAM(jstream, fid, stream);
return rslt;
}
/*
* Method: Pm_OpenOutput
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1OpenOutput
(JNIEnv *env, jclass cl, jobject jstream, jint index, jstring extras,
jint bufsiz, jint latency)
{
PmError rslt;
PortMidiStream *stream;
CLASS(c, jstream);
ADDRESS_FID(fid, c);
rslt = Pm_OpenOutput(&stream, index, NULL, bufsiz, NULL, NULL, latency);
SET_PMSTREAM(jstream, fid, stream);
return rslt;
}
/*
* Method: Pm_SetFilter
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1SetFilter
(JNIEnv *env, jclass cl, jobject jstream, jint filters)
{
CLASS(c, jstream);
ADDRESS_FID(fid, c);
return Pm_SetFilter(PMSTREAM(jstream, fid), filters);
}
/*
* Method: Pm_SetChannelMask
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1SetChannelMask
(JNIEnv *env, jclass cl, jobject jstream, jint mask)
{
CLASS(c, jstream);
ADDRESS_FID(fid, c);
return Pm_SetChannelMask(PMSTREAM(jstream, fid), mask);
}
/*
* Method: Pm_Abort
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Abort
(JNIEnv *env, jclass cl, jobject jstream)
{
CLASS(c, jstream);
ADDRESS_FID(fid, c);
return Pm_Abort(PMSTREAM(jstream, fid));
}
/*
* Method: Pm_Close
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Close
(JNIEnv *env, jclass cl, jobject jstream)
{
CLASS(c, jstream);
ADDRESS_FID(fid, c);
return Pm_Close(PMSTREAM(jstream, fid));
}
/*
* Method: Pm_Read
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Read
(JNIEnv *env, jclass cl, jobject jstream, jobject jpmevent)
{
CLASS(jstream_class, jstream);
ADDRESS_FID(address_fid, jstream_class);
jclass jpmevent_class = (*env)->GetObjectClass(env, jpmevent);
jfieldID message_fid =
(*env)->GetFieldID(env, jpmevent_class, "message", "I");
jfieldID timestamp_fid =
(*env)->GetFieldID(env, jpmevent_class, "timestamp", "I");
PmEvent buffer;
PmError rslt = Pm_Read(PMSTREAM(jstream, address_fid), &buffer, 1);
(*env)->SetIntField(env, jpmevent, message_fid, buffer.message);
(*env)->SetIntField(env, jpmevent, timestamp_fid, buffer.timestamp);
return rslt;
}
/*
* Method: Pm_Poll
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Poll
(JNIEnv *env, jclass cl, jobject jstream)
{
CLASS(c, jstream);
ADDRESS_FID(fid, c);
return Pm_Poll(PMSTREAM(jstream, fid));
}
/*
* Method: Pm_Write
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Write
(JNIEnv *env, jclass cl, jobject jstream, jobject jpmevent)
{
CLASS(jstream_class, jstream);
ADDRESS_FID(address_fid, jstream_class);
jclass jpmevent_class = (*env)->GetObjectClass(env, jpmevent);
jfieldID message_fid =
(*env)->GetFieldID(env, jpmevent_class, "message", "I");
jfieldID timestamp_fid =
(*env)->GetFieldID(env, jpmevent_class, "timestamp", "I");
// note that we call WriteShort because it's simpler than constructing
// a buffer and passing it to Pm_Write
return Pm_WriteShort(PMSTREAM(jstream, address_fid),
(*env)->GetIntField(env, jpmevent, timestamp_fid),
(*env)->GetIntField(env, jpmevent, message_fid));
}
/*
* Method: Pm_WriteShort
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1WriteShort
(JNIEnv *env, jclass cl, jobject jstream, jint when, jint msg)
{
CLASS(c, jstream);
ADDRESS_FID(fid, c);
return Pm_WriteShort(PMSTREAM(jstream, fid), when, msg);
}
/*
* Method: Pm_WriteSysEx
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1WriteSysEx
(JNIEnv *env, jclass cl, jobject jstream, jint when, jbyteArray jmsg)
{
CLASS(c, jstream);
ADDRESS_FID(fid, c);
jbyte *bytes = (*env)->GetByteArrayElements(env, jmsg, 0);
PmError rslt = Pm_WriteSysEx(PMSTREAM(jstream, fid), when,
(unsigned char *) bytes);
(*env)->ReleaseByteArrayElements(env, jmsg, bytes, 0);
return rslt;
}
/*
* Method: Pt_TimeStart
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStart
(JNIEnv *env, jclass c, jint resolution)
{
return Pt_Start(resolution, NULL, NULL);
}
/*
* Method: Pt_TimeStop
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStop
(JNIEnv *env, jclass c)
{
return Pt_Stop();
}
/*
* Method: Pt_Time
*/
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1Time
(JNIEnv *env, jclass c)
{
return Pt_Time();
}
/*
* Method: Pt_TimeStarted
*/
JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStarted
(JNIEnv *env, jclass c)
{
return Pt_Started();
}

View File

@ -0,0 +1,63 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

Binary file not shown.

View File

@ -0,0 +1,113 @@
README_LINUX.txt for PortMidi
Roger Dannenberg
14 Oct 2009
To make PortMidi, you need cmake and the Java SDK.
Go back up to the portmidi directory and type:
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.)
THE pmdefaults PROGRAM
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
and so users have a single place to set a preference.
Follow the instructions above to run ccmake, making sure that
CMAKE_BUILD_TYPE is Release. Run make as described above. Then:
sudo make install
This will install PortMidi libraries and the pmdefault program.
You must alos have the environment variable LD_LIBRARY_PATH set
to include /usr/local/lib (where libpmjni.so is installed).
Now, you can run pmdefault.
SETTING LD_LIBRARY_PATH
pmdefaults will not work unless LD_LIBRARY_PATH includes a
directory (normally /usr/local/lib) containing libpmjni.so,
installed as described above.
To set LD_LIBRARY_PATH, you might want to add this to your
~/.profile (if you use the bash shell):
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
export LD_LIBRARY_PATH
A NOTE ABOUT AMD64:
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
with this error:
./linux/libportmidi.a(pmlinux.o): relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
./linux/libportmidi.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
error: command 'gcc' failed with exit status 1
What they said:
http://www.gentoo.org/proj/en/base/amd64/howtos/index.xml?part=1&chap=3
On certain architectures (AMD64 amongst them), shared libraries *must*
be "PIC-enabled".
CHANGELOG
22-jan-2010 Roger B. Dannenberg
Updated instructions about Java paths
14-oct-2009 Roger B. Dannenberg
Using CMake now for building and configuration
29-aug-2006 Roger B. Dannenberg
Fixed PortTime to join with time thread for clean exit.
28-aug-2006 Roger B. Dannenberg
Updated this documentation.
08-Jun-2004 Roger B. Dannenberg
Updated code to use new system abstraction.
12-Apr-2003 Roger B. Dannenberg
Fixed pm_test/test.c to filter clocks and active messages.
Integrated changes from Clemens Ladisch:
cleaned up pmlinuxalsa.c
record timestamp on sysex input
deallocate some resources previously left open

View File

@ -0,0 +1,92 @@
/* finddefault.c -- find_default_device() implementation
Roger Dannenberg, Jan 2009
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "portmidi.h"
#define STRING_MAX 256
/* skip over spaces, return first non-space */
void skip_spaces(FILE *inf)
{
char c;
while (isspace(c = getc(inf))) ;
ungetc(c, inf);
}
/* trim leading spaces and match a string */
int match_string(FILE *inf, char *s)
{
skip_spaces(inf);
while (*s && *s == getc(inf)) s++;
return (*s == 0);
}
/*
/* Parse preference files, find default device, search devices --
*/
PmDeviceID find_default_device(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 = "/.java/.userPrefs/";
static char *pref_3 = "prefs.xml";
char *pref_1 = getenv("HOME");
char *full_name, *path_ptr;
FILE *inf;
int c, i;
if (!pref_1) goto nopref; // cannot find preference file
// full_name will be larger than necessary
full_name = malloc(strlen(pref_1) + strlen(pref_2) + strlen(pref_3) +
strlen(path) + 2);
strcpy(full_name, pref_1);
strcat(full_name, pref_2);
// copy all but last path segment to full_name
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);
memcpy(full_name + offset, path, path_ptr - path);
full_name[offset + path_ptr - path] = 0; // end of string
} else {
path_ptr = path;
}
strcat(full_name, pref_3);
inf = fopen(full_name, "r");
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
// "value", "=", quote. Then get string up to quote.
while ((c = getc(inf)) != EOF) {
char pref_str[STRING_MAX];
if (c != '"') continue; // scan up to quote
// 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, "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;
pref_str[i] = c;
}
if (i == STRING_MAX) continue; // value too long, ignore
pref_str[i] == 0;
i = pm_find_default_device(pref_str, input);
if (i != pmNoDevice) {
id = i;
}
break;
}
nopref:
return id;
}

73
3rdparty/portmidi/pm_linux/pmlinux.c vendored Normal file
View File

@ -0,0 +1,73 @@
/* pmlinux.c -- PortMidi os-dependent code */
/* This file only needs to implement pm_init(), which calls various
routines to register the available midi devices. This file must
be separate from the main portmidi.c file because it is system
dependent, and it is separate from, pmlinuxalsa.c, because it
might need to register non-alsa devices as well.
NOTE: if you add non-ALSA support, you need to fix :alsa_poll()
in pmlinuxalsa.c, which assumes all input devices are ALSA.
*/
#include "stdlib.h"
#include "portmidi.h"
#include "pmutil.h"
#include "pminternal.h"
#ifdef PMALSA
#include "pmlinuxalsa.h"
#endif
#ifdef PMNULL
#include "pmlinuxnull.h"
#endif
PmDeviceID pm_default_input_device_id = -1;
PmDeviceID pm_default_output_device_id = -1;
void pm_init()
{
/* 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
pm_linuxnull_init();
#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(
"/PortMidi/PM_RECOMMENDED_INPUT_DEVICE", TRUE,
pm_default_input_device_id);
pm_default_output_device_id = find_default_device(
"/PortMidi/PM_RECOMMENDED_OUTPUT_DEVICE", FALSE,
pm_default_output_device_id);
}
void pm_term(void)
{
#ifdef PMALSA
pm_linuxalsa_term();
#endif
}
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); }

View File

@ -2,3 +2,4 @@
extern PmDeviceID pm_default_input_device_id;
extern PmDeviceID pm_default_output_device_id;

779
3rdparty/portmidi/pm_linux/pmlinuxalsa.c vendored Normal file
View File

@ -0,0 +1,779 @@
/*
* pmlinuxalsa.c -- system specific definitions
*
* written by:
* Roger Dannenberg (port to Alsa 0.9.x)
* Clemens Ladisch (provided code examples and invaluable consulting)
* Jason Cohen, Rico Colon, Matt Filippone (Alsa 0.5.x implementation)
*/
#include "stdlib.h"
#include "portmidi.h"
#include "pmutil.h"
#include "pminternal.h"
#include "pmlinuxalsa.h"
#include "string.h"
#include "porttime.h"
#include "pmlinux.h"
#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:
*/
#define VERBOSE_ON 0
#define VERBOSE if (VERBOSE_ON)
#define MIDI_SYSEX 0xf0
#define MIDI_EOX 0xf7
#if SND_LIB_MAJOR == 0 && SND_LIB_MINOR < 9
#error needs ALSA 0.9.0 or later
#endif
/* to store client/port in the device descriptor */
#define MAKE_DESCRIPTOR(client, port) ((void*)(((client) << 8) | (port)))
#define GET_DESCRIPTOR_CLIENT(info) ((((int)(info)) >> 8) & 0xff)
#define GET_DESCRIPTOR_PORT(info) (((int)(info)) & 0xff)
#define BYTE unsigned char
extern pm_fns_node pm_linuxalsa_in_dictionary;
extern pm_fns_node pm_linuxalsa_out_dictionary;
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 {
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;
/* get_alsa_error_text -- copy error text to potentially short string */
/**/
static void get_alsa_error_text(char *msg, int len, int err)
{
int errlen = strlen(snd_strerror(err));
if (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;
}
}
/* queue is shared by both input and output, reference counted */
static PmError alsa_use_queue(void)
{
if (queue_used == 0) {
snd_seq_queue_tempo_t *tempo;
queue = snd_seq_alloc_queue(seq);
if (queue < 0) {
pm_hosterror = queue;
return pmHostError;
}
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;
snd_seq_start_queue(seq, queue, NULL);
snd_seq_drain_output(seq);
}
++queue_used;
return pmNoError;
}
static void alsa_unuse_queue(void)
{
if (--queue_used == 0) {
snd_seq_stop_queue(seq, queue, NULL);
snd_seq_drain_output(seq);
snd_seq_free_queue(seq, queue);
VERBOSE printf("queue freed\n");
}
}
/* midi_message_length -- how many bytes in a message? */
static int midi_message_length(PmMessage message)
{
message &= 0xff;
if (message < 0x80) {
return 0;
} else if (message < 0xf0) {
static const int length[] = {3, 3, 3, 3, 2, 2, 3};
return length[(message - 0x80) >> 4];
} else {
static const int length[] = {
-1, 2, 3, 2, 0, 0, 1, -1, 1, 0, 1, 1, 1, 0, 1, 1};
return length[message - 0xf0];
}
}
static PmError alsa_out_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 err;
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;
err = snd_midi_event_new(PM_DEFAULT_SYSEX_BUFFER_SIZE, &desc->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;
err = snd_seq_connect_to(seq, desc->this_port, desc->client, desc->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();
free_parser:
snd_midi_event_free(desc->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;
}
static PmError alsa_write_byte(PmInternal *midi, unsigned char byte,
PmTimestamp timestamp)
{
alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor;
snd_seq_event_t ev;
int err;
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 (midi->latency > 0) {
/* compute relative time of event = timestamp - now + latency */
PmTimestamp now = (midi->time_proc ?
midi->time_proc(midi->time_info) :
Pt_Time(NULL));
int when = timestamp;
/* if timestamp is zero, send immediately */
/* otherwise compute time delay and use delay if positive */
if (when == 0) when = now;
when = (when - now) + midi->latency;
if (when < 0) when = 0;
VERBOSE printf("timestamp %d now %d latency %d, ",
(int) timestamp, (int) now, midi->latency);
VERBOSE printf("scheduling event after %d\n", when);
/* message is sent in relative ticks, where 1 tick = 1 ms */
snd_seq_ev_schedule_tick(&ev, queue, 1, when);
/* NOTE: for cases where the user does not supply a time function,
we could optimize the code by not starting Pt_Time and using
the alsa tick time instead. I didn't do this because it would
entail changing the queue management to start the queue tick
count when PortMidi is initialized and keep it running until
PortMidi is terminated. (This should be simple, but it's not
how the code works now.) -RBD */
} else { /* send event out without queueing */
VERBOSE printf("direct\n");
/* ev.queue = SND_SEQ_QUEUE_DIRECT;
ev.dest.client = SND_SEQ_ADDRESS_SUBSCRIBERS; */
snd_seq_ev_set_direct(&ev);
}
VERBOSE printf("sending event\n");
err = snd_seq_event_output(seq, &ev);
if (err < 0) {
desc->error = err;
return pmHostError;
}
}
return pmNoError;
}
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);
}
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;
}
return pmNoError;
}
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;
snd_seq_port_subscribe_t *sub;
snd_seq_addr_t addr;
int err;
if (!desc) return pmInsufficientMemory;
err = alsa_use_queue();
if (err < 0) goto free_desc;
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 */
return pmNoError;
free_this_port:
snd_seq_delete_port(seq, desc->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;
}
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);
}
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;
}
static PmError alsa_abort(PmInternal *midi)
{
/* NOTE: ALSA documentation is vague. This is supposed to
* remove any pending output messages. If you can test and
* confirm this code is correct, please update this comment. -RBD
*/
/* Unfortunately, I can't even compile it -- my ALSA version
* does not implement snd_seq_remove_events_t, so this does
* not compile. I'll try again, but it looks like I'll need to
* upgrade my entire Linux OS -RBD
*/
/*
alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor;
snd_seq_remove_events_t info;
snd_seq_addr_t addr;
addr.client = desc->client;
addr.port = desc->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);
if (pm_hosterror) {
get_alsa_error_text(pm_hosterror_text, PM_HOST_ERROR_MSG_LEN,
pm_hosterror);
return pmHostError;
}
*/
printf("WARNING: alsa_abort not implemented\n");
return pmNoError;
}
#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) seq);
desc->error = snd_seq_drain_output(seq);
if (desc->error < 0) return pmHostError;
desc->error = pmNoError;
return pmNoError;
}
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;
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;
msg >>= 8; /* shift next byte into position */
}
if (desc->error < 0) return pmHostError;
desc->error = pmNoError;
return pmNoError;
}
/* alsa_sysex -- implements begin_sysex and end_sysex */
PmError alsa_sysex(PmInternal *midi, PmTimestamp timestamp) {
return pmNoError;
}
static PmTimestamp alsa_synchronize(PmInternal *midi)
{
return 0; /* linux implementation does not use this synchronize function */
/* Apparently, Alsa data is relative to the time you send it, and there
is no reference. If this is true, this is a serious shortcoming of
Alsa. If not true, then PortMidi has a serious shortcoming -- it
should be scheduling relative to Alsa's time reference. */
}
static void handle_event(snd_seq_event_t *ev)
{
int device_id = ev->dest.port;
PmInternal *midi = descriptors[device_id].internalDescriptor;
PmEvent pm_ev;
PmTimeProcPtr time_proc = midi->time_proc;
PmTimestamp timestamp;
/* 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);
/* if no time_proc, just return "native" ticks (ms) */
if (time_proc == NULL) {
timestamp = ev->time.tick;
} else { /* 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);
}
pm_ev.timestamp = timestamp;
switch (ev->type) {
case SND_SEQ_EVENT_NOTEON:
pm_ev.message = Pm_Message(0x90 | ev->data.note.channel,
ev->data.note.note & 0x7f,
ev->data.note.velocity & 0x7f);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_NOTEOFF:
pm_ev.message = Pm_Message(0x80 | ev->data.note.channel,
ev->data.note.note & 0x7f,
ev->data.note.velocity & 0x7f);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_KEYPRESS:
pm_ev.message = Pm_Message(0xa0 | ev->data.note.channel,
ev->data.note.note & 0x7f,
ev->data.note.velocity & 0x7f);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_CONTROLLER:
pm_ev.message = Pm_Message(0xb0 | ev->data.note.channel,
ev->data.control.param & 0x7f,
ev->data.control.value & 0x7f);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_PGMCHANGE:
pm_ev.message = Pm_Message(0xc0 | ev->data.note.channel,
ev->data.control.value & 0x7f, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_CHANPRESS:
pm_ev.message = Pm_Message(0xd0 | ev->data.note.channel,
ev->data.control.value & 0x7f, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_PITCHBEND:
pm_ev.message = Pm_Message(0xe0 | ev->data.note.channel,
(ev->data.control.value + 0x2000) & 0x7f,
((ev->data.control.value + 0x2000) >> 7) & 0x7f);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_CONTROL14:
if (ev->data.control.param < 0x20) {
pm_ev.message = Pm_Message(0xb0 | ev->data.note.channel,
ev->data.control.param,
(ev->data.control.value >> 7) & 0x7f);
pm_read_short(midi, &pm_ev);
pm_ev.message = Pm_Message(0xb0 | ev->data.note.channel,
ev->data.control.param + 0x20,
ev->data.control.value & 0x7f);
pm_read_short(midi, &pm_ev);
} else {
pm_ev.message = Pm_Message(0xb0 | ev->data.note.channel,
ev->data.control.param & 0x7f,
ev->data.control.value & 0x7f);
pm_read_short(midi, &pm_ev);
}
break;
case SND_SEQ_EVENT_SONGPOS:
pm_ev.message = Pm_Message(0xf2,
ev->data.control.value & 0x7f,
(ev->data.control.value >> 7) & 0x7f);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_SONGSEL:
pm_ev.message = Pm_Message(0xf3,
ev->data.control.value & 0x7f, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_QFRAME:
pm_ev.message = Pm_Message(0xf1,
ev->data.control.value & 0x7f, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_START:
pm_ev.message = Pm_Message(0xfa, 0, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_CONTINUE:
pm_ev.message = Pm_Message(0xfb, 0, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_STOP:
pm_ev.message = Pm_Message(0xfc, 0, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_CLOCK:
pm_ev.message = Pm_Message(0xf8, 0, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_TUNE_REQUEST:
pm_ev.message = Pm_Message(0xf6, 0, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_RESET:
pm_ev.message = Pm_Message(0xff, 0, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_SENSING:
pm_ev.message = Pm_Message(0xfe, 0, 0);
pm_read_short(midi, &pm_ev);
break;
case SND_SEQ_EVENT_SYSEX: {
const BYTE *ptr = (const BYTE *) ev->data.ext.ptr;
/* assume there is one sysex byte to process */
pm_read_bytes(midi, ptr, ev->data.ext.len, timestamp);
break;
}
}
}
static PmError alsa_poll(PmInternal *midi)
{
snd_seq_event_t *ev;
/* expensive check for input data, gets data from device: */
while (snd_seq_event_input_pending(seq, TRUE) > 0) {
/* cheap check on local input buffer */
while (snd_seq_event_input_pending(seq, FALSE) > 0) {
/* check for and ignore errors, e.g. input overflow */
/* note: if there's overflow, this should be reported
* all the way through to client. Since input from all
* devices is merged, we need to find all input devices
* and set all to the overflow state.
* NOTE: this assumes every input is ALSA based.
*/
int rslt = snd_seq_event_input(seq, &ev);
if (rslt >= 0) {
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;
/* careful, device may not be open! */
if (midi) Pm_SetOverflow(midi->queue);
}
}
}
}
}
return pmNoError;
}
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)
{
alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor;
int err = (pm_hosterror || desc->error);
get_alsa_error_text(msg, len, err);
}
pm_fns_node pm_linuxalsa_in_dictionary = {
none_write_short,
none_sysex,
none_sysex,
none_write_byte,
none_write_short,
none_write_flush,
alsa_synchronize,
alsa_in_open,
alsa_abort,
alsa_in_close,
alsa_poll,
alsa_has_host_error,
alsa_get_host_error
};
pm_fns_node pm_linuxalsa_out_dictionary = {
alsa_write_short,
alsa_sysex,
alsa_sysex,
alsa_write_byte,
alsa_write_short, /* short realtime message */
alsa_write_flush,
alsa_synchronize,
alsa_out_open,
alsa_abort,
alsa_out_close,
none_poll,
alsa_has_host_error,
alsa_get_host_error
};
/* pm_strdup -- copy a string to the heap. Use this rather than strdup so
* that we call pm_alloc, not malloc. This allows portmidi to avoid
* malloc which might cause priority inversion. Probably ALSA is going
* to call malloc anyway, so this extra work here may be pointless.
*/
char *pm_strdup(const char *s)
{
int len = strlen(s);
char *dup = (char *) pm_alloc(len + 1);
strcpy(dup, s);
return dup;
}
PmError pm_linuxalsa_init( void )
{
int err;
snd_seq_client_info_t *cinfo;
snd_seq_port_info_t *pinfo;
unsigned int caps;
/* 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
* room to send all the data. The client should normally allocate
* a large enough buffer to avoid blocking on output.
* Now that blocking is enabled, the seq_event_input() will block
* if there is no input data. This is not what we want, so must
* call seq_event_input_pending() to avoid blocking.
*/
err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0);
if (err < 0) return err;
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_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)))
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;
pm_add_device("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);
}
if (caps & SND_SEQ_PORT_CAP_SUBS_READ) {
if (pm_default_input_device_id == -1)
pm_default_input_device_id = pm_descriptor_index;
pm_add_device("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);
}
}
}
return pmNoError;
}
void pm_linuxalsa_term(void)
{
if (seq) {
snd_seq_close(seq);
pm_free(descriptors);
descriptors = NULL;
pm_descriptor_index = 0;
pm_descriptor_max = 0;
}
}

View File

@ -2,3 +2,5 @@
PmError pm_linuxalsa_init(void);
void pm_linuxalsa_term(void);

129
3rdparty/portmidi/pm_mac/Makefile.osx vendored Normal file
View File

@ -0,0 +1,129 @@
# MAKEFILE FOR PORTMIDI
# Roger B. Dannenberg
# Sep 2009
# NOTE: you can use
# make -f pm_osx/Makefile.osx configuration=Release
# to override the default Debug configuration
configuration=Release
PF=/usr/local
# For debugging, define PM_CHECK_ERRORS
ifeq ($(configuration),Release)
CONFIG = Release
else
CONFIG = Debug
endif
current: all
all: $(CONFIG)/CMakeCache.txt
cd $(CONFIG); make
$(CONFIG)/CMakeCache.txt:
rm -f 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'
help:
echo $$'\n\n\
This is help for portmidi/pm_mac/Makefile.osx\n\n\
Installation path for dylib is $(PF)\n\
To build Release version libraries and test applications,\n \
make -f pm_mac/Makefile.osx\n\
To build Debug version libraries and test applications,\n \
make -f pm_mac/Makefile.osx configuration=Debug\n\
To install universal dynamic library,\n \
sudo make -f pm_mac/Makefile.osx install\n\
To install universal dynamic library with xcode,\n \
make -f pm_mac/Makefile.osx install-with-xcode\n\
To make PmDefaults Java application,\n \
make -f pm_mac/Makefile.osx pmdefaults\n\n \
configuration = $(configuration)\n'
clean:
rm -f *.o *~ core* */*.o */*/*.o */*~ */core* pm_test/*/pm_dll.dll
rm -f *.opt *.ncb *.plg pm_win/Debug/pm_dll.lib pm_win/Release/pm_dll.lib
rm -f pm_test/*.opt pm_test/*.ncb
rm -f pm_java/pmjni/*.o pm_java/pmjni/*~ pm_java/*.h
rm -rf Release/CMakeFiles Debug/CMakeFiles
rm -rf pm_mac/pmdefaults/lib pm_mac/pmdefaults/src
cleaner: clean
rm -rf pm_mac/build
rm -rf pm_mac/Debug pm_mac/Release pm_test/Debug pm_test/Release
rm -f Debug/*.dylib Release/*.dylib
rm -f pm_java/pmjni/Debug/*.jnilib
rm -f pm_java/pmjni/Release/*.jnilib
cleanest: cleaner
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
rm -f pm_test/Debug/qtest pm_test/Debug/mm
rm -f pm_test/Release/test pm_test/Release/sysex pm_test/Release/midithread
rm -f pm_test/Release/latency pm_test/Release/midithru
rm -f pm_test/Release/qtest pm_test/Release/mm
rm -f pm_java/*/*.class
rm -f pm_java/pmjni/jportmidi_JPortMidiApi_PortMidiStream.h
backup: cleanest
cd ..; zip -r portmidi.zip portmidi
install: porttime/porttime.h pm_common/portmidi.h \
$(CONFIG)/libportmidi.dylib
install porttime/porttime.h $(PF)/include/
install pm_common/portmidi.h $(PF)/include
install $(CONFIG)/libportmidi.dylib $(PF)/lib/
# note - this uses xcode to build and install portmidi universal binaries
install-with-xcode:
sudo xcodebuild -project pm_mac/pm_mac.xcodeproj \
-configuration Release install DSTROOT=/
##### build pmdefault ######
pm_java/pmjni/jportmidi_JPortMidiApi.h: pm_java/jportmidi/JPortMidiApi.class
cd pm_java; javah jportmidi.JPortMidiApi
mv pm_java/jportmidi_JportMidiApi.h pm_java/pmjni
JAVASRC = pmdefaults/PmDefaultsFrame.java \
pmdefaults/PmDefaults.java \
jportmidi/JPortMidiApi.java jportmidi/JPortMidi.java \
jportmidi/JPortMidiException.java
# this compiles ALL of the java code
pm_java/jportmidi/JPortMidiApi.class: $(JAVASRC:%=pm_java/%)
cd pm_java; javac $(JAVASRC)
$(CONFIG)/libpmjni.dylib:
mkdir -p $(CONFIG)
cd $(CONFIG); make -f ../pm_mac/$(MAKEFILE)
pmdefaults: $(CONFIG)/libpmjni.dylib pm_java/jportmidi/JPortMidiApi.class
ifeq ($(CONFIG),Debug)
echo "Error: you cannot build pmdefaults in a Debug configuration \n\
You should use configuration=Release in the Makefile command line. "
@exit 2
endif
xcodebuild -project pm_mac/pm_mac.xcodeproj \
-configuration Release -target PmDefaults
echo "pmdefaults java application is made"
###### test plist reader #######
PLHDR = pm_mac/readbinaryplist.h
PLSRC = pm_mac/plisttest.c pm_mac/readbinaryplist.c
pm_mac/plisttest: $(PLHDR) $(PLSRC)
cc $(VFLAGS) -Ipm_mac \
-I/Developer/Headers/FlatCarbon \
-I/System/Library/Frameworks/CoreFoundation.framework/Headers \
-I/System/Library/Frameworks/CoreServices.framework/Headers \
$(PLSRC) -o pm_mac/$(CONFIG)/plisttest \
-framework CoreFoundation -framework CoreServices

163
3rdparty/portmidi/pm_mac/README_MAC.txt vendored Normal file
View File

@ -0,0 +1,163 @@
README_MAC.txt for PortMidi
Roger Dannenberg
20 nov 2009
revised 20 Sep 2010 for Xcode 3.2.4 and CMake 8.2-2
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.

57
3rdparty/portmidi/pm_mac/finddefault.c vendored Normal file
View File

@ -0,0 +1,57 @@
/* finddefault.c -- find_default_device() implementation
Roger Dannenberg, June 2008
*/
#include <stdlib.h>
#include <string.h>
#include "portmidi.h"
#include "pmutil.h"
#include "pminternal.h"
#include "pmmacosxcm.h"
#include "readbinaryplist.h"
/* Parse preference files, find default device, search devices --
This parses the preference file(s) once for input and once for
output, which is inefficient but much simpler to manage. Note
that using the readbinaryplist.c module, you cannot keep two
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)
/* 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 = "com.apple.java.util.prefs.plist";
char *pref_str = NULL;
// read device preferences
value_ptr prefs = bplist_read_user_pref(pref_file);
if (prefs) {
value_ptr pref_val = value_dict_lookup_using_path(prefs, path);
if (pref_val) {
pref_str = value_get_asciistring(pref_val);
}
}
if (!pref_str) {
bplist_free_data(); /* look elsewhere */
prefs = bplist_read_system_pref(pref_file);
if (prefs) {
value_ptr pref_val = value_dict_lookup_using_path(prefs, path);
if (pref_val) {
pref_str = value_get_asciistring(pref_val);
}
}
}
if (pref_str) { /* search devices for match */
int i = pm_find_default_device(pref_str, input);
if (i != pmNoDevice) {
id = i;
}
}
if (prefs) {
bplist_free_data();
}
return id;
}

View File

@ -0,0 +1,594 @@
// !$*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 */;
}

View File

@ -0,0 +1,87 @@
<?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>

View File

@ -0,0 +1,31 @@
#!/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

View File

@ -0,0 +1,14 @@
{\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\
}

View File

@ -0,0 +1,40 @@
<?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>

View File

@ -0,0 +1 @@
Main-Class: pmdefaults/PmDefaults

59
3rdparty/portmidi/pm_mac/pmmac.c vendored Normal file
View File

@ -0,0 +1,59 @@
/* pmmac.c -- PortMidi os-dependent code */
/* This file only needs to implement:
pm_init(), which calls various routines to register the
available midi devices,
Pm_GetDefaultInputDeviceID(), and
Pm_GetDefaultOutputDeviceID().
It is seperate from pmmacosxcm because we might want to register
non-CoreMIDI devices.
*/
#include "stdlib.h"
#include "portmidi.h"
#include "pmutil.h"
#include "pminternal.h"
#include "pmmacosxcm.h"
PmDeviceID pm_default_input_device_id = -1;
PmDeviceID pm_default_output_device_id = -1;
void pm_init()
{
PmError err = pm_macosxcm_init();
// this is set when we return to Pm_Initialize, but we need it
// now in order to (successfully) call Pm_CountDevices()
pm_initialized = TRUE;
if (!err) {
pm_default_input_device_id = find_default_device(
"/PortMidi/PM_RECOMMENDED_INPUT_DEVICE", TRUE,
pm_default_input_device_id);
pm_default_output_device_id = find_default_device(
"/PortMidi/PM_RECOMMENDED_OUTPUT_DEVICE", FALSE,
pm_default_output_device_id);
}
}
void pm_term(void)
{
pm_macosxcm_term();
}
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); }

View File

@ -1,4 +1,4 @@
/* pmmac.h */
extern PmDeviceID pm_default_input_device_id;
extern PmDeviceID pm_default_output_device_id;
extern PmDeviceID pm_default_output_device_id;

1010
3rdparty/portmidi/pm_mac/pmmacosxcm.c vendored Normal file

File diff suppressed because it is too large Load Diff

1115
3rdparty/portmidi/pm_mac/readbinaryplist.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -6,75 +6,75 @@
#include <stdint.h> /* for uint8_t ... */
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#define TRUE 1
#define FALSE 0
#endif
#define MAX_KEY_SIZE 256
enum
{
// Object tags (high nybble)
kTAG_SIMPLE = 0x00, // Null, true, false, filler, or invalid
kTAG_INT = 0x10,
kTAG_REAL = 0x20,
kTAG_DATE = 0x30,
kTAG_DATA = 0x40,
kTAG_ASCIISTRING = 0x50,
kTAG_UNICODESTRING = 0x60,
kTAG_UID = 0x80,
kTAG_ARRAY = 0xA0,
kTAG_DICTIONARY = 0xD0,
// "simple" object values
kVALUE_NULL = 0x00,
kVALUE_FALSE = 0x08,
kVALUE_TRUE = 0x09,
kVALUE_FILLER = 0x0F,
kVALUE_FULLDATETAG = 0x33 // Dates are tagged with a whole byte.
// Object tags (high nybble)
kTAG_SIMPLE = 0x00, // Null, true, false, filler, or invalid
kTAG_INT = 0x10,
kTAG_REAL = 0x20,
kTAG_DATE = 0x30,
kTAG_DATA = 0x40,
kTAG_ASCIISTRING = 0x50,
kTAG_UNICODESTRING = 0x60,
kTAG_UID = 0x80,
kTAG_ARRAY = 0xA0,
kTAG_DICTIONARY = 0xD0,
// "simple" object values
kVALUE_NULL = 0x00,
kVALUE_FALSE = 0x08,
kVALUE_TRUE = 0x09,
kVALUE_FILLER = 0x0F,
kVALUE_FULLDATETAG = 0x33 // Dates are tagged with a whole byte.
};
typedef struct pldata_struct {
uint8_t *data;
size_t len;
uint8_t *data;
size_t len;
} pldata_node, *pldata_ptr;
typedef struct array_struct {
struct value_struct **array;
uint64_t length;
struct value_struct **array;
uint64_t length;
} array_node, *array_ptr;
// a dict_node is a list of <key, value> pairs
typedef struct dict_struct {
struct value_struct *key;
struct value_struct *value;
struct dict_struct *next;
struct value_struct *key;
struct value_struct *value;
struct dict_struct *next;
} dict_node, *dict_ptr;
// an value_node is a value with a tag telling the type
typedef struct value_struct {
int tag;
union {
int64_t integer;
uint64_t uinteger;
double real;
char *string;
pldata_ptr data;
array_ptr array;
struct dict_struct *dict;
};
int tag;
union {
int64_t integer;
uint64_t uinteger;
double real;
char *string;
pldata_ptr data;
array_ptr array;
struct dict_struct *dict;
};
} 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);
void bplist_free_data(void);
void bplist_free_data();
/*************** functions for accessing values ****************/
@ -85,3 +85,4 @@ value_ptr value_dict_lookup_using_path(value_ptr v, char *path);
/*************** functions for debugging ***************/
void plist_print(value_ptr v);

View File

@ -0,0 +1,11 @@
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.

View File

@ -0,0 +1,23 @@
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

View File

@ -0,0 +1,710 @@
<?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="&quot;${workspace_loc:/PortMidi/pm_common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/PortMidi/pm_win}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/PortMidi/porttime}&quot;"/>
</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="&quot;${workspace_loc:/PortMidi/pm_common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/PortMidi/pm_win}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/PortMidi/porttime}&quot;"/>
</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="&quot;${workspace_loc:/PortMidi/pm_common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/PortMidi/pm_win}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/PortMidi/porttime}&quot;"/>
</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="&quot;${workspace_loc:/PortMidi/pm_common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/PortMidi/pm_win}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/PortMidi/porttime}&quot;"/>
</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>

View File

@ -0,0 +1,69 @@
<?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>

View File

@ -0,0 +1,8 @@
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

View File

@ -0,0 +1,34 @@
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.

View File

@ -0,0 +1,3 @@
from .midi import *

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,537 @@
# 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

View File

@ -0,0 +1,566 @@
"""
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)

185
3rdparty/portmidi/pm_python/setup.py vendored Normal file
View File

@ -0,0 +1,185 @@
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)

15
3rdparty/portmidi/pm_qt/README_QT.txt vendored Normal file
View File

@ -0,0 +1,15 @@
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"

47
3rdparty/portmidi/pm_qt/portmidi.pro vendored Normal file
View File

@ -0,0 +1,47 @@
#-------------------------------------------------
#
# 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

View File

@ -0,0 +1,26 @@
# pm_test
# set the build directory to be in portmidi, not in portmidi/pm_test
# this is required for Xcode:
if(APPLE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
endif(APPLE)
if(WIN32)
include(../pm_win/static.cmake)
endif(WIN32)
macro(make_a_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)
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)

290
3rdparty/portmidi/pm_test/latency.c vendored Normal file
View File

@ -0,0 +1,290 @@
/* latency.c -- measure latency of OS */
#include "porttime.h"
#include "portmidi.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "assert.h"
/* Latency is defined here to mean the time starting when a
process becomes ready to run, and ending when the process
actually runs. Latency is due to contention for the
processor, usually due to other processes, OS activity
including device drivers handling interrupts, and
waiting for the scheduler to suspend the currently running
process and activate the one that is waiting.
Latency can affect PortMidi applications: if a process fails
to wake up promptly, MIDI input may sit in the input buffer
waiting to be handled, and MIDI output may not be generated
with accurate timing. Using the latency parameter when
opening a MIDI output port allows the caller to defer timing
to PortMidi, which in most implementations will pass the
data on to the OS. By passing timestamps and data to the
OS kernel, device driver, or even hardware, there are fewer
sources of latency that can affect the ultimate timing of
the data. On the other hand, the application must generate
and deliver the data ahead of the timestamp. The amount by
which data is computed early must be at least as large as
the worst-case latency to avoid timing problems.
Latency is even more important in audio applications. If an
application lets an audio output buffer underflow, an audible
pop or click is produced. Audio input buffers can overflow,
causing data to be lost. In general the audio buffers must
be large enough to buffer the worst-case latency that the
application will encounter.
This program measures latency by recording the difference
between the scheduled callback time and the current real time.
We do not really know the scheduled callback time, so we will
record the differences between the real time of each callback
and the real time of the previous callback. Differences that
are larger than the scheduled difference are recorded. Smaller
differences indicate the system is recovering from an earlier
latency, so these are ignored.
Since printing by the callback process can cause all sorts of
delays, this program records latency observations in a
histogram. When the program is stopped, the histogram is
printed to the console.
Optionally the system can be tested under a load of MIDI input,
MIDI output, or both. If MIDI input is selected, the callback
thread will read any waiting MIDI events each iteration. You
must generate events on this interface for the test to actually
put any appreciable load on PortMidi. If MIDI output is
selected, alternating note on and note off events are sent each
X iterations, where you specify X. For example, with a timer
callback period of 2ms and X=1, a MIDI event is sent every 2ms.
INTERPRETING RESULTS: Time is quantized to 1ms, so there is
some uncertainty due to rounding. A microsecond latency that
spans the time when the clock is incremented will be reported
as a latency of 1. On the other hand, a latency of almost
1ms that falls between two clock ticks will be reported as
zero. In general, if the highest nonzero bin is numbered N,
then the maximum latency is N+1.
CHANGE LOG
18-Jul-03 Mark Nelson -- Added code to generate MIDI or receive
MIDI during test, and made period user-settable.
*/
#define HIST_LEN 21 /* how many 1ms bins in the histogram */
#define STRING_MAX 80 /* used for console input */
#define INPUT_BUFFER_SIZE 100
#define OUTPUT_BUFFER_SIZE 0
#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef min
#define min(a, b) ((a) <= (b) ? (a) : (b))
#endif
int get_number(char *prompt);
PtTimestamp previous_callback_time = 0;
int period; /* milliseconds per callback */
int histogram[HIST_LEN];
int max_latency = 0; /* worst latency observed */
int out_of_range = 0; /* how many points outside of HIST_LEN? */
int test_in, test_out; /* test MIDI in and/or out? */
int output_period; /* output MIDI every __ iterations if test_out true */
int iteration = 0;
PmStream *in, *out;
int note_on = 0; /* is the note currently on? */
/* callback function for PortTime -- computes histogram */
void pt_callback(PtTimestamp timestamp, void *userData)
{
PtTimestamp difference = timestamp - previous_callback_time - period;
previous_callback_time = timestamp;
/* allow 5 seconds for the system to settle down */
if (timestamp < 5000) return;
iteration++;
/* 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);
if (note_on) {
/* note off */
buffer[0].message = Pm_Message(0x90, 60, 0);
note_on = 0;
} else {
/* note on */
buffer[0].message = Pm_Message(0x90, 60, 100);
note_on = 1;
}
Pm_Write(out, buffer, 1);
iteration = 0;
}
/* read all waiting events (if user requested) */
if (test_in) {
PmError status;
PmEvent buffer[1];
do {
status = Pm_Poll(in);
if (status == TRUE) {
Pm_Read(in,buffer,1);
}
} while (status == TRUE);
}
if (difference < 0) return; /* ignore when system is "catching up" */
/* update the histogram */
if (difference < HIST_LEN) {
histogram[difference]++;
} else {
out_of_range++;
}
if (max_latency < difference) max_latency = difference;
}
int main()
{
char line[STRING_MAX];
int i;
int len;
int choice;
PtTimestamp stop;
printf("Latency histogram.\n");
period = 0;
while (period < 1) {
period = get_number("Choose timer period (in ms, >= 1): ");
}
printf("Benchmark with:\n\t%s\n\t%s\n\t%s\n\t%s\n",
"1. No MIDI traffic",
"2. MIDI input",
"3. MIDI output",
"4. MIDI input and output");
choice = get_number("? ");
switch (choice) {
case 1: test_in = 0; test_out = 0; break;
case 2: test_in = 1; test_out = 0; break;
case 3: test_in = 0; test_out = 1; break;
case 4: test_in = 1; test_out = 1; break;
default: assert(0);
}
if (test_in || test_out) {
/* list device information */
for (i = 0; i < Pm_CountDevices(); i++) {
const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
if ((test_in && info->input) ||
(test_out && info->output)) {
printf("%d: %s, %s", i, info->interf, info->name);
if (info->input) printf(" (input)");
if (info->output) printf(" (output)");
printf("\n");
}
}
/* open stream(s) */
if (test_in) {
int i = get_number("MIDI input device number: ");
Pm_OpenInput(&in,
i,
NULL,
INPUT_BUFFER_SIZE,
(PmTimestamp (*)(void *)) Pt_Time,
NULL);
/* turn on filtering; otherwise, input might overflow in the
5-second period before timer callback starts reading midi */
Pm_SetFilter(in, PM_FILT_ACTIVE | PM_FILT_CLOCK);
}
if (test_out) {
int i = get_number("MIDI output device number: ");
PmEvent buffer[1];
Pm_OpenOutput(&out,
i,
NULL,
OUTPUT_BUFFER_SIZE,
(PmTimestamp (*)(void *)) Pt_Time,
NULL,
0); /* no latency scheduling */
/* send a program change to force a status byte -- this fixes
a problem with a buggy linux MidiSport driver, and shouldn't
hurt anything else
*/
buffer[0].timestamp = 0;
buffer[0].message = Pm_Message(0xC0, 0, 0); /* program change */
Pm_Write(out, buffer, 1);
output_period = get_number(
"MIDI out should be sent every __ callback iterations: ");
assert(output_period >= 1);
}
}
printf("%s%s", "Latency measurements will start in 5 seconds. ",
"Type return to stop: ");
Pt_Start(period, &pt_callback, 0);
fgets(line, STRING_MAX, stdin);
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].message = Pm_Message(0x90, 60, 0);
Pm_Write(out, buffer, 1);
}
/* print the histogram */
printf("Duration of test: %g seconds\n\n", max(0, stop - 5000) * 0.001);
printf("Latency(ms) Number of occurrences\n");
/* avoid printing beyond last non-zero histogram entry */
len = min(HIST_LEN, max_latency + 1);
for (i = 0; i < len; i++) {
printf("%2d %10d\n", i, histogram[i]);
}
printf("Number of points greater than %dms: %d\n",
HIST_LEN - 1, out_of_range);
printf("Maximum latency: %d milliseconds\n", max_latency);
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);
if(choice == 2)
Pm_Close(in);
else if(choice == 3)
Pm_Close(out);
else if(choice == 4)
{
Pm_Close(in);
Pm_Close(out);
}
return 0;
}
/* read a number from console */
int get_number(char *prompt)
{
char line[STRING_MAX];
int n = 0, i;
printf(prompt);
while (n != 1) {
n = scanf("%d", &i);
fgets(line, STRING_MAX, stdin);
}
return i;
}

148
3rdparty/portmidi/pm_test/latency.vcproj vendored Normal file
View File

@ -0,0 +1,148 @@
<?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=\&quot;Debug\&quot;"
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=\&quot;Debug\&quot;"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="WIN32,_WINDOWS,_DEBUG,PM_CHECK_ERRORS=1,DEBUG,CMAKE_INTDIR=\&quot;Debug\&quot;"
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=\&quot;Release\&quot;"
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=\&quot;Release\&quot;"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="WIN32,_WINDOWS,NDEBUG,CMAKE_INTDIR=\&quot;Release\&quot;"
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>

Some files were not shown because too many files have changed in this diff Show More