diff options
Diffstat (limited to 'portmidi/pm_common')
| -rw-r--r-- | portmidi/pm_common/CMakeLists.txt | 167 | ||||
| -rwxr-xr-x | portmidi/pm_common/pminternal.h | 190 | ||||
| -rwxr-xr-x | portmidi/pm_common/pmutil.c | 284 | ||||
| -rwxr-xr-x | portmidi/pm_common/pmutil.h | 184 | ||||
| -rwxr-xr-x | portmidi/pm_common/portmidi.c | 1472 | ||||
| -rwxr-xr-x | portmidi/pm_common/portmidi.h | 974 |
6 files changed, 3271 insertions, 0 deletions
diff --git a/portmidi/pm_common/CMakeLists.txt b/portmidi/pm_common/CMakeLists.txt new file mode 100644 index 0000000..1ad54ad --- /dev/null +++ b/portmidi/pm_common/CMakeLists.txt | |||
| @@ -0,0 +1,167 @@ | |||
| 1 | # pm_common/CMakeLists.txt -- how to build portmidi library | ||
| 2 | |||
| 3 | # creates the portmidi library | ||
| 4 | # exports PM_NEEDED_LIBS to parent. It seems that PM_NEEDED_LIBS for | ||
| 5 | # Linux should include Thread::Thread and ALSA::ALSA, but these | ||
| 6 | # are not visible in other CMake files, even though the portmidi | ||
| 7 | # target is. Therefore, Thread::Thread is replaced by | ||
| 8 | # CMAKE_THREAD_LIBS_INIT and ALSA::ALSA is replaced by ALSA_LIBRARIES. | ||
| 9 | # Is there a better way to do this? Maybe this whole file should be | ||
| 10 | # at the parent level. | ||
| 11 | |||
| 12 | # Support alternative name for static libraries to avoid confusion. | ||
| 13 | # (In particular, Xcode has automatically converted portmidi.a to | ||
| 14 | # portmidi.dylib without warning, so using portmidi-static.a eliminates | ||
| 15 | # this possibility, but default for all libs is "portmidi"): | ||
| 16 | set(PM_STATIC_LIB_NAME "portmidi" CACHE STRING | ||
| 17 | "For static builds, the PortMidi library name, e.g. portmidi-static. | ||
| 18 | Default is portmidi") | ||
| 19 | set(PM_ACTUAL_LIB_NAME "portmidi") | ||
| 20 | if(NOT BUILD_SHARED_LIBS) | ||
| 21 | set(PM_ACTUAL_LIB_NAME ${PM_STATIC_LIB_NAME}) | ||
| 22 | endif() | ||
| 23 | |||
| 24 | # set the build directory for libportmidi.a to be in portmidi, not in | ||
| 25 | # portmidi/pm_common. Must be done here BEFORE add_library below. | ||
| 26 | if(APPLE OR WIN32) | ||
| 27 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) | ||
| 28 | # set the build directory for .dylib libraries | ||
| 29 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) | ||
| 30 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) | ||
| 31 | endif(APPLE OR WIN32) | ||
| 32 | |||
| 33 | # we need full paths to sources because they are shared with other targets | ||
| 34 | # (in particular pmjni). Set PMDIR to the top-level portmidi directory: | ||
| 35 | get_filename_component(PMDIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) | ||
| 36 | set(PM_LIB_PUBLIC_SRC ${PMDIR}/pm_common/portmidi.c | ||
| 37 | ${PMDIR}/pm_common/pmutil.c | ||
| 38 | ${PMDIR}/porttime/porttime.c) | ||
| 39 | add_library(portmidi ${PM_LIB_PUBLIC_SRC}) | ||
| 40 | |||
| 41 | # MSVCRT_DLL is "DLL" for shared runtime library, and "" for static: | ||
| 42 | set_target_properties(portmidi PROPERTIES | ||
| 43 | VERSION ${LIBRARY_VERSION} | ||
| 44 | SOVERSION ${LIBRARY_SOVERSION} | ||
| 45 | OUTPUT_NAME "${PM_ACTUAL_LIB_NAME}" | ||
| 46 | MSVC_RUNTIME_LIBRARY | ||
| 47 | "MultiThreaded$<$<CONFIG:Debug>:Debug>${MSVCRT_DLL}" | ||
| 48 | WINDOWS_EXPORT_ALL_SYMBOLS TRUE) | ||
| 49 | target_include_directories(portmidi PUBLIC | ||
| 50 | $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> | ||
| 51 | $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>) | ||
| 52 | |||
| 53 | |||
| 54 | option(PM_CHECK_ERRORS | ||
| 55 | "Insert a check for error return values at the end of each PortMidi function. | ||
| 56 | If an error is encountered, a text message is printed using printf(), the user | ||
| 57 | is asked to type ENTER, and then exit(-1) is called to clean up and terminate | ||
| 58 | the program. | ||
| 59 | |||
| 60 | You should not use PM_CHECK_ERRORS if printf() does not work (e.g. this is not | ||
| 61 | a console application under Windows, or there is no visible console on some | ||
| 62 | other OS), and you should not use PM_CHECK_ERRORS if you intend to recover | ||
| 63 | from errors rather than abruptly terminate the program." OFF) | ||
| 64 | if(PM_CHECK_ERRORS) | ||
| 65 | target_compile_definitions(portmidi PRIVATE PM_CHECK_ERRORS) | ||
| 66 | endif(PM_CHECK_ERRORS) | ||
| 67 | |||
| 68 | macro(prepend_path RESULT PATH) | ||
| 69 | set(${RESULT}) | ||
| 70 | foreach(FILE ${ARGN}) | ||
| 71 | list(APPEND ${RESULT} "${PATH}${FILE}") | ||
| 72 | endforeach(FILE) | ||
| 73 | endmacro(prepend_path) | ||
| 74 | |||
| 75 | # UNIX needs pthread library | ||
| 76 | if(NOT WIN32) | ||
| 77 | set(THREADS_PREFER_PTHREAD_FLAG ON) | ||
| 78 | find_package(Threads REQUIRED) | ||
| 79 | endif() | ||
| 80 | |||
| 81 | # Check for sndio | ||
| 82 | if(USE_SNDIO) | ||
| 83 | include (FindPackageHandleStandardArgs) | ||
| 84 | find_path(SNDIO_INCLUDE_DIRS NAMES sndio.h) | ||
| 85 | find_library(SNDIO_LIBRARY sndio) | ||
| 86 | find_package_handle_standard_args(Sndio | ||
| 87 | REQUIRED_VARS SNDIO_LIBRARY SNDIO_INCLUDE_DIRS) | ||
| 88 | endif(USE_SNDIO) | ||
| 89 | |||
| 90 | # first include the appropriate system-dependent file: | ||
| 91 | if(SNDIO_FOUND AND USE_SNDIO) | ||
| 92 | set(PM_LIB_PRIVATE_SRC | ||
| 93 | ${PMDIR}/porttime/ptlinux.c | ||
| 94 | ${PMDIR}/pm_sndio/pmsndio.c) | ||
| 95 | set(PM_NEEDED_LIBS Threads::Threads ${SNDIO_LIBRARY} PARENT_SCOPE) | ||
| 96 | target_link_libraries(portmidi PRIVATE Threads::Threads ${SNDIO_LIBRARY}) | ||
| 97 | target_include_directories(portmidi PRIVATE ${SNDIO_INCLUDE_DIRS}) | ||
| 98 | elseif(UNIX AND APPLE) | ||
| 99 | set(Threads::Threads "" PARENT_SCOPE) | ||
| 100 | set(PM_LIB_PRIVATE_SRC | ||
| 101 | ${PMDIR}/porttime/ptmacosx_mach.c | ||
| 102 | ${PMDIR}/pm_mac/pmmac.c | ||
| 103 | ${PMDIR}/pm_mac/pmmacosxcm.c) | ||
| 104 | set(PM_NEEDED_LIBS | ||
| 105 | ${CMAKE_THREAD_LIBS_INIT} | ||
| 106 | -Wl,-framework,CoreAudio | ||
| 107 | -Wl,-framework,CoreFoundation | ||
| 108 | -Wl,-framework,CoreMidi | ||
| 109 | -Wl,-framework,CoreServices | ||
| 110 | PARENT_SCOPE) | ||
| 111 | target_link_libraries(portmidi PRIVATE | ||
| 112 | Threads::Threads | ||
| 113 | -Wl,-framework,CoreAudio | ||
| 114 | -Wl,-framework,CoreFoundation | ||
| 115 | -Wl,-framework,CoreMidi | ||
| 116 | -Wl,-framework,CoreServices | ||
| 117 | ) | ||
| 118 | # set to CMake default; is this right?: | ||
| 119 | set_target_properties(portmidi PROPERTIES MACOSX_RPATH ON) | ||
| 120 | elseif(HAIKU) | ||
| 121 | set(PM_LIB_PRIVATE_SRC | ||
| 122 | ${PMDIR}/porttime/pthaiku.cpp | ||
| 123 | ${PMDIR}/pm_haiku/pmhaiku.cpp) | ||
| 124 | set(PM_NEEDED_LIBS be midi midi2 PARENT_SCOPE) | ||
| 125 | target_link_libraries(portmidi PRIVATE be midi midi2) | ||
| 126 | elseif(UNIX) | ||
| 127 | target_compile_definitions(portmidi PRIVATE ${LINUX_FLAGS}) | ||
| 128 | set(PM_LIB_PRIVATE_SRC | ||
| 129 | ${PMDIR}/porttime/ptlinux.c | ||
| 130 | ${PMDIR}/pm_linux/pmlinux.c | ||
| 131 | ${PMDIR}/pm_linux/pmlinuxnull.c) | ||
| 132 | if(${LINUX_DEFINES} MATCHES ".*PMALSA.*") | ||
| 133 | # Note that ALSA is not required if PMNULL is defined -- PortMidi will then | ||
| 134 | # compile without ALSA and report no MIDI devices. Later, PMSNDIO or PMJACK | ||
| 135 | # might be additional options. | ||
| 136 | find_package(ALSA REQUIRED) | ||
| 137 | list(APPEND PM_LIB_PRIVATE_SRC ${PMDIR}/pm_linux/pmlinuxalsa.c) | ||
| 138 | set(PM_NEEDED_LIBS ${CMAKE_THREAD_LIBS_INIT} ${ALSA_LIBRARIES} PARENT_SCOPE) | ||
| 139 | target_link_libraries(portmidi PRIVATE Threads::Threads ALSA::ALSA) | ||
| 140 | set(PKGCONFIG_REQUIRES_PRIVATE "alsa" PARENT_SCOPE) | ||
| 141 | else() | ||
| 142 | message(WARNING "No PMALSA, so PortMidi will not use ALSA, " | ||
| 143 | "and will not find or open MIDI devices.") | ||
| 144 | set(PM_NEEDED_LIBS ${CMAKE_THREAD_LIBS_INIT} PARENT_SCOPE) | ||
| 145 | target_link_libraries(portmidi PRIVATE Threads::Threads) | ||
| 146 | endif() | ||
| 147 | elseif(WIN32) | ||
| 148 | set(PM_LIB_PRIVATE_SRC | ||
| 149 | ${PMDIR}/porttime/ptwinmm.c | ||
| 150 | ${PMDIR}/pm_win/pmwin.c | ||
| 151 | ${PMDIR}/pm_win/pmwinmm.c) | ||
| 152 | set(PM_NEEDED_LIBS winmm PARENT_SCOPE) | ||
| 153 | target_link_libraries(portmidi PRIVATE winmm) | ||
| 154 | # if(NOT BUILD_SHARED_LIBS AND PM_USE_STATIC_RUNTIME) | ||
| 155 | # /MDd is multithread debug DLL, /MTd is multithread debug | ||
| 156 | # /MD is multithread DLL, /MT is multithread. Change to static: | ||
| 157 | # include(../pm_win/static.cmake) | ||
| 158 | # endif() | ||
| 159 | else() | ||
| 160 | message(FATAL_ERROR "Operating system not supported.") | ||
| 161 | endif() | ||
| 162 | |||
| 163 | set(PM_LIB_PUBLIC_SRC ${PM_LIB_PUBLIC_SRC} PARENT_SCOPE) # export to parent | ||
| 164 | set(PM_LIB_PRIVATE_SRC ${PM_LIB_PRIVATE_SRC} PARENT_SCOPE) # export to parent | ||
| 165 | |||
| 166 | target_sources(portmidi PRIVATE ${PM_LIB_PRIVATE_SRC}) | ||
| 167 | |||
diff --git a/portmidi/pm_common/pminternal.h b/portmidi/pm_common/pminternal.h new file mode 100755 index 0000000..8b3d8f5 --- /dev/null +++ b/portmidi/pm_common/pminternal.h | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | /** @file pminternal.h header for PortMidi implementations */ | ||
| 2 | |||
| 3 | /* this file is included by files that implement library internals */ | ||
| 4 | /* Here is a guide to implementers: | ||
| 5 | provide an initialization function similar to pm_winmm_init() | ||
| 6 | add your initialization function to pm_init() | ||
| 7 | Note that your init function should never require not-standard | ||
| 8 | libraries or fail in any way. If the interface is not available, | ||
| 9 | simply do not call pm_add_device. This means that non-standard | ||
| 10 | libraries should try to do dynamic linking at runtime using a DLL | ||
| 11 | and return without error if the DLL cannot be found or if there | ||
| 12 | is any other failure. | ||
| 13 | implement functions as indicated in pm_fns_type to open, read, write, | ||
| 14 | close, etc. | ||
| 15 | call pm_add_device() for each input and output device, passing it a | ||
| 16 | pm_fns_type structure. | ||
| 17 | assumptions about pm_fns_type functions are given below. | ||
| 18 | */ | ||
| 19 | |||
| 20 | /** @cond INTERNAL - add INTERNAL to Doxygen ENABLED_SECTIONS to include */ | ||
| 21 | |||
| 22 | #ifdef __cplusplus | ||
| 23 | extern "C" { | ||
| 24 | #endif | ||
| 25 | |||
| 26 | extern int pm_initialized; /* see note in portmidi.c */ | ||
| 27 | extern PmDeviceID pm_default_input_device_id; | ||
| 28 | extern PmDeviceID pm_default_output_device_id; | ||
| 29 | |||
| 30 | /* these are defined in system-specific file */ | ||
| 31 | void *pm_alloc(size_t s); | ||
| 32 | void pm_free(void *ptr); | ||
| 33 | |||
| 34 | /* if a host error (an error reported by the host MIDI API that is not | ||
| 35 | * mapped to a PortMidi error code) occurs in a synchronous operation | ||
| 36 | * (i.e., not in a callback from another thread) set these: */ | ||
| 37 | extern int pm_hosterror; /* boolean */ | ||
| 38 | extern char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN]; | ||
| 39 | |||
| 40 | struct pm_internal_struct; | ||
| 41 | |||
| 42 | /* these do not use PmInternal because it is not defined yet... */ | ||
| 43 | typedef PmError (*pm_write_short_fn)(struct pm_internal_struct *midi, | ||
| 44 | PmEvent *buffer); | ||
| 45 | typedef PmError (*pm_begin_sysex_fn)(struct pm_internal_struct *midi, | ||
| 46 | PmTimestamp timestamp); | ||
| 47 | typedef PmError (*pm_end_sysex_fn)(struct pm_internal_struct *midi, | ||
| 48 | PmTimestamp timestamp); | ||
| 49 | typedef PmError (*pm_write_byte_fn)(struct pm_internal_struct *midi, | ||
| 50 | unsigned char byte, PmTimestamp timestamp); | ||
| 51 | typedef PmError (*pm_write_realtime_fn)(struct pm_internal_struct *midi, | ||
| 52 | PmEvent *buffer); | ||
| 53 | typedef PmError (*pm_write_flush_fn)(struct pm_internal_struct *midi, | ||
| 54 | PmTimestamp timestamp); | ||
| 55 | typedef PmTimestamp (*pm_synchronize_fn)(struct pm_internal_struct *midi); | ||
| 56 | /* pm_open_fn should clean up all memory and close the device if any part | ||
| 57 | of the open fails */ | ||
| 58 | typedef PmError (*pm_open_fn)(struct pm_internal_struct *midi, | ||
| 59 | void *driverInfo); | ||
| 60 | typedef PmError (*pm_create_fn)(int is_input, const char *name, | ||
| 61 | void *driverInfo); | ||
| 62 | typedef PmError (*pm_delete_fn)(PmDeviceID id); | ||
| 63 | typedef PmError (*pm_abort_fn)(struct pm_internal_struct *midi); | ||
| 64 | /* pm_close_fn should clean up all memory and close the device if any | ||
| 65 | part of the close fails. */ | ||
| 66 | typedef PmError (*pm_close_fn)(struct pm_internal_struct *midi); | ||
| 67 | typedef PmError (*pm_poll_fn)(struct pm_internal_struct *midi); | ||
| 68 | typedef unsigned int (*pm_check_host_error_fn)(struct pm_internal_struct *midi); | ||
| 69 | |||
| 70 | typedef struct { | ||
| 71 | pm_write_short_fn write_short; /* output short MIDI msg */ | ||
| 72 | pm_begin_sysex_fn begin_sysex; /* prepare to send a sysex message */ | ||
| 73 | pm_end_sysex_fn end_sysex; /* marks end of sysex message */ | ||
| 74 | pm_write_byte_fn write_byte; /* accumulate one more sysex byte */ | ||
| 75 | pm_write_realtime_fn write_realtime; /* send real-time msg within sysex */ | ||
| 76 | pm_write_flush_fn write_flush; /* send any accumulated but unsent data */ | ||
| 77 | pm_synchronize_fn synchronize; /* synchronize PM time to stream time */ | ||
| 78 | pm_open_fn open; /* open MIDI device */ | ||
| 79 | pm_abort_fn abort; /* abort */ | ||
| 80 | pm_close_fn close; /* close device */ | ||
| 81 | pm_poll_fn poll; /* read pending midi events into portmidi buffer */ | ||
| 82 | pm_check_host_error_fn check_host_error; /* true when device has had host */ | ||
| 83 | /* error; sets pm_hosterror and writes message to pm_hosterror_text */ | ||
| 84 | } pm_fns_node, *pm_fns_type; | ||
| 85 | |||
| 86 | |||
| 87 | /* when open fails, the dictionary gets this set of functions: */ | ||
| 88 | extern pm_fns_node pm_none_dictionary; | ||
| 89 | |||
| 90 | typedef struct { | ||
| 91 | PmDeviceInfo pub; /* some portmidi state also saved in here (for automatic | ||
| 92 | device closing -- see PmDeviceInfo struct) */ | ||
| 93 | int deleted; /* is this is a deleted virtual device? */ | ||
| 94 | void *descriptor; /* ID number passed to win32 multimedia API open, | ||
| 95 | * coreMIDI endpoint, etc., representing the device */ | ||
| 96 | struct pm_internal_struct *pm_internal; /* points to PmInternal device */ | ||
| 97 | /* when the device is open, allows automatic device closing */ | ||
| 98 | pm_fns_type dictionary; | ||
| 99 | } descriptor_node, *descriptor_type; | ||
| 100 | |||
| 101 | extern int pm_descriptor_max; | ||
| 102 | extern descriptor_type pm_descriptors; | ||
| 103 | extern int pm_descriptor_len; | ||
| 104 | |||
| 105 | typedef uint32_t (*time_get_proc_type)(void *time_info); | ||
| 106 | |||
| 107 | typedef struct pm_internal_struct { | ||
| 108 | int device_id; /* which device is open (index to pm_descriptors) */ | ||
| 109 | short is_input; /* MIDI IN (true) or MIDI OUT (false) */ | ||
| 110 | short is_removed; /* MIDI device was removed */ | ||
| 111 | PmTimeProcPtr time_proc; /* where to get the time */ | ||
| 112 | void *time_info; /* pass this to get_time() */ | ||
| 113 | int32_t buffer_len; /* how big is the buffer or queue? */ | ||
| 114 | PmQueue *queue; | ||
| 115 | |||
| 116 | int32_t latency; /* time delay in ms between timestamps and actual output */ | ||
| 117 | /* set to zero to get immediate, simple blocking output */ | ||
| 118 | /* if latency is zero, timestamps will be ignored; */ | ||
| 119 | /* if midi input device, this field ignored */ | ||
| 120 | |||
| 121 | int sysex_in_progress; /* when sysex status is seen, this flag becomes | ||
| 122 | * true until EOX is seen. When true, new data is appended to the | ||
| 123 | * stream of outgoing bytes. When overflow occurs, sysex data is | ||
| 124 | * dropped (until an EOX or non-real-timei status byte is seen) so | ||
| 125 | * that, if the overflow condition is cleared, we don't start | ||
| 126 | * sending data from the middle of a sysex message. If a sysex | ||
| 127 | * message is filtered, sysex_in_progress is false, causing the | ||
| 128 | * message to be dropped. */ | ||
| 129 | PmMessage message; /* buffer for 4 bytes of sysex data */ | ||
| 130 | int message_count; /* how many bytes in sysex_message so far */ | ||
| 131 | int short_message_count; /* how many bytes are expected in short message */ | ||
| 132 | unsigned char running_status; /* running status byte or zero if none */ | ||
| 133 | int32_t filters; /* flags that filter incoming message classes */ | ||
| 134 | int32_t channel_mask; /* filter incoming messages based on channel */ | ||
| 135 | PmTimestamp last_msg_time; /* timestamp of last message */ | ||
| 136 | PmTimestamp sync_time; /* time of last synchronization */ | ||
| 137 | PmTimestamp now; /* set by PmWrite to current time */ | ||
| 138 | int first_message; /* initially true, used to run first synchronization */ | ||
| 139 | pm_fns_type dictionary; /* implementation functions */ | ||
| 140 | void *api_info; /* system-dependent state */ | ||
| 141 | /* the following are used to expedite sysex data */ | ||
| 142 | /* on windows, in debug mode, based on some profiling, these optimizations | ||
| 143 | * cut the time to process sysex bytes from about 7.5 to 0.26 usec/byte, | ||
| 144 | * but this does not count time in the driver, so I don't know if it is | ||
| 145 | * important | ||
| 146 | */ | ||
| 147 | unsigned char *fill_base; /* addr of ptr to sysex data */ | ||
| 148 | uint32_t *fill_offset_ptr; /* offset of next sysex byte */ | ||
| 149 | uint32_t fill_length; /* how many sysex bytes to write */ | ||
| 150 | } PmInternal; | ||
| 151 | |||
| 152 | /* what is the length of this short message? */ | ||
| 153 | int pm_midi_length(PmMessage msg); | ||
| 154 | |||
| 155 | /* defined by system specific implementation, e.g. pmwinmm, used by PortMidi */ | ||
| 156 | void pm_init(void); | ||
| 157 | void pm_term(void); | ||
| 158 | |||
| 159 | /* defined by portMidi, used by pmwinmm */ | ||
| 160 | PmError none_write_short(PmInternal *midi, PmEvent *buffer); | ||
| 161 | PmError none_write_byte(PmInternal *midi, unsigned char byte, | ||
| 162 | PmTimestamp timestamp); | ||
| 163 | PmTimestamp none_synchronize(PmInternal *midi); | ||
| 164 | |||
| 165 | PmError pm_fail_fn(PmInternal *midi); | ||
| 166 | PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp); | ||
| 167 | PmError pm_success_fn(PmInternal *midi); | ||
| 168 | PmError pm_add_interf(char *interf, pm_create_fn create_fn, | ||
| 169 | pm_delete_fn delete_fn); | ||
| 170 | PmError pm_add_device(char *interf, const char *name, int is_input, | ||
| 171 | int is_virtual, void *descriptor, pm_fns_type dictionary); | ||
| 172 | void pm_undo_add_device(int id); | ||
| 173 | uint32_t pm_read_bytes(PmInternal *midi, const unsigned char *data, int len, | ||
| 174 | PmTimestamp timestamp); | ||
| 175 | void pm_read_short(PmInternal *midi, PmEvent *event); | ||
| 176 | |||
| 177 | #define none_write_flush pm_fail_timestamp_fn | ||
| 178 | #define none_sysex pm_fail_timestamp_fn | ||
| 179 | #define none_poll pm_fail_fn | ||
| 180 | #define success_poll pm_success_fn | ||
| 181 | |||
| 182 | #define MIDI_REALTIME_MASK 0xf8 | ||
| 183 | #define is_real_time(msg) \ | ||
| 184 | ((Pm_MessageStatus(msg) & MIDI_REALTIME_MASK) == MIDI_REALTIME_MASK) | ||
| 185 | |||
| 186 | #ifdef __cplusplus | ||
| 187 | } | ||
| 188 | #endif | ||
| 189 | |||
| 190 | /** @endcond */ | ||
diff --git a/portmidi/pm_common/pmutil.c b/portmidi/pm_common/pmutil.c new file mode 100755 index 0000000..a70fe2f --- /dev/null +++ b/portmidi/pm_common/pmutil.c | |||
| @@ -0,0 +1,284 @@ | |||
| 1 | /* pmutil.c -- some helpful utilities for building midi | ||
| 2 | applications that use PortMidi | ||
| 3 | */ | ||
| 4 | #include <stdlib.h> | ||
| 5 | #include <assert.h> | ||
| 6 | #include <string.h> | ||
| 7 | #include "portmidi.h" | ||
| 8 | #include "pmutil.h" | ||
| 9 | #include "pminternal.h" | ||
| 10 | |||
| 11 | #ifdef WIN32 | ||
| 12 | #define bzero(addr, siz) memset(addr, 0, siz) | ||
| 13 | #endif | ||
| 14 | |||
| 15 | // #define QUEUE_DEBUG 1 | ||
| 16 | #ifdef QUEUE_DEBUG | ||
| 17 | #include "stdio.h" | ||
| 18 | #endif | ||
| 19 | |||
| 20 | typedef struct { | ||
| 21 | long head; | ||
| 22 | long tail; | ||
| 23 | long len; | ||
| 24 | long overflow; | ||
| 25 | int32_t msg_size; /* number of int32_t in a message including extra word */ | ||
| 26 | int32_t peek_overflow; | ||
| 27 | int32_t *buffer; | ||
| 28 | int32_t *peek; | ||
| 29 | int32_t peek_flag; | ||
| 30 | } PmQueueRep; | ||
| 31 | |||
| 32 | |||
| 33 | PMEXPORT PmQueue *Pm_QueueCreate(long num_msgs, int32_t bytes_per_msg) | ||
| 34 | { | ||
| 35 | int32_t int32s_per_msg = | ||
| 36 | (int32_t) (((bytes_per_msg + sizeof(int32_t) - 1) & | ||
| 37 | ~(sizeof(int32_t) - 1)) / sizeof(int32_t)); | ||
| 38 | PmQueueRep *queue = (PmQueueRep *) pm_alloc(sizeof(PmQueueRep)); | ||
| 39 | if (!queue) /* memory allocation failed */ | ||
| 40 | return NULL; | ||
| 41 | |||
| 42 | /* need extra word per message for non-zero encoding */ | ||
| 43 | queue->len = num_msgs * (int32s_per_msg + 1); | ||
| 44 | queue->buffer = (int32_t *) pm_alloc(queue->len * sizeof(int32_t)); | ||
| 45 | bzero(queue->buffer, queue->len * sizeof(int32_t)); | ||
| 46 | if (!queue->buffer) { | ||
| 47 | pm_free(queue); | ||
| 48 | return NULL; | ||
| 49 | } else { /* allocate the "peek" buffer */ | ||
| 50 | queue->peek = (int32_t *) pm_alloc(int32s_per_msg * sizeof(int32_t)); | ||
| 51 | if (!queue->peek) { | ||
| 52 | /* free everything allocated so far and return */ | ||
| 53 | pm_free(queue->buffer); | ||
| 54 | pm_free(queue); | ||
| 55 | return NULL; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | bzero(queue->buffer, queue->len * sizeof(int32_t)); | ||
| 59 | queue->head = 0; | ||
| 60 | queue->tail = 0; | ||
| 61 | /* msg_size is in words */ | ||
| 62 | queue->msg_size = int32s_per_msg + 1; /* note extra word is counted */ | ||
| 63 | queue->overflow = FALSE; | ||
| 64 | queue->peek_overflow = FALSE; | ||
| 65 | queue->peek_flag = FALSE; | ||
| 66 | return queue; | ||
| 67 | } | ||
| 68 | |||
| 69 | |||
| 70 | PMEXPORT PmError Pm_QueueDestroy(PmQueue *q) | ||
| 71 | { | ||
| 72 | PmQueueRep *queue = (PmQueueRep *) q; | ||
| 73 | |||
| 74 | /* arg checking */ | ||
| 75 | if (!queue || !queue->buffer || !queue->peek) | ||
| 76 | return pmBadPtr; | ||
| 77 | |||
| 78 | pm_free(queue->peek); | ||
| 79 | pm_free(queue->buffer); | ||
| 80 | pm_free(queue); | ||
| 81 | return pmNoError; | ||
| 82 | } | ||
| 83 | |||
| 84 | |||
| 85 | PMEXPORT PmError Pm_Dequeue(PmQueue *q, void *msg) | ||
| 86 | { | ||
| 87 | long head; | ||
| 88 | PmQueueRep *queue = (PmQueueRep *) q; | ||
| 89 | int i; | ||
| 90 | int32_t *msg_as_int32 = (int32_t *) msg; | ||
| 91 | |||
| 92 | /* arg checking */ | ||
| 93 | if (!queue) | ||
| 94 | return pmBadPtr; | ||
| 95 | /* a previous peek operation encountered an overflow, but the overflow | ||
| 96 | * has not yet been reported to client, so do it now. No message is | ||
| 97 | * returned, but on the next call, we will return the peek buffer. | ||
| 98 | */ | ||
| 99 | if (queue->peek_overflow) { | ||
| 100 | queue->peek_overflow = FALSE; | ||
| 101 | return pmBufferOverflow; | ||
| 102 | } | ||
| 103 | if (queue->peek_flag) { | ||
| 104 | memcpy(msg, queue->peek, (queue->msg_size - 1) * sizeof(int32_t)); | ||
| 105 | queue->peek_flag = FALSE; | ||
| 106 | return pmGotData; | ||
| 107 | } | ||
| 108 | |||
| 109 | head = queue->head; | ||
| 110 | /* if writer overflows, it writes queue->overflow = tail+1 so that | ||
| 111 | * when the reader gets to that position in the buffer, it can | ||
| 112 | * return the overflow condition to the reader. The problem is that | ||
| 113 | * at overflow, things have wrapped around, so tail == head, and the | ||
| 114 | * reader will detect overflow immediately instead of waiting until | ||
| 115 | * it reads everything in the buffer, wrapping around again to the | ||
| 116 | * point where tail == head. So the condition also checks that | ||
| 117 | * queue->buffer[head] is zero -- if so, then the buffer is now | ||
| 118 | * empty, and we're at the point in the msg stream where overflow | ||
| 119 | * occurred. It's time to signal overflow to the reader. If | ||
| 120 | * queue->buffer[head] is non-zero, there's a message there and we | ||
| 121 | * should read all the way around the buffer before signalling overflow. | ||
| 122 | * There is a write-order dependency here, but to fail, the overflow | ||
| 123 | * field would have to be written while an entire buffer full of | ||
| 124 | * writes are still pending. I'm assuming out-of-order writes are | ||
| 125 | * possible, but not that many. | ||
| 126 | */ | ||
| 127 | if (queue->overflow == head + 1 && !queue->buffer[head]) { | ||
| 128 | queue->overflow = 0; /* non-overflow condition */ | ||
| 129 | return pmBufferOverflow; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* test to see if there is data in the queue -- test from back | ||
| 133 | * to front so if writer is simultaneously writing, we don't | ||
| 134 | * waste time discovering the write is not finished | ||
| 135 | */ | ||
| 136 | for (i = queue->msg_size - 1; i >= 0; i--) { | ||
| 137 | if (!queue->buffer[head + i]) { | ||
| 138 | return pmNoData; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | memcpy(msg, (char *) &queue->buffer[head + 1], | ||
| 142 | sizeof(int32_t) * (queue->msg_size - 1)); | ||
| 143 | /* fix up zeros */ | ||
| 144 | i = queue->buffer[head]; | ||
| 145 | while (i < queue->msg_size) { | ||
| 146 | int32_t j; | ||
| 147 | i--; /* msg does not have extra word so shift down */ | ||
| 148 | j = msg_as_int32[i]; | ||
| 149 | msg_as_int32[i] = 0; | ||
| 150 | i = j; | ||
| 151 | } | ||
| 152 | /* signal that data has been removed by zeroing: */ | ||
| 153 | bzero((char *) &queue->buffer[head], sizeof(int32_t) * queue->msg_size); | ||
| 154 | |||
| 155 | /* update head */ | ||
| 156 | head += queue->msg_size; | ||
| 157 | if (head == queue->len) head = 0; | ||
| 158 | queue->head = head; | ||
| 159 | return pmGotData; /* success */ | ||
| 160 | } | ||
| 161 | |||
| 162 | |||
| 163 | |||
| 164 | PMEXPORT PmError Pm_SetOverflow(PmQueue *q) | ||
| 165 | { | ||
| 166 | PmQueueRep *queue = (PmQueueRep *) q; | ||
| 167 | long tail; | ||
| 168 | /* arg checking */ | ||
| 169 | if (!queue) | ||
| 170 | return pmBadPtr; | ||
| 171 | /* no more enqueue until receiver acknowledges overflow */ | ||
| 172 | if (queue->overflow) return pmBufferOverflow; | ||
| 173 | tail = queue->tail; | ||
| 174 | queue->overflow = tail + 1; | ||
| 175 | return pmBufferOverflow; | ||
| 176 | } | ||
| 177 | |||
| 178 | |||
| 179 | PMEXPORT PmError Pm_Enqueue(PmQueue *q, void *msg) | ||
| 180 | { | ||
| 181 | PmQueueRep *queue = (PmQueueRep *) q; | ||
| 182 | long tail; | ||
| 183 | int i; | ||
| 184 | int32_t *src = (int32_t *) msg; | ||
| 185 | int32_t *ptr; | ||
| 186 | int32_t *dest; | ||
| 187 | int rslt; | ||
| 188 | if (!queue) | ||
| 189 | return pmBadPtr; | ||
| 190 | /* no more enqueue until receiver acknowledges overflow */ | ||
| 191 | if (queue->overflow) return pmBufferOverflow; | ||
| 192 | rslt = Pm_QueueFull(q); | ||
| 193 | /* already checked above: if (rslt == pmBadPtr) return rslt; */ | ||
| 194 | tail = queue->tail; | ||
| 195 | if (rslt) { | ||
| 196 | queue->overflow = tail + 1; | ||
| 197 | return pmBufferOverflow; | ||
| 198 | } | ||
| 199 | |||
| 200 | /* queue is has room for message, and overflow flag is cleared */ | ||
| 201 | ptr = &queue->buffer[tail]; | ||
| 202 | dest = ptr + 1; | ||
| 203 | for (i = 1; i < queue->msg_size; i++) { | ||
| 204 | int32_t j = src[i - 1]; | ||
| 205 | if (!j) { | ||
| 206 | *ptr = i; | ||
| 207 | ptr = dest; | ||
| 208 | } else { | ||
| 209 | *dest = j; | ||
| 210 | } | ||
| 211 | dest++; | ||
| 212 | } | ||
| 213 | *ptr = i; | ||
| 214 | tail += queue->msg_size; | ||
| 215 | if (tail == queue->len) tail = 0; | ||
| 216 | queue->tail = tail; | ||
| 217 | return pmNoError; | ||
| 218 | } | ||
| 219 | |||
| 220 | |||
| 221 | PMEXPORT int Pm_QueueEmpty(PmQueue *q) | ||
| 222 | { | ||
| 223 | PmQueueRep *queue = (PmQueueRep *) q; | ||
| 224 | return (!queue) || /* null pointer -> return "empty" */ | ||
| 225 | (queue->buffer[queue->head] == 0 && !queue->peek_flag); | ||
| 226 | } | ||
| 227 | |||
| 228 | |||
| 229 | PMEXPORT int Pm_QueueFull(PmQueue *q) | ||
| 230 | { | ||
| 231 | long tail; | ||
| 232 | int i; | ||
| 233 | PmQueueRep *queue = (PmQueueRep *) q; | ||
| 234 | /* arg checking */ | ||
| 235 | if (!queue) | ||
| 236 | return pmBadPtr; | ||
| 237 | tail = queue->tail; | ||
| 238 | /* test to see if there is space in the queue */ | ||
| 239 | for (i = 0; i < queue->msg_size; i++) { | ||
| 240 | if (queue->buffer[tail + i]) { | ||
| 241 | return TRUE; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | return FALSE; | ||
| 245 | } | ||
| 246 | |||
| 247 | |||
| 248 | PMEXPORT void *Pm_QueuePeek(PmQueue *q) | ||
| 249 | { | ||
| 250 | PmError rslt; | ||
| 251 | int32_t temp; | ||
| 252 | PmQueueRep *queue = (PmQueueRep *) q; | ||
| 253 | /* arg checking */ | ||
| 254 | if (!queue) | ||
| 255 | return NULL; | ||
| 256 | |||
| 257 | if (queue->peek_flag) { | ||
| 258 | return queue->peek; | ||
| 259 | } | ||
| 260 | /* this is ugly: if peek_overflow is set, then Pm_Dequeue() | ||
| 261 | * returns immediately with pmBufferOverflow, but here, we | ||
| 262 | * want Pm_Dequeue() to really check for data. If data is | ||
| 263 | * there, we can return it | ||
| 264 | */ | ||
| 265 | temp = queue->peek_overflow; | ||
| 266 | queue->peek_overflow = FALSE; | ||
| 267 | rslt = Pm_Dequeue(q, queue->peek); | ||
| 268 | queue->peek_overflow = temp; | ||
| 269 | |||
| 270 | if (rslt == 1) { | ||
| 271 | queue->peek_flag = TRUE; | ||
| 272 | return queue->peek; | ||
| 273 | } else if (rslt == pmBufferOverflow) { | ||
| 274 | /* when overflow is indicated, the queue is empty and the | ||
| 275 | * first message that was dropped by Enqueue (signalling | ||
| 276 | * pmBufferOverflow to its caller) would have been the next | ||
| 277 | * message in the queue. Pm_QueuePeek will return NULL, but | ||
| 278 | * remember that an overflow occurred. (see Pm_Dequeue) | ||
| 279 | */ | ||
| 280 | queue->peek_overflow = TRUE; | ||
| 281 | } | ||
| 282 | return NULL; | ||
| 283 | } | ||
| 284 | |||
diff --git a/portmidi/pm_common/pmutil.h b/portmidi/pm_common/pmutil.h new file mode 100755 index 0000000..46c618e --- /dev/null +++ b/portmidi/pm_common/pmutil.h | |||
| @@ -0,0 +1,184 @@ | |||
| 1 | /** @file pmutil.h lock-free queue for building MIDI | ||
| 2 | applications with PortMidi. | ||
| 3 | |||
| 4 | PortMidi is not reentrant, and locks can suffer from priority | ||
| 5 | inversion. To support coordination between system callbacks, a | ||
| 6 | high-priority thread created with PortTime, and the main | ||
| 7 | application thread, PortMidi uses a lock-free, non-blocking | ||
| 8 | queue. The queue implementation is not particular to MIDI and is | ||
| 9 | available for other uses. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef PORTMIDI_PMUTIL_H | ||
| 13 | #define PORTMIDI_PMUTIL_H | ||
| 14 | |||
| 15 | #ifdef __cplusplus | ||
| 16 | extern "C" { | ||
| 17 | #endif /* __cplusplus */ | ||
| 18 | |||
| 19 | /** @defgroup grp_pmutil Lock-free Queue | ||
| 20 | @{ | ||
| 21 | */ | ||
| 22 | |||
| 23 | /** The queue representation is opaque. Declare a queue as PmQueue * */ | ||
| 24 | typedef void PmQueue; | ||
| 25 | |||
| 26 | /** create a single-reader, single-writer queue. | ||
| 27 | |||
| 28 | @param num_msgs the number of messages the queue can hold | ||
| 29 | |||
| 30 | @param the fixed message size | ||
| 31 | |||
| 32 | @return the allocated and initialized queue, or NULL if memory | ||
| 33 | cannot be allocated. Allocation uses #pm_malloc(). | ||
| 34 | |||
| 35 | The queue only accepts fixed sized messages. | ||
| 36 | |||
| 37 | This queue implementation uses the "light pipe" algorithm which | ||
| 38 | operates correctly even with multi-processors and out-of-order | ||
| 39 | memory writes. (see Alexander Dokumentov, "Lock-free Interprocess | ||
| 40 | Communication," Dr. Dobbs Portal, http://www.ddj.com/, | ||
| 41 | articleID=189401457, June 15, 2006. This algorithm requires that | ||
| 42 | messages be translated to a form where no words contain | ||
| 43 | zeros. Each word becomes its own "data valid" tag. Because of this | ||
| 44 | translation, we cannot return a pointer to data still in the queue | ||
| 45 | when the "peek" method is called. Instead, a buffer is | ||
| 46 | preallocated so that data can be copied there. Pm_QueuePeek() | ||
| 47 | dequeues a message into this buffer and returns a pointer to it. A | ||
| 48 | subsequent Pm_Dequeue() will copy from this buffer. | ||
| 49 | |||
| 50 | This implementation does not try to keep reader/writer data in | ||
| 51 | separate cache lines or prevent thrashing on cache lines. | ||
| 52 | However, this algorithm differs by doing inserts/removals in | ||
| 53 | units of messages rather than units of machine words. Some | ||
| 54 | performance improvement might be obtained by not clearing data | ||
| 55 | immediately after a read, but instead by waiting for the end | ||
| 56 | of the cache line, especially if messages are smaller than | ||
| 57 | cache lines. See the Dokumentov article for explanation. | ||
| 58 | |||
| 59 | The algorithm is extended to handle "overflow" reporting. To | ||
| 60 | report an overflow, the sender writes the current tail position to | ||
| 61 | a field. The receiver must acknowlege receipt by zeroing the | ||
| 62 | field. The sender will not send more until the field is zeroed. | ||
| 63 | */ | ||
| 64 | PMEXPORT PmQueue *Pm_QueueCreate(long num_msgs, int32_t bytes_per_msg); | ||
| 65 | |||
| 66 | /** destroy a queue and free its storage. | ||
| 67 | |||
| 68 | @param queue a queue created by #Pm_QueueCreate(). | ||
| 69 | |||
| 70 | @return pmNoError or an error code. | ||
| 71 | |||
| 72 | Uses #pm_free(). | ||
| 73 | |||
| 74 | */ | ||
| 75 | PMEXPORT PmError Pm_QueueDestroy(PmQueue *queue); | ||
| 76 | |||
| 77 | /** remove one message from the queue, copying it into \p msg. | ||
| 78 | |||
| 79 | @param queue a queue created by #Pm_QueueCreate(). | ||
| 80 | |||
| 81 | @param msg address to which the message, if any, is copied. | ||
| 82 | |||
| 83 | @return 1 if successful, and 0 if the queue is empty. Returns | ||
| 84 | #pmBufferOverflow if what would have been the next thing in the | ||
| 85 | queue was dropped due to overflow. (So when overflow occurs, the | ||
| 86 | receiver can receive a queue full of messages before getting the | ||
| 87 | overflow report. This protocol ensures that the reader will be | ||
| 88 | notified when data is lost due to overflow. | ||
| 89 | */ | ||
| 90 | PMEXPORT PmError Pm_Dequeue(PmQueue *queue, void *msg); | ||
| 91 | |||
| 92 | /** insert one message into the queue, copying it from \p msg. | ||
| 93 | |||
| 94 | @param queue a queue created by #Pm_QueueCreate(). | ||
| 95 | |||
| 96 | @param msg address of the message to be enqueued. | ||
| 97 | |||
| 98 | @return #pmNoError if successful and #pmBufferOverflow if the | ||
| 99 | queue was already full. If #pmBufferOverflow is returned, the | ||
| 100 | overflow flag is set. | ||
| 101 | */ | ||
| 102 | PMEXPORT PmError Pm_Enqueue(PmQueue *queue, void *msg); | ||
| 103 | |||
| 104 | /** test if the queue is full. | ||
| 105 | |||
| 106 | @param queue a queue created by #Pm_QueueCreate(). | ||
| 107 | |||
| 108 | @return non-zero iff the queue is empty, and @pmBadPtr if \p queue | ||
| 109 | is NULL. | ||
| 110 | |||
| 111 | The full condition may change immediately because a parallel | ||
| 112 | dequeue operation could be in progress. The result is | ||
| 113 | pessimistic: if it returns false (zero) to the single writer, then | ||
| 114 | #Pm_Enqueue() is guaranteed to succeed. | ||
| 115 | */ | ||
| 116 | PMEXPORT int Pm_QueueFull(PmQueue *queue); | ||
| 117 | |||
| 118 | /** test if the queue is empty. | ||
| 119 | |||
| 120 | @param queue a queue created by #Pm_QueueCreate(). | ||
| 121 | |||
| 122 | @return zero iff the queue is either empty or NULL. | ||
| 123 | |||
| 124 | The empty condition may change immediately because a parallel | ||
| 125 | enqueue operation could be in progress. Furthermore, the | ||
| 126 | result is optimistic: it may say false, when due to | ||
| 127 | out-of-order writes, the full message has not arrived. Therefore, | ||
| 128 | #Pm_Dequeue() could still return 0 after #Pm_QueueEmpty() returns | ||
| 129 | false. | ||
| 130 | */ | ||
| 131 | PMEXPORT int Pm_QueueEmpty(PmQueue *queue); | ||
| 132 | |||
| 133 | /** get a pointer to the item at the head of the queue. | ||
| 134 | |||
| 135 | @param queue a queue created by #Pm_QueueCreate(). | ||
| 136 | |||
| 137 | @result a pointer to the head message or NULL if the queue is empty. | ||
| 138 | |||
| 139 | The message is not removed from the queue. #Pm_QueuePeek() will | ||
| 140 | not indicate when an overflow occurs. If you want to get and check | ||
| 141 | #pmBufferOverflow messages, use the return value of | ||
| 142 | #Pm_QueuePeek() *only* as an indication that you should call | ||
| 143 | #Pm_Dequeue(). At the point where a direct call to #Pm_Dequeue() | ||
| 144 | would return #pmBufferOverflow, #Pm_QueuePeek() will return NULL, | ||
| 145 | but internally clear the #pmBufferOverflow flag, enabling | ||
| 146 | #Pm_Enqueue() to resume enqueuing messages. A subsequent call to | ||
| 147 | #Pm_QueuePeek() will return a pointer to the first message *after* | ||
| 148 | the overflow. Using this as an indication to call #Pm_Dequeue(), | ||
| 149 | the first call to #Pm_Dequeue() will return #pmBufferOverflow. The | ||
| 150 | second call will return success, copying the same message pointed | ||
| 151 | to by the previous #Pm_QueuePeek(). | ||
| 152 | |||
| 153 | When to use #Pm_QueuePeek(): (1) when you need to look at the message | ||
| 154 | data to decide who should be called to receive it. (2) when you need | ||
| 155 | to know a message is ready but cannot accept the message. | ||
| 156 | |||
| 157 | Note that #Pm_QueuePeek() is not a fast check, so if possible, you | ||
| 158 | might as well just call #Pm_Dequeue() and accept the data if it is there. | ||
| 159 | */ | ||
| 160 | PMEXPORT void *Pm_QueuePeek(PmQueue *queue); | ||
| 161 | |||
| 162 | /** allows the writer (enqueuer) to signal an overflow | ||
| 163 | condition to the reader (dequeuer). | ||
| 164 | |||
| 165 | @param queue a queue created by #Pm_QueueCreate(). | ||
| 166 | |||
| 167 | @return #pmNoError if overflow is set, or #pmBadPtr if queue is | ||
| 168 | NULL, or #pmBufferOverflow if buffer is already in an overflow | ||
| 169 | state. | ||
| 170 | |||
| 171 | E.g., when transfering data from the OS to an application, if the | ||
| 172 | OS indicates a buffer overrun, #Pm_SetOverflow() can be used to | ||
| 173 | insure that the reader receives a #pmBufferOverflow result from | ||
| 174 | #Pm_Dequeue(). | ||
| 175 | */ | ||
| 176 | PMEXPORT PmError Pm_SetOverflow(PmQueue *queue); | ||
| 177 | |||
| 178 | /** @} */ | ||
| 179 | |||
| 180 | #ifdef __cplusplus | ||
| 181 | } | ||
| 182 | #endif /* __cplusplus */ | ||
| 183 | |||
| 184 | #endif // PORTMIDI_PMUTIL_H | ||
diff --git a/portmidi/pm_common/portmidi.c b/portmidi/pm_common/portmidi.c new file mode 100755 index 0000000..e78ee73 --- /dev/null +++ b/portmidi/pm_common/portmidi.c | |||
| @@ -0,0 +1,1472 @@ | |||
| 1 | /* portmidi.c -- cross-platform MIDI I/O library */ | ||
| 2 | /* see license.txt for license */ | ||
| 3 | |||
| 4 | #include "stdlib.h" | ||
| 5 | #include "string.h" | ||
| 6 | #include "portmidi.h" | ||
| 7 | #include "porttime.h" | ||
| 8 | #include "pmutil.h" | ||
| 9 | #include "pminternal.h" | ||
| 10 | #include <assert.h> | ||
| 11 | |||
| 12 | #define MIDI_CLOCK 0xf8 | ||
| 13 | #define MIDI_ACTIVE 0xfe | ||
| 14 | #define MIDI_STATUS_MASK 0x80 | ||
| 15 | #define MIDI_SYSEX 0xf0 | ||
| 16 | #define MIDI_EOX 0xf7 | ||
| 17 | #define MIDI_START 0xFA | ||
| 18 | #define MIDI_STOP 0xFC | ||
| 19 | #define MIDI_CONTINUE 0xFB | ||
| 20 | #define MIDI_F9 0xF9 | ||
| 21 | #define MIDI_FD 0xFD | ||
| 22 | #define MIDI_RESET 0xFF | ||
| 23 | #define MIDI_NOTE_ON 0x90 | ||
| 24 | #define MIDI_NOTE_OFF 0x80 | ||
| 25 | #define MIDI_CHANNEL_AT 0xD0 | ||
| 26 | #define MIDI_POLY_AT 0xA0 | ||
| 27 | #define MIDI_PROGRAM 0xC0 | ||
| 28 | #define MIDI_CONTROL 0xB0 | ||
| 29 | #define MIDI_PITCHBEND 0xE0 | ||
| 30 | #define MIDI_MTC 0xF1 | ||
| 31 | #define MIDI_SONGPOS 0xF2 | ||
| 32 | #define MIDI_SONGSEL 0xF3 | ||
| 33 | #define MIDI_TUNE 0xF6 | ||
| 34 | |||
| 35 | #define is_empty(midi) ((midi)->tail == (midi)->head) | ||
| 36 | |||
| 37 | /* these are not static so that (possibly) some system-dependent code | ||
| 38 | * could override the portmidi.c default which is to use the first | ||
| 39 | * device added using pm_add_device() | ||
| 40 | */ | ||
| 41 | PmDeviceID pm_default_input_device_id = -1; | ||
| 42 | PmDeviceID pm_default_output_device_id = -1; | ||
| 43 | |||
| 44 | /* this is not static so that pm_init can set it directly | ||
| 45 | * (see pmmac.c:pm_init()) | ||
| 46 | */ | ||
| 47 | int pm_initialized = FALSE; | ||
| 48 | |||
| 49 | int pm_hosterror; /* boolean */ | ||
| 50 | |||
| 51 | /* if PM_CHECK_ERRORS is enabled, but the caller wants to | ||
| 52 | * handle an error condition, declare this as extern and | ||
| 53 | * set to FALSE (this override is provided specifically | ||
| 54 | * for the test program virttest.c, where pmNameConflict | ||
| 55 | * is expected in a call to Pm_CreateVirtualInput()): | ||
| 56 | */ | ||
| 57 | int pm_check_errors = TRUE; | ||
| 58 | |||
| 59 | char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN]; | ||
| 60 | |||
| 61 | #ifdef PM_CHECK_ERRORS | ||
| 62 | |||
| 63 | #include <stdio.h> | ||
| 64 | |||
| 65 | #define STRING_MAX 80 | ||
| 66 | |||
| 67 | static void prompt_and_exit(void) | ||
| 68 | { | ||
| 69 | char line[STRING_MAX]; | ||
| 70 | printf("type ENTER..."); | ||
| 71 | char *rslt = fgets(line, STRING_MAX, stdin); | ||
| 72 | /* this will clean up open ports: */ | ||
| 73 | exit(-1); | ||
| 74 | } | ||
| 75 | |||
| 76 | static PmError pm_errmsg(PmError err) | ||
| 77 | { | ||
| 78 | if (!pm_check_errors) { /* see pm_check_errors declaration above */ | ||
| 79 | ; | ||
| 80 | } else if (err == pmHostError) { | ||
| 81 | /* it seems pointless to allocate memory and copy the string, | ||
| 82 | * so I will do the work of Pm_GetHostErrorText directly | ||
| 83 | */ | ||
| 84 | printf("PortMidi found host error...\n %s\n", pm_hosterror_text); | ||
| 85 | pm_hosterror = FALSE; | ||
| 86 | pm_hosterror_text[0] = 0; /* clear the message */ | ||
| 87 | prompt_and_exit(); | ||
| 88 | } else if (err < 0) { | ||
| 89 | printf("PortMidi call failed...\n %s\n", Pm_GetErrorText(err)); | ||
| 90 | prompt_and_exit(); | ||
| 91 | } | ||
| 92 | return err; | ||
| 93 | } | ||
| 94 | #else | ||
| 95 | #define pm_errmsg(err) err | ||
| 96 | #endif | ||
| 97 | |||
| 98 | |||
| 99 | int pm_midi_length(PmMessage msg) | ||
| 100 | { | ||
| 101 | int status, high, low; | ||
| 102 | static int high_lengths[] = { | ||
| 103 | 1, 1, 1, 1, 1, 1, 1, 1, /* 0x00 through 0x70 */ | ||
| 104 | 3, 3, 3, 3, 2, 2, 3, 1 /* 0x80 through 0xf0 */ | ||
| 105 | }; | ||
| 106 | static int low_lengths[] = { | ||
| 107 | 1, 2, 3, 2, 1, 1, 1, 1, /* 0xf0 through 0xf8 */ | ||
| 108 | 1, 1, 1, 1, 1, 1, 1, 1 /* 0xf9 through 0xff */ | ||
| 109 | }; | ||
| 110 | |||
| 111 | status = msg & 0xFF; | ||
| 112 | high = status >> 4; | ||
| 113 | low = status & 15; | ||
| 114 | |||
| 115 | return (high != 0xF) ? high_lengths[high] : low_lengths[low]; | ||
| 116 | } | ||
| 117 | |||
| 118 | |||
| 119 | /* | ||
| 120 | ==================================================================== | ||
| 121 | system implementation of portmidi interface | ||
| 122 | ==================================================================== | ||
| 123 | */ | ||
| 124 | |||
| 125 | int pm_descriptor_max = 0; | ||
| 126 | int pm_descriptor_len = 0; | ||
| 127 | descriptor_type pm_descriptors = NULL; | ||
| 128 | |||
| 129 | /* interface pm_descriptors are simple: an array of string/fnptr pairs: */ | ||
| 130 | #define MAX_INTERF 4 | ||
| 131 | static struct { | ||
| 132 | const char *interf; | ||
| 133 | pm_create_fn create_fn; | ||
| 134 | pm_delete_fn delete_fn; | ||
| 135 | } pm_interf_list[MAX_INTERF]; | ||
| 136 | |||
| 137 | static int pm_interf_list_len = 0; | ||
| 138 | |||
| 139 | |||
| 140 | /* pm_add_interf -- describe an interface to library | ||
| 141 | * | ||
| 142 | * This is called at initialization time, once for each | ||
| 143 | * supported interface (e.g., CoreMIDI). The strings | ||
| 144 | * are retained but NOT COPIED, so do not destroy them! | ||
| 145 | * | ||
| 146 | * The purpose is to register functions that create/delete | ||
| 147 | * a virtual input or output device. | ||
| 148 | * | ||
| 149 | * returns pmInsufficientMemor if interface memory is | ||
| 150 | * exceeded, otherwise returns pmNoError. | ||
| 151 | */ | ||
| 152 | PmError pm_add_interf(char *interf, pm_create_fn create_fn, | ||
| 153 | pm_delete_fn delete_fn) | ||
| 154 | { | ||
| 155 | if (pm_interf_list_len >= MAX_INTERF) { | ||
| 156 | return pmInsufficientMemory; | ||
| 157 | } | ||
| 158 | pm_interf_list[pm_interf_list_len].interf = interf; | ||
| 159 | pm_interf_list[pm_interf_list_len].create_fn = create_fn; | ||
| 160 | pm_interf_list[pm_interf_list_len].delete_fn = delete_fn; | ||
| 161 | pm_interf_list_len++; | ||
| 162 | return pmNoError; | ||
| 163 | } | ||
| 164 | |||
| 165 | |||
| 166 | PmError pm_create_virtual(PmInternal *midi, int is_input, const char *interf, | ||
| 167 | const char *name, void *device_info) | ||
| 168 | { | ||
| 169 | int i; | ||
| 170 | if (pm_interf_list_len == 0) { | ||
| 171 | return pmNotImplemented; | ||
| 172 | } | ||
| 173 | if (!interf) { | ||
| 174 | /* default interface is the first one */ | ||
| 175 | interf = pm_interf_list[0].interf; | ||
| 176 | } | ||
| 177 | for (i = 0; i < pm_interf_list_len; i++) { | ||
| 178 | if (strcmp(pm_interf_list[i].interf, | ||
| 179 | interf) == 0) { | ||
| 180 | int id = (*pm_interf_list[i].create_fn)(is_input, name, | ||
| 181 | device_info); | ||
| 182 | pm_descriptors[id].pub.is_virtual = TRUE; | ||
| 183 | return id; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | return pmInterfaceNotSupported; | ||
| 187 | } | ||
| 188 | |||
| 189 | |||
| 190 | /* pm_add_device -- describe interface/device pair to library | ||
| 191 | * | ||
| 192 | * This is called at intialization time, once for each | ||
| 193 | * interface (e.g. DirectSound) and device (e.g. SoundBlaster 1). | ||
| 194 | * This is also called when user creates a virtual device. | ||
| 195 | * | ||
| 196 | * Normally, increasing integer indices are returned. If the device | ||
| 197 | * is virtual, a linear search is performed to ensure that the name | ||
| 198 | * is unique. If the name is already taken, the call will fail and | ||
| 199 | * no device is added. | ||
| 200 | * | ||
| 201 | * interf is assumed to be static memory, so it is NOT COPIED and | ||
| 202 | * NOT FREED. | ||
| 203 | * name is owned by caller, COPIED if needed, and FREED by PortMidi. | ||
| 204 | * Caller is resposible for freeing name when pm_add_device returns. | ||
| 205 | * | ||
| 206 | * returns pmInvalidDeviceId if device memory is exceeded or a virtual | ||
| 207 | * device would take the name of an existing device. | ||
| 208 | * otherwise returns index (portmidi device_id) of the added device | ||
| 209 | */ | ||
| 210 | PmError pm_add_device(char *interf, const char *name, int is_input, | ||
| 211 | int is_virtual, void *descriptor, pm_fns_type dictionary) { | ||
| 212 | /* printf("pm_add_device: %s %s %d %p %p\n", | ||
| 213 | interf, name, is_input, descriptor, dictionary); */ | ||
| 214 | int device_id; | ||
| 215 | PmDeviceInfo *d; | ||
| 216 | /* if virtual, search for duplicate name or unused ID; otherwise, | ||
| 217 | * just add a new device at the next integer available: | ||
| 218 | */ | ||
| 219 | for (device_id = (is_virtual ? 0 : pm_descriptor_len); | ||
| 220 | device_id < pm_descriptor_len; device_id++) { | ||
| 221 | d = &pm_descriptors[device_id].pub; | ||
| 222 | d->structVersion = PM_DEVICEINFO_VERS; | ||
| 223 | if (strcmp(d->interf, interf) == 0 && strcmp(d->name, name) == 0) { | ||
| 224 | /* only reuse a name if it is a deleted virtual device with | ||
| 225 | * a matching direction (input or output) */ | ||
| 226 | if (pm_descriptors[device_id].deleted && is_input == d->input) { | ||
| 227 | /* here, we know d->is_virtual because only virtual devices | ||
| 228 | * can be deleted, and we know is_virtual because we are | ||
| 229 | * in this loop. | ||
| 230 | */ | ||
| 231 | pm_free((void *) d->name); /* reuse this device entry */ | ||
| 232 | d->name = NULL; | ||
| 233 | break; | ||
| 234 | /* name conflict exists if the new device appears to others as | ||
| 235 | * the same direction (input or output) as the existing device. | ||
| 236 | * Note that virtual inputs appear to others as outputs and | ||
| 237 | * vice versa. | ||
| 238 | * The direction of the new virtual device to others is "output" | ||
| 239 | * if is_input, i.e., virtual inputs appear to others as outputs. | ||
| 240 | * The existing device appears to others as "output" if | ||
| 241 | * (d->is_virtual == d->input) by the same logic. | ||
| 242 | * The compare will detect if device directions are the same: | ||
| 243 | */ | ||
| 244 | } else if (is_input == (d->is_virtual == d->input)) { | ||
| 245 | return pmNameConflict; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | } | ||
| 249 | if (device_id >= pm_descriptor_max) { | ||
| 250 | // expand pm_descriptors | ||
| 251 | descriptor_type new_descriptors = (descriptor_type) | ||
| 252 | pm_alloc(sizeof(descriptor_node) * (pm_descriptor_max + 32)); | ||
| 253 | if (!new_descriptors) return pmInsufficientMemory; | ||
| 254 | if (pm_descriptors) { | ||
| 255 | memcpy(new_descriptors, pm_descriptors, | ||
| 256 | sizeof(descriptor_node) * pm_descriptor_max); | ||
| 257 | pm_free(pm_descriptors); | ||
| 258 | } | ||
| 259 | pm_descriptor_max += 32; | ||
| 260 | pm_descriptors = new_descriptors; | ||
| 261 | } | ||
| 262 | if (device_id == pm_descriptor_len) { | ||
| 263 | pm_descriptor_len++; /* extending array of pm_descriptors */ | ||
| 264 | } | ||
| 265 | d = &pm_descriptors[device_id].pub; | ||
| 266 | d->interf = interf; | ||
| 267 | d->name = pm_alloc(strlen(name) + 1); | ||
| 268 | if (!d->name) { | ||
| 269 | return pmInsufficientMemory; | ||
| 270 | } | ||
| 271 | #if defined(WIN32) && !defined(_WIN32) | ||
| 272 | #pragma warning(suppress: 4996) // don't use suggested strncpy_s | ||
| 273 | #endif | ||
| 274 | strcpy(d->name, name); | ||
| 275 | d->input = is_input; | ||
| 276 | d->output = !is_input; | ||
| 277 | d->is_virtual = FALSE; /* caller should set to TRUE if this is virtual */ | ||
| 278 | |||
| 279 | /* default state: nothing to close (for automatic device closing) */ | ||
| 280 | d->opened = FALSE; | ||
| 281 | |||
| 282 | pm_descriptors[device_id].deleted = FALSE; | ||
| 283 | |||
| 284 | /* ID number passed to win32 multimedia API open */ | ||
| 285 | pm_descriptors[device_id].descriptor = descriptor; | ||
| 286 | |||
| 287 | /* points to PmInternal, allows automatic device closing */ | ||
| 288 | pm_descriptors[device_id].pm_internal = NULL; | ||
| 289 | |||
| 290 | pm_descriptors[device_id].dictionary = dictionary; | ||
| 291 | |||
| 292 | /* set the defaults to the first input and output we see */ | ||
| 293 | if (is_input && pm_default_input_device_id == -1) { | ||
| 294 | pm_default_input_device_id = device_id; | ||
| 295 | } else if (!is_input && pm_default_output_device_id == -1) { | ||
| 296 | pm_default_output_device_id = device_id; | ||
| 297 | } | ||
| 298 | |||
| 299 | return device_id; | ||
| 300 | } | ||
| 301 | |||
| 302 | |||
| 303 | /* Undo a successful call to pm_add_device(). If a new device was | ||
| 304 | * allocated, it must be the last device in pm_descriptors, so it is | ||
| 305 | * easy to delete by decrementing the length of pm_descriptors, but | ||
| 306 | * first free the name (which was copied to the heap). Otherwise, | ||
| 307 | * the device must be a virtual device that was created previously | ||
| 308 | * and is in the interior of the array of pm_descriptors. Leave it, | ||
| 309 | * but mark it as deleted. | ||
| 310 | */ | ||
| 311 | void pm_undo_add_device(int id) | ||
| 312 | { | ||
| 313 | /* Clear some fields (not all are strictly necessary) */ | ||
| 314 | pm_descriptors[id].deleted = TRUE; | ||
| 315 | pm_descriptors[id].descriptor = NULL; | ||
| 316 | pm_descriptors[id].pm_internal = NULL; | ||
| 317 | |||
| 318 | if (id == pm_descriptor_len - 1) { | ||
| 319 | pm_free(pm_descriptors[id].pub.name); | ||
| 320 | pm_descriptor_len--; | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | |||
| 325 | /* utility to look up device, given a pattern, | ||
| 326 | note: pattern is modified | ||
| 327 | */ | ||
| 328 | int Pm_FindDevice(char *pattern, int is_input) | ||
| 329 | { | ||
| 330 | int id = pmNoDevice; | ||
| 331 | int i; | ||
| 332 | /* first parse pattern into name, interf parts */ | ||
| 333 | char *interf_pref = ""; /* initially assume it is not there */ | ||
| 334 | char *name_pref = strstr(pattern, ", "); | ||
| 335 | |||
| 336 | if (name_pref) { /* found separator, adjust the pointer */ | ||
| 337 | interf_pref = pattern; | ||
| 338 | name_pref[0] = 0; | ||
| 339 | name_pref += 2; | ||
| 340 | } else { | ||
| 341 | name_pref = pattern; /* whole string is the name pattern */ | ||
| 342 | } | ||
| 343 | for (i = 0; i < pm_descriptor_len; i++) { | ||
| 344 | const PmDeviceInfo *info = Pm_GetDeviceInfo(i); | ||
| 345 | if (info->input == is_input && | ||
| 346 | strstr(info->name, name_pref) && | ||
| 347 | strstr(info->interf, interf_pref)) { | ||
| 348 | id = i; | ||
| 349 | break; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | return id; | ||
| 353 | } | ||
| 354 | |||
| 355 | |||
| 356 | /* | ||
| 357 | ==================================================================== | ||
| 358 | portmidi implementation | ||
| 359 | ==================================================================== | ||
| 360 | */ | ||
| 361 | |||
| 362 | PMEXPORT int Pm_CountDevices(void) | ||
| 363 | { | ||
| 364 | Pm_Initialize(); | ||
| 365 | /* no error checking -- Pm_Initialize() does not fail */ | ||
| 366 | return pm_descriptor_len; | ||
| 367 | } | ||
| 368 | |||
| 369 | |||
| 370 | PMEXPORT const PmDeviceInfo* Pm_GetDeviceInfo(PmDeviceID id) | ||
| 371 | { | ||
| 372 | Pm_Initialize(); /* no error check needed */ | ||
| 373 | if (id >= 0 && id < pm_descriptor_len && !pm_descriptors[id].deleted) { | ||
| 374 | return &pm_descriptors[id].pub; | ||
| 375 | } | ||
| 376 | return NULL; | ||
| 377 | } | ||
| 378 | |||
| 379 | /* pm_success_fn -- "noop" function pointer */ | ||
| 380 | PmError pm_success_fn(PmInternal *midi) | ||
| 381 | { | ||
| 382 | return pmNoError; | ||
| 383 | } | ||
| 384 | |||
| 385 | /* none_write -- returns an error if called */ | ||
| 386 | PmError none_write_short(PmInternal *midi, PmEvent *buffer) | ||
| 387 | { | ||
| 388 | return pmBadPtr; | ||
| 389 | } | ||
| 390 | |||
| 391 | /* pm_fail_timestamp_fn -- placeholder for begin_sysex and flush */ | ||
| 392 | PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp) | ||
| 393 | { | ||
| 394 | return pmBadPtr; | ||
| 395 | } | ||
| 396 | |||
| 397 | PmError none_write_byte(PmInternal *midi, unsigned char byte, | ||
| 398 | PmTimestamp timestamp) | ||
| 399 | { | ||
| 400 | return pmBadPtr; | ||
| 401 | } | ||
| 402 | |||
| 403 | /* pm_fail_fn -- generic function, returns error if called */ | ||
| 404 | PmError pm_fail_fn(PmInternal *midi) | ||
| 405 | { | ||
| 406 | return pmBadPtr; | ||
| 407 | } | ||
| 408 | |||
| 409 | static PmError none_open(PmInternal *midi, void *driverInfo) | ||
| 410 | { | ||
| 411 | return pmBadPtr; | ||
| 412 | } | ||
| 413 | |||
| 414 | static unsigned int none_check_host_error(PmInternal * midi) | ||
| 415 | { | ||
| 416 | return FALSE; | ||
| 417 | } | ||
| 418 | |||
| 419 | PmTimestamp none_synchronize(PmInternal *midi) | ||
| 420 | { | ||
| 421 | return 0; | ||
| 422 | } | ||
| 423 | |||
| 424 | #define none_abort pm_fail_fn | ||
| 425 | #define none_close pm_fail_fn | ||
| 426 | |||
| 427 | pm_fns_node pm_none_dictionary = { | ||
| 428 | none_write_short, | ||
| 429 | none_sysex, | ||
| 430 | none_sysex, | ||
| 431 | none_write_byte, | ||
| 432 | none_write_short, | ||
| 433 | none_write_flush, | ||
| 434 | none_synchronize, | ||
| 435 | none_open, | ||
| 436 | none_abort, | ||
| 437 | none_close, | ||
| 438 | none_poll, | ||
| 439 | none_check_host_error, | ||
| 440 | }; | ||
| 441 | |||
| 442 | |||
| 443 | PMEXPORT const char *Pm_GetErrorText(PmError errnum) | ||
| 444 | { | ||
| 445 | const char *msg; | ||
| 446 | |||
| 447 | switch(errnum) | ||
| 448 | { | ||
| 449 | case pmNoError: | ||
| 450 | msg = ""; | ||
| 451 | break; | ||
| 452 | case pmHostError: | ||
| 453 | msg = "PortMidi: Host error"; | ||
| 454 | break; | ||
| 455 | case pmInvalidDeviceId: | ||
| 456 | msg = "PortMidi: Invalid device ID"; | ||
| 457 | break; | ||
| 458 | case pmInsufficientMemory: | ||
| 459 | msg = "PortMidi: Insufficient memory"; | ||
| 460 | break; | ||
| 461 | case pmBufferTooSmall: | ||
| 462 | msg = "PortMidi: Buffer too small"; | ||
| 463 | break; | ||
| 464 | case pmBadPtr: | ||
| 465 | msg = "PortMidi: Bad pointer"; | ||
| 466 | break; | ||
| 467 | case pmInternalError: | ||
| 468 | msg = "PortMidi: Internal PortMidi Error"; | ||
| 469 | break; | ||
| 470 | case pmBufferOverflow: | ||
| 471 | msg = "PortMidi: Buffer overflow"; | ||
| 472 | break; | ||
| 473 | case pmBadData: | ||
| 474 | msg = "PortMidi: Invalid MIDI message Data"; | ||
| 475 | break; | ||
| 476 | case pmBufferMaxSize: | ||
| 477 | msg = "PortMidi: Buffer cannot be made larger"; | ||
| 478 | break; | ||
| 479 | case pmNotImplemented: | ||
| 480 | msg = "PortMidi: Function is not implemented"; | ||
| 481 | break; | ||
| 482 | case pmInterfaceNotSupported: | ||
| 483 | msg = "PortMidi: Interface not supported"; | ||
| 484 | break; | ||
| 485 | case pmNameConflict: | ||
| 486 | msg = "PortMidi: Cannot create virtual device: name is taken"; | ||
| 487 | break; | ||
| 488 | case pmDeviceRemoved: | ||
| 489 | msg = "PortMidi: Output attempted after (USB) device removed"; | ||
| 490 | break; | ||
| 491 | default: | ||
| 492 | msg = "PortMidi: Illegal error number"; | ||
| 493 | break; | ||
| 494 | } | ||
| 495 | return msg; | ||
| 496 | } | ||
| 497 | |||
| 498 | |||
| 499 | /* This can be called whenever you get a pmHostError return value | ||
| 500 | * or TRUE from Pm_HasHostError(). | ||
| 501 | * The error will always be in the global pm_hosterror_text. | ||
| 502 | */ | ||
| 503 | PMEXPORT void Pm_GetHostErrorText(char * msg, unsigned int len) | ||
| 504 | { | ||
| 505 | assert(msg); | ||
| 506 | assert(len > 0); | ||
| 507 | if (pm_hosterror) { | ||
| 508 | #if defined(WIN32) && !defined(_WIN32) | ||
| 509 | #pragma warning(suppress: 4996) // don't use suggested strncpy_s | ||
| 510 | #endif | ||
| 511 | strncpy(msg, (char *) pm_hosterror_text, len); | ||
| 512 | pm_hosterror = FALSE; | ||
| 513 | pm_hosterror_text[0] = 0; /* clear the message; not necessary, but it | ||
| 514 | might help with debugging */ | ||
| 515 | msg[len - 1] = 0; /* make sure string is terminated */ | ||
| 516 | } else { | ||
| 517 | msg[0] = 0; /* no string to return */ | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | |||
| 522 | PMEXPORT int Pm_HasHostError(PortMidiStream * stream) | ||
| 523 | { | ||
| 524 | if (pm_hosterror) return TRUE; | ||
| 525 | if (stream) { | ||
| 526 | PmInternal * midi = (PmInternal *) stream; | ||
| 527 | return (*midi->dictionary->check_host_error)(midi); | ||
| 528 | } | ||
| 529 | return FALSE; | ||
| 530 | } | ||
| 531 | |||
| 532 | |||
| 533 | PMEXPORT PmError Pm_Initialize(void) | ||
| 534 | { | ||
| 535 | if (!pm_initialized) { | ||
| 536 | pm_descriptor_len = 0; | ||
| 537 | pm_interf_list_len = 0; | ||
| 538 | pm_hosterror = FALSE; | ||
| 539 | pm_hosterror_text[0] = 0; /* the null string */ | ||
| 540 | pm_init(); | ||
| 541 | pm_initialized = TRUE; | ||
| 542 | } | ||
| 543 | return pmNoError; | ||
| 544 | } | ||
| 545 | |||
| 546 | |||
| 547 | PMEXPORT PmError Pm_Terminate(void) | ||
| 548 | { | ||
| 549 | if (pm_initialized) { | ||
| 550 | pm_term(); | ||
| 551 | /* if there are no devices, pm_descriptors might still be NULL */ | ||
| 552 | if (pm_descriptors != NULL) { | ||
| 553 | int i; /* free names copied into pm_descriptors */ | ||
| 554 | for (i = 0; i < pm_descriptor_len; i++) { | ||
| 555 | if (pm_descriptors[i].pub.name) { | ||
| 556 | pm_free(pm_descriptors[i].pub.name); | ||
| 557 | } | ||
| 558 | } | ||
| 559 | pm_free(pm_descriptors); | ||
| 560 | pm_descriptors = NULL; | ||
| 561 | } | ||
| 562 | pm_descriptor_len = 0; | ||
| 563 | pm_descriptor_max = 0; | ||
| 564 | pm_interf_list_len = 0; | ||
| 565 | pm_initialized = FALSE; | ||
| 566 | } | ||
| 567 | return pmNoError; | ||
| 568 | } | ||
| 569 | |||
| 570 | |||
| 571 | /* Pm_Read -- read up to length messages from source into buffer */ | ||
| 572 | /* | ||
| 573 | * returns number of messages actually read, or error code | ||
| 574 | */ | ||
| 575 | PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length) | ||
| 576 | { | ||
| 577 | PmInternal *midi = (PmInternal *) stream; | ||
| 578 | int n = 0; | ||
| 579 | PmError err = pmNoError; | ||
| 580 | pm_hosterror = FALSE; | ||
| 581 | /* arg checking */ | ||
| 582 | if(midi == NULL) | ||
| 583 | err = pmBadPtr; | ||
| 584 | else if(!pm_descriptors[midi->device_id].pub.opened) | ||
| 585 | err = pmBadPtr; | ||
| 586 | else if(!pm_descriptors[midi->device_id].pub.input) | ||
| 587 | err = pmBadPtr; | ||
| 588 | /* First poll for data in the buffer... | ||
| 589 | * This either simply checks for data, or attempts first to fill the buffer | ||
| 590 | * with data from the MIDI hardware; this depends on the implementation. | ||
| 591 | * We could call Pm_Poll here, but that would redo a lot of redundant | ||
| 592 | * parameter checking, so I copied some code from Pm_Poll to here: */ | ||
| 593 | else err = (*(midi->dictionary->poll))(midi); | ||
| 594 | |||
| 595 | if (err != pmNoError) { | ||
| 596 | if (err == pmHostError) { | ||
| 597 | midi->dictionary->check_host_error(midi); | ||
| 598 | } | ||
| 599 | return pm_errmsg(err); | ||
| 600 | } | ||
| 601 | |||
| 602 | while (n < length) { | ||
| 603 | err = Pm_Dequeue(midi->queue, buffer++); | ||
| 604 | if (err == pmBufferOverflow) { | ||
| 605 | /* ignore the data we have retreived so far */ | ||
| 606 | return pm_errmsg(pmBufferOverflow); | ||
| 607 | } else if (err == 0) { /* empty queue */ | ||
| 608 | break; | ||
| 609 | } | ||
| 610 | n++; | ||
| 611 | } | ||
| 612 | return n; | ||
| 613 | } | ||
| 614 | |||
| 615 | PMEXPORT PmError Pm_Poll(PortMidiStream *stream) | ||
| 616 | { | ||
| 617 | PmInternal *midi = (PmInternal *) stream; | ||
| 618 | PmError err; | ||
| 619 | |||
| 620 | pm_hosterror = FALSE; | ||
| 621 | /* arg checking */ | ||
| 622 | if(midi == NULL) | ||
| 623 | err = pmBadPtr; | ||
| 624 | else if (!pm_descriptors[midi->device_id].pub.opened) | ||
| 625 | err = pmBadPtr; | ||
| 626 | else if (!pm_descriptors[midi->device_id].pub.input) | ||
| 627 | err = pmBadPtr; | ||
| 628 | else | ||
| 629 | err = (*(midi->dictionary->poll))(midi); | ||
| 630 | |||
| 631 | if (err != pmNoError) { | ||
| 632 | return pm_errmsg(err); | ||
| 633 | } | ||
| 634 | |||
| 635 | return (PmError) !Pm_QueueEmpty(midi->queue); | ||
| 636 | } | ||
| 637 | |||
| 638 | |||
| 639 | /* this is called from Pm_Write and Pm_WriteSysEx to issue a | ||
| 640 | * call to the system-dependent end_sysex function and handle | ||
| 641 | * the error return | ||
| 642 | */ | ||
| 643 | static PmError pm_end_sysex(PmInternal *midi) | ||
| 644 | { | ||
| 645 | PmError err = (*midi->dictionary->end_sysex)(midi, 0); | ||
| 646 | midi->sysex_in_progress = FALSE; | ||
| 647 | return err; | ||
| 648 | } | ||
| 649 | |||
| 650 | |||
| 651 | /* to facilitate correct error-handling, Pm_Write, Pm_WriteShort, and | ||
| 652 | Pm_WriteSysEx all operate a state machine that "outputs" calls to | ||
| 653 | write_short, begin_sysex, write_byte, end_sysex, and write_realtime */ | ||
| 654 | |||
| 655 | PMEXPORT PmError Pm_Write(PortMidiStream *stream, PmEvent *buffer, | ||
| 656 | int32_t length) | ||
| 657 | { | ||
| 658 | PmInternal *midi = (PmInternal *) stream; | ||
| 659 | PmError err = pmNoError; | ||
| 660 | int i; | ||
| 661 | int bits; | ||
| 662 | |||
| 663 | pm_hosterror = FALSE; | ||
| 664 | /* arg checking */ | ||
| 665 | if (midi == NULL) { | ||
| 666 | err = pmBadPtr; | ||
| 667 | } else { | ||
| 668 | descriptor_type desc = &pm_descriptors[midi->device_id]; | ||
| 669 | if (!desc || !desc->pub.opened || | ||
| 670 | !desc->pub.output || !desc->pm_internal) { | ||
| 671 | err = pmBadPtr; | ||
| 672 | } else if (desc->pm_internal->is_removed) { | ||
| 673 | err = pmDeviceRemoved; | ||
| 674 | } | ||
| 675 | } | ||
| 676 | if (err != pmNoError) goto pm_write_error; | ||
| 677 | |||
| 678 | if (midi->latency == 0) { | ||
| 679 | midi->now = 0; | ||
| 680 | } else { | ||
| 681 | midi->now = (*(midi->time_proc))(midi->time_info); | ||
| 682 | if (midi->first_message || midi->sync_time + 100 /*ms*/ < midi->now) { | ||
| 683 | /* time to resync */ | ||
| 684 | midi->now = (*midi->dictionary->synchronize)(midi); | ||
| 685 | midi->first_message = FALSE; | ||
| 686 | } | ||
| 687 | } | ||
| 688 | /* error recovery: when a sysex is detected, we call | ||
| 689 | * dictionary->begin_sysex() followed by calls to | ||
| 690 | * dictionary->write_byte() and dictionary->write_realtime() | ||
| 691 | * until an end-of-sysex is detected, when we call | ||
| 692 | * dictionary->end_sysex(). After an error occurs, | ||
| 693 | * Pm_Write() continues to call functions. For example, | ||
| 694 | * it will continue to call write_byte() even after | ||
| 695 | * an error sending a sysex message, and end_sysex() will be | ||
| 696 | * called when an EOX or non-real-time status is found. | ||
| 697 | * When errors are detected, Pm_Write() returns immediately, | ||
| 698 | * so it is possible that this will drop data and leave | ||
| 699 | * sysex messages in a partially transmitted state. | ||
| 700 | */ | ||
| 701 | for (i = 0; i < length; i++) { | ||
| 702 | uint32_t msg = buffer[i].message; | ||
| 703 | bits = 0; | ||
| 704 | /* is this a sysex message? */ | ||
| 705 | if (Pm_MessageStatus(msg) == MIDI_SYSEX) { | ||
| 706 | if (midi->sysex_in_progress) { | ||
| 707 | /* error: previous sysex was not terminated by EOX */ | ||
| 708 | midi->sysex_in_progress = FALSE; | ||
| 709 | err = pmBadData; | ||
| 710 | goto pm_write_error; | ||
| 711 | } | ||
| 712 | midi->sysex_in_progress = TRUE; | ||
| 713 | if ((err = (*midi->dictionary->begin_sysex)(midi, | ||
| 714 | buffer[i].timestamp)) != pmNoError) | ||
| 715 | goto pm_write_error; | ||
| 716 | if ((err = (*midi->dictionary->write_byte)(midi, MIDI_SYSEX, | ||
| 717 | buffer[i].timestamp)) != pmNoError) | ||
| 718 | goto pm_write_error; | ||
| 719 | bits = 8; | ||
| 720 | /* fall through to continue sysex processing */ | ||
| 721 | } else if ((msg & MIDI_STATUS_MASK) && | ||
| 722 | (Pm_MessageStatus(msg) != MIDI_EOX)) { | ||
| 723 | /* a non-sysex message */ | ||
| 724 | if (midi->sysex_in_progress) { | ||
| 725 | /* this should be a realtime message */ | ||
| 726 | if (is_real_time(msg)) { | ||
| 727 | if ((err = (*midi->dictionary->write_realtime)(midi, | ||
| 728 | &(buffer[i]))) != pmNoError) | ||
| 729 | goto pm_write_error; | ||
| 730 | } else { | ||
| 731 | midi->sysex_in_progress = FALSE; | ||
| 732 | err = pmBadData; | ||
| 733 | /* ignore any error from this, because we already have one */ | ||
| 734 | /* pass 0 as timestamp -- it's ignored */ | ||
| 735 | (*midi->dictionary->end_sysex)(midi, 0); | ||
| 736 | goto pm_write_error; | ||
| 737 | } | ||
| 738 | } else { /* regular short midi message */ | ||
| 739 | if ((err = (*midi->dictionary->write_short)(midi, | ||
| 740 | &(buffer[i]))) != pmNoError) | ||
| 741 | goto pm_write_error; | ||
| 742 | continue; | ||
| 743 | } | ||
| 744 | } | ||
| 745 | if (midi->sysex_in_progress) { /* send sysex bytes until EOX */ | ||
| 746 | /* see if we can accelerate data transfer */ | ||
| 747 | if (bits == 0 && midi->fill_base && /* 4 bytes to copy */ | ||
| 748 | (*midi->fill_offset_ptr) + 4 <= midi->fill_length && | ||
| 749 | (msg & 0x80808080) == 0) { /* all data */ | ||
| 750 | /* copy 4 bytes from msg to fill_base + fill_offset */ | ||
| 751 | unsigned char *ptr = midi->fill_base + | ||
| 752 | *(midi->fill_offset_ptr); | ||
| 753 | ptr[0] = msg; ptr[1] = msg >> 8; | ||
| 754 | ptr[2] = msg >> 16; ptr[3] = msg >> 24; | ||
| 755 | (*midi->fill_offset_ptr) += 4; | ||
| 756 | continue; | ||
| 757 | } | ||
| 758 | /* no acceleration, so do byte-by-byte copying */ | ||
| 759 | while (bits < 32) { | ||
| 760 | unsigned char midi_byte = (unsigned char) (msg >> bits); | ||
| 761 | if ((err = (*midi->dictionary->write_byte)(midi, midi_byte, | ||
| 762 | buffer[i].timestamp)) != pmNoError) | ||
| 763 | goto pm_write_error; | ||
| 764 | if (midi_byte == MIDI_EOX) { | ||
| 765 | err = pm_end_sysex(midi); | ||
| 766 | if (err != pmNoError) goto error_exit; | ||
| 767 | break; /* from while loop */ | ||
| 768 | } | ||
| 769 | bits += 8; | ||
| 770 | } | ||
| 771 | } else { | ||
| 772 | /* not in sysex mode, but message did not start with status */ | ||
| 773 | err = pmBadData; | ||
| 774 | goto pm_write_error; | ||
| 775 | } | ||
| 776 | } | ||
| 777 | /* after all messages are processed, send the data */ | ||
| 778 | if (!midi->sysex_in_progress) | ||
| 779 | err = (*midi->dictionary->write_flush)(midi, 0); | ||
| 780 | pm_write_error: | ||
| 781 | if (err == pmHostError) { | ||
| 782 | midi->dictionary->check_host_error(midi); | ||
| 783 | } | ||
| 784 | error_exit: | ||
| 785 | return pm_errmsg(err); | ||
| 786 | } | ||
| 787 | |||
| 788 | |||
| 789 | PMEXPORT PmError Pm_WriteShort(PortMidiStream *stream, PmTimestamp when, | ||
| 790 | PmMessage msg) | ||
| 791 | { | ||
| 792 | PmEvent event; | ||
| 793 | |||
| 794 | event.timestamp = when; | ||
| 795 | event.message = msg; | ||
| 796 | return Pm_Write(stream, &event, 1); | ||
| 797 | } | ||
| 798 | |||
| 799 | |||
| 800 | PMEXPORT PmError Pm_WriteSysEx(PortMidiStream *stream, PmTimestamp when, | ||
| 801 | unsigned char *msg) | ||
| 802 | { | ||
| 803 | /* allocate buffer space for PM_DEFAULT_SYSEX_BUFFER_SIZE bytes */ | ||
| 804 | /* each PmEvent holds sizeof(PmMessage) bytes of sysex data */ | ||
| 805 | #define BUFLEN ((int) (PM_DEFAULT_SYSEX_BUFFER_SIZE / sizeof(PmMessage))) | ||
| 806 | PmEvent buffer[BUFLEN]; | ||
| 807 | int buffer_size = 1; /* first time, send 1. After that, it's BUFLEN */ | ||
| 808 | PmInternal *midi = (PmInternal *) stream; | ||
| 809 | PmError err = pmNoError; | ||
| 810 | /* the next byte in the buffer is represented by an index, bufx, and | ||
| 811 | a shift in bits */ | ||
| 812 | int shift = 0; | ||
| 813 | int bufx = 0; | ||
| 814 | buffer[0].message = 0; | ||
| 815 | buffer[0].timestamp = when; | ||
| 816 | |||
| 817 | while (1) { | ||
| 818 | /* insert next byte into buffer */ | ||
| 819 | buffer[bufx].message |= ((*msg) << shift); | ||
| 820 | shift += 8; | ||
| 821 | if (*msg++ == MIDI_EOX) break; | ||
| 822 | if (shift == 32) { | ||
| 823 | shift = 0; | ||
| 824 | bufx++; | ||
| 825 | if (bufx == buffer_size) { | ||
| 826 | err = Pm_Write(stream, buffer, buffer_size); | ||
| 827 | /* note: Pm_Write has already called errmsg() */ | ||
| 828 | if (err) return err; | ||
| 829 | /* prepare to fill another buffer */ | ||
| 830 | bufx = 0; | ||
| 831 | buffer_size = BUFLEN; | ||
| 832 | /* optimization: maybe we can just copy bytes */ | ||
| 833 | if (midi->fill_base) { | ||
| 834 | while (*(midi->fill_offset_ptr) < midi->fill_length) { | ||
| 835 | midi->fill_base[(*midi->fill_offset_ptr)++] = *msg; | ||
| 836 | if (*msg++ == MIDI_EOX) { | ||
| 837 | err = pm_end_sysex(midi); | ||
| 838 | if (err != pmNoError) return pm_errmsg(err); | ||
| 839 | goto end_of_sysex; | ||
| 840 | } | ||
| 841 | } | ||
| 842 | /* I thought that I could do a pm_Write here and | ||
| 843 | * change this if to a loop, avoiding calls in Pm_Write | ||
| 844 | * to the slower write_byte, but since | ||
| 845 | * sysex_in_progress is true, this will not flush | ||
| 846 | * the buffer, and we'll infinite loop: */ | ||
| 847 | /* err = Pm_Write(stream, buffer, 0); | ||
| 848 | if (err) return err; */ | ||
| 849 | /* instead, the way this works is that Pm_Write calls | ||
| 850 | * write_byte on 4 bytes. The first, since the buffer | ||
| 851 | * is full, will flush the buffer and allocate a new | ||
| 852 | * one. This primes the buffer so | ||
| 853 | * that we can return to the loop above and fill it | ||
| 854 | * efficiently without a lot of function calls. | ||
| 855 | */ | ||
| 856 | buffer_size = 1; /* get another message started */ | ||
| 857 | } | ||
| 858 | } | ||
| 859 | buffer[bufx].message = 0; | ||
| 860 | buffer[bufx].timestamp = when; | ||
| 861 | } | ||
| 862 | /* keep inserting bytes until you find MIDI_EOX */ | ||
| 863 | } | ||
| 864 | end_of_sysex: | ||
| 865 | /* we're finished sending full buffers, but there may | ||
| 866 | * be a partial one left. | ||
| 867 | */ | ||
| 868 | if (shift != 0) bufx++; /* add partial message to buffer len */ | ||
| 869 | if (bufx) { /* bufx is number of PmEvents to send from buffer */ | ||
| 870 | err = Pm_Write(stream, buffer, bufx); | ||
| 871 | if (err) return err; | ||
| 872 | } | ||
| 873 | return pmNoError; | ||
| 874 | } | ||
| 875 | |||
| 876 | |||
| 877 | |||
| 878 | PmError pm_create_internal(PmInternal **stream, PmDeviceID device_id, | ||
| 879 | int is_input, int latency, PmTimeProcPtr time_proc, | ||
| 880 | void *time_info, int buffer_size) | ||
| 881 | { | ||
| 882 | PmInternal *midi; | ||
| 883 | if (device_id < 0 || device_id >= pm_descriptor_len) { | ||
| 884 | return pmInvalidDeviceId; | ||
| 885 | } | ||
| 886 | if (latency < 0) { /* force a legal value */ | ||
| 887 | latency = 0; | ||
| 888 | } | ||
| 889 | /* create portMidi internal data */ | ||
| 890 | midi = (PmInternal *) pm_alloc(sizeof(PmInternal)); | ||
| 891 | *stream = midi; | ||
| 892 | if (!midi) { | ||
| 893 | return pmInsufficientMemory; | ||
| 894 | } | ||
| 895 | midi->device_id = device_id; | ||
| 896 | midi->is_input = is_input; | ||
| 897 | midi->is_removed = FALSE; | ||
| 898 | midi->time_proc = time_proc; | ||
| 899 | /* if latency != 0, we need a time reference for output. | ||
| 900 | we always need a time reference for input. | ||
| 901 | If none is provided, use PortTime library */ | ||
| 902 | if (time_proc == NULL && (latency != 0 || is_input)) { | ||
| 903 | if (!Pt_Started()) | ||
| 904 | Pt_Start(1, 0, 0); | ||
| 905 | /* time_get does not take a parameter, so coerce */ | ||
| 906 | midi->time_proc = (PmTimeProcPtr) Pt_Time; | ||
| 907 | } | ||
| 908 | midi->time_info = time_info; | ||
| 909 | if (is_input) { | ||
| 910 | midi->latency = 0; /* unused by input */ | ||
| 911 | if (buffer_size <= 0) buffer_size = 256; /* default buffer size */ | ||
| 912 | midi->queue = Pm_QueueCreate(buffer_size, (int32_t) sizeof(PmEvent)); | ||
| 913 | if (!midi->queue) { | ||
| 914 | /* free portMidi data */ | ||
| 915 | *stream = NULL; | ||
| 916 | pm_free(midi); | ||
| 917 | return pmInsufficientMemory; | ||
| 918 | } | ||
| 919 | } else { | ||
| 920 | /* if latency zero, output immediate (timestamps ignored) */ | ||
| 921 | /* if latency < 0, use 0 but don't return an error */ | ||
| 922 | if (latency < 0) latency = 0; | ||
| 923 | midi->latency = latency; | ||
| 924 | midi->queue = NULL; /* unused by output; input needs to allocate: */ | ||
| 925 | } | ||
| 926 | midi->buffer_len = buffer_size; /* portMidi input storage */ | ||
| 927 | midi->sysex_in_progress = FALSE; | ||
| 928 | midi->message = 0; | ||
| 929 | midi->message_count = 0; | ||
| 930 | midi->filters = (is_input ? PM_FILT_ACTIVE : 0); | ||
| 931 | midi->channel_mask = 0xFFFF; | ||
| 932 | midi->sync_time = 0; | ||
| 933 | midi->first_message = TRUE; | ||
| 934 | midi->api_info = NULL; | ||
| 935 | midi->fill_base = NULL; | ||
| 936 | midi->fill_offset_ptr = NULL; | ||
| 937 | midi->fill_length = 0; | ||
| 938 | midi->dictionary = pm_descriptors[device_id].dictionary; | ||
| 939 | pm_descriptors[device_id].pm_internal = midi; | ||
| 940 | return pmNoError; | ||
| 941 | } | ||
| 942 | |||
| 943 | |||
| 944 | PMEXPORT PmError Pm_OpenInput(PortMidiStream** stream, | ||
| 945 | PmDeviceID inputDevice, | ||
| 946 | void *inputDriverInfo, | ||
| 947 | int32_t bufferSize, | ||
| 948 | PmTimeProcPtr time_proc, | ||
| 949 | void *time_info) | ||
| 950 | { | ||
| 951 | PmInternal *midi; | ||
| 952 | PmError err = pmNoError; | ||
| 953 | pm_hosterror = FALSE; | ||
| 954 | *stream = NULL; /* invariant: *stream == midi */ | ||
| 955 | |||
| 956 | /* arg checking */ | ||
| 957 | if (!pm_descriptors[inputDevice].pub.input) | ||
| 958 | err = pmInvalidDeviceId; | ||
| 959 | else if (pm_descriptors[inputDevice].pub.opened) | ||
| 960 | err = pmInvalidDeviceId; | ||
| 961 | if (err != pmNoError) | ||
| 962 | goto error_return; | ||
| 963 | |||
| 964 | /* common initialization of PmInternal structure (midi): */ | ||
| 965 | err = pm_create_internal(&midi, inputDevice, TRUE, 0, time_proc, | ||
| 966 | time_info, bufferSize); | ||
| 967 | *stream = midi; | ||
| 968 | if (err) { | ||
| 969 | goto error_return; | ||
| 970 | } | ||
| 971 | |||
| 972 | /* open system dependent input device */ | ||
| 973 | err = (*midi->dictionary->open)(midi, inputDriverInfo); | ||
| 974 | if (err) { | ||
| 975 | *stream = NULL; | ||
| 976 | pm_descriptors[inputDevice].pm_internal = NULL; | ||
| 977 | /* free portMidi data */ | ||
| 978 | Pm_QueueDestroy(midi->queue); | ||
| 979 | pm_free(midi); | ||
| 980 | } else { | ||
| 981 | /* portMidi input open successful */ | ||
| 982 | pm_descriptors[inputDevice].pub.opened = TRUE; | ||
| 983 | } | ||
| 984 | error_return: | ||
| 985 | /* note: if there is a pmHostError, it is the responsibility | ||
| 986 | * of the system-dependent code (*midi->dictionary->open)() | ||
| 987 | * to set pm_hosterror and pm_hosterror_text | ||
| 988 | */ | ||
| 989 | return pm_errmsg(err); | ||
| 990 | } | ||
| 991 | |||
| 992 | |||
| 993 | PMEXPORT PmError Pm_OpenOutput(PortMidiStream** stream, | ||
| 994 | PmDeviceID outputDevice, | ||
| 995 | void *outputDriverInfo, | ||
| 996 | int32_t bufferSize, | ||
| 997 | PmTimeProcPtr time_proc, | ||
| 998 | void *time_info, | ||
| 999 | int32_t latency) | ||
| 1000 | { | ||
| 1001 | PmInternal *midi; | ||
| 1002 | PmError err = pmNoError; | ||
| 1003 | pm_hosterror = FALSE; | ||
| 1004 | *stream = NULL; | ||
| 1005 | |||
| 1006 | /* arg checking */ | ||
| 1007 | if (outputDevice < 0 || outputDevice >= pm_descriptor_len) | ||
| 1008 | err = pmInvalidDeviceId; | ||
| 1009 | else if (!pm_descriptors[outputDevice].pub.output) | ||
| 1010 | err = pmInvalidDeviceId; | ||
| 1011 | else if (pm_descriptors[outputDevice].pub.opened) | ||
| 1012 | err = pmInvalidDeviceId; | ||
| 1013 | if (err != pmNoError) | ||
| 1014 | goto error_return; | ||
| 1015 | |||
| 1016 | /* common initialization of PmInternal structure (midi): */ | ||
| 1017 | err = pm_create_internal(&midi, outputDevice, FALSE, latency, time_proc, | ||
| 1018 | time_info, bufferSize); | ||
| 1019 | *stream = midi; | ||
| 1020 | if (err) { | ||
| 1021 | goto error_return; | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | /* open system dependent output device */ | ||
| 1025 | err = (*midi->dictionary->open)(midi, outputDriverInfo); | ||
| 1026 | if (err) { | ||
| 1027 | *stream = NULL; | ||
| 1028 | pm_descriptors[outputDevice].pm_internal = NULL; | ||
| 1029 | /* free portMidi data */ | ||
| 1030 | pm_free(midi); | ||
| 1031 | } else { | ||
| 1032 | /* portMidi input open successful */ | ||
| 1033 | pm_descriptors[outputDevice].pub.opened = TRUE; | ||
| 1034 | } | ||
| 1035 | error_return: | ||
| 1036 | /* note: system-dependent code must set pm_hosterror and | ||
| 1037 | * pm_hosterror_text if a pmHostError occurs | ||
| 1038 | */ | ||
| 1039 | return pm_errmsg(err); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | |||
| 1043 | static PmError create_virtual_device(const char *name, const char *interf, | ||
| 1044 | void *device_info, int is_input) | ||
| 1045 | { | ||
| 1046 | PmError err = pmNoError; | ||
| 1047 | int i; | ||
| 1048 | pm_hosterror = FALSE; | ||
| 1049 | |||
| 1050 | /* arg checking */ | ||
| 1051 | if (!name) { | ||
| 1052 | err = pmInvalidDeviceId; | ||
| 1053 | goto error_return; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | Pm_Initialize(); /* just in case */ | ||
| 1057 | |||
| 1058 | /* create the virtual device */ | ||
| 1059 | if (pm_interf_list_len == 0) { | ||
| 1060 | return pmNotImplemented; | ||
| 1061 | } | ||
| 1062 | if (!interf) { | ||
| 1063 | /* default interface is the first one */ | ||
| 1064 | interf = pm_interf_list[0].interf; | ||
| 1065 | } | ||
| 1066 | /* look up and call the create_fn for interf(ace), e.g. "CoreMIDI" */ | ||
| 1067 | for (i = 0; i < pm_interf_list_len; i++) { | ||
| 1068 | if (strcmp(pm_interf_list[i].interf, interf) == 0) { | ||
| 1069 | int id = (*pm_interf_list[i].create_fn)(is_input, | ||
| 1070 | name, device_info); | ||
| 1071 | /* id could be pmNameConflict or an actual descriptor index */ | ||
| 1072 | if (id >= 0) { | ||
| 1073 | pm_descriptors[id].pub.is_virtual = TRUE; | ||
| 1074 | } | ||
| 1075 | err = id; | ||
| 1076 | goto error_return; | ||
| 1077 | } | ||
| 1078 | } | ||
| 1079 | err = pmInterfaceNotSupported; | ||
| 1080 | |||
| 1081 | error_return: | ||
| 1082 | /* note: if there is a pmHostError, it is the responsibility | ||
| 1083 | * of the system-dependent code (*midi->dictionary->open)() | ||
| 1084 | * to set pm_hosterror and pm_hosterror_text | ||
| 1085 | */ | ||
| 1086 | return pm_errmsg(err); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | |||
| 1090 | PMEXPORT PmError Pm_CreateVirtualInput(const char *name, | ||
| 1091 | const char *interf, | ||
| 1092 | void *deviceInfo) | ||
| 1093 | { | ||
| 1094 | return create_virtual_device(name, interf, deviceInfo, TRUE); | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | PMEXPORT PmError Pm_CreateVirtualOutput(const char *name, const char *interf, | ||
| 1098 | void *deviceInfo) | ||
| 1099 | { | ||
| 1100 | return create_virtual_device(name, interf, deviceInfo, FALSE); | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | PmError Pm_DeleteVirtualDevice(PmDeviceID id) | ||
| 1104 | { | ||
| 1105 | int i; | ||
| 1106 | const char *interf = pm_descriptors[id].pub.interf; | ||
| 1107 | PmError err = pmBadData; /* returned if we cannot find the interface- | ||
| 1108 | * specific delete function */ | ||
| 1109 | /* arg checking */ | ||
| 1110 | if (id < 0 || id >= pm_descriptor_len || | ||
| 1111 | pm_descriptors[id].pub.opened || pm_descriptors[id].deleted) { | ||
| 1112 | return pmInvalidDeviceId; | ||
| 1113 | } | ||
| 1114 | /* delete function pointer is in interfaces list */ | ||
| 1115 | for (i = 0; i < pm_interf_list_len; i++) { | ||
| 1116 | if (strcmp(pm_interf_list[i].interf, interf) == 0) { | ||
| 1117 | err = (*pm_interf_list[i].delete_fn)(id); | ||
| 1118 | break; | ||
| 1119 | } | ||
| 1120 | } | ||
| 1121 | pm_descriptors[id].deleted = TRUE; | ||
| 1122 | /* (pm_internal should already be NULL because !pub.opened) */ | ||
| 1123 | pm_descriptors[id].pm_internal = NULL; | ||
| 1124 | pm_descriptors[id].descriptor = NULL; | ||
| 1125 | return err; | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | PMEXPORT PmError Pm_SetChannelMask(PortMidiStream *stream, int mask) | ||
| 1129 | { | ||
| 1130 | PmInternal *midi = (PmInternal *) stream; | ||
| 1131 | PmError err = pmNoError; | ||
| 1132 | |||
| 1133 | if (midi == NULL) | ||
| 1134 | err = pmBadPtr; | ||
| 1135 | else | ||
| 1136 | midi->channel_mask = mask; | ||
| 1137 | |||
| 1138 | return pm_errmsg(err); | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | |||
| 1142 | PMEXPORT PmError Pm_SetFilter(PortMidiStream *stream, int32_t filters) | ||
| 1143 | { | ||
| 1144 | PmInternal *midi = (PmInternal *) stream; | ||
| 1145 | PmError err = pmNoError; | ||
| 1146 | |||
| 1147 | /* arg checking */ | ||
| 1148 | if (midi == NULL) | ||
| 1149 | err = pmBadPtr; | ||
| 1150 | else if (!pm_descriptors[midi->device_id].pub.opened) | ||
| 1151 | err = pmBadPtr; | ||
| 1152 | else | ||
| 1153 | midi->filters = filters; | ||
| 1154 | return pm_errmsg(err); | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | |||
| 1158 | PMEXPORT PmError Pm_Close(PortMidiStream *stream) | ||
| 1159 | { | ||
| 1160 | PmInternal *midi = (PmInternal *) stream; | ||
| 1161 | PmError err = pmNoError; | ||
| 1162 | |||
| 1163 | pm_hosterror = FALSE; | ||
| 1164 | /* arg checking */ | ||
| 1165 | if (midi == NULL) /* midi must point to something */ | ||
| 1166 | err = pmBadPtr; | ||
| 1167 | /* if it is an open device, the device_id will be valid */ | ||
| 1168 | else if (midi->device_id < 0 || midi->device_id >= pm_descriptor_len) | ||
| 1169 | err = pmBadPtr; | ||
| 1170 | /* and the device should be in the opened state */ | ||
| 1171 | else if (!pm_descriptors[midi->device_id].pub.opened) | ||
| 1172 | err = pmBadPtr; | ||
| 1173 | |||
| 1174 | if (err != pmNoError) | ||
| 1175 | goto error_return; | ||
| 1176 | |||
| 1177 | /* close the device */ | ||
| 1178 | err = (*midi->dictionary->close)(midi); | ||
| 1179 | /* even if an error occurred, continue with cleanup */ | ||
| 1180 | pm_descriptors[midi->device_id].pm_internal = NULL; | ||
| 1181 | pm_descriptors[midi->device_id].pub.opened = FALSE; | ||
| 1182 | if (midi->queue) Pm_QueueDestroy(midi->queue); | ||
| 1183 | pm_free(midi); | ||
| 1184 | error_return: | ||
| 1185 | /* system dependent code must set pm_hosterror and | ||
| 1186 | * pm_hosterror_text if a pmHostError occurs. | ||
| 1187 | */ | ||
| 1188 | return pm_errmsg(err); | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | PmError Pm_Synchronize(PortMidiStream* stream) | ||
| 1192 | { | ||
| 1193 | PmInternal *midi = (PmInternal *) stream; | ||
| 1194 | PmError err = pmNoError; | ||
| 1195 | if (midi == NULL) | ||
| 1196 | err = pmBadPtr; | ||
| 1197 | else if (!pm_descriptors[midi->device_id].pub.output) | ||
| 1198 | err = pmBadPtr; | ||
| 1199 | else if (!pm_descriptors[midi->device_id].pub.opened) | ||
| 1200 | err = pmBadPtr; | ||
| 1201 | else | ||
| 1202 | midi->first_message = TRUE; | ||
| 1203 | return err; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | PMEXPORT PmError Pm_Abort(PortMidiStream* stream) | ||
| 1207 | { | ||
| 1208 | PmInternal *midi = (PmInternal *) stream; | ||
| 1209 | PmError err; | ||
| 1210 | /* arg checking */ | ||
| 1211 | if (midi == NULL) | ||
| 1212 | err = pmBadPtr; | ||
| 1213 | else if (!pm_descriptors[midi->device_id].pub.output) | ||
| 1214 | err = pmBadPtr; | ||
| 1215 | else if (!pm_descriptors[midi->device_id].pub.opened) | ||
| 1216 | err = pmBadPtr; | ||
| 1217 | else | ||
| 1218 | err = (*midi->dictionary->abort)(midi); | ||
| 1219 | |||
| 1220 | if (err == pmHostError) { | ||
| 1221 | midi->dictionary->check_host_error(midi); | ||
| 1222 | } | ||
| 1223 | return pm_errmsg(err); | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | |||
| 1227 | |||
| 1228 | /* pm_channel_filtered returns non-zero if the channel mask is | ||
| 1229 | blocking the current channel */ | ||
| 1230 | #define pm_channel_filtered(status, mask) \ | ||
| 1231 | ((((status) & 0xF0) != 0xF0) && (!(Pm_Channel((status) & 0x0F) & (mask)))) | ||
| 1232 | |||
| 1233 | |||
| 1234 | /* The following two functions will checks to see if a MIDI message | ||
| 1235 | matches the filtering criteria. Since the sysex routines only want | ||
| 1236 | to filter realtime messages, we need to have separate routines. | ||
| 1237 | */ | ||
| 1238 | |||
| 1239 | |||
| 1240 | /* pm_realtime_filtered returns non-zero if the filter will kill the | ||
| 1241 | current message. Note that only realtime messages are checked here. | ||
| 1242 | */ | ||
| 1243 | #define pm_realtime_filtered(status, filters) \ | ||
| 1244 | ((((status) & 0xF0) == 0xF0) && ((1 << ((status) & 0xF)) & (filters))) | ||
| 1245 | |||
| 1246 | /* | ||
| 1247 | return ((status == MIDI_ACTIVE) && (filters & PM_FILT_ACTIVE)) | ||
| 1248 | || ((status == MIDI_CLOCK) && (filters & PM_FILT_CLOCK)) | ||
| 1249 | || ((status == MIDI_START) && (filters & PM_FILT_PLAY)) | ||
| 1250 | || ((status == MIDI_STOP) && (filters & PM_FILT_PLAY)) | ||
| 1251 | || ((status == MIDI_CONTINUE) && (filters & PM_FILT_PLAY)) | ||
| 1252 | || ((status == MIDI_F9) && (filters & PM_FILT_F9)) | ||
| 1253 | || ((status == MIDI_FD) && (filters & PM_FILT_FD)) | ||
| 1254 | || ((status == MIDI_RESET) && (filters & PM_FILT_RESET)) | ||
| 1255 | || ((status == MIDI_MTC) && (filters & PM_FILT_MTC)) | ||
| 1256 | || ((status == MIDI_SONGPOS) && (filters & PM_FILT_SONG_POSITION)) | ||
| 1257 | || ((status == MIDI_SONGSEL) && (filters & PM_FILT_SONG_SELECT)) | ||
| 1258 | || ((status == MIDI_TUNE) && (filters & PM_FILT_TUNE)); | ||
| 1259 | }*/ | ||
| 1260 | |||
| 1261 | |||
| 1262 | /* pm_status_filtered returns non-zero if a filter will kill the | ||
| 1263 | current message, based on status. Note that sysex and real time are | ||
| 1264 | not checked. It is up to the subsystem (winmm, core midi, alsa) to | ||
| 1265 | filter sysex, as it is handled more easily and efficiently at that | ||
| 1266 | level. Realtime message are filtered in pm_realtime_filtered. | ||
| 1267 | */ | ||
| 1268 | #define pm_status_filtered(status, filters) \ | ||
| 1269 | ((1 << (16 + ((status) >> 4))) & (filters)) | ||
| 1270 | |||
| 1271 | |||
| 1272 | /* | ||
| 1273 | return ((status == MIDI_NOTE_ON) && (filters & PM_FILT_NOTE)) | ||
| 1274 | || ((status == MIDI_NOTE_OFF) && (filters & PM_FILT_NOTE)) | ||
| 1275 | || ((status == MIDI_CHANNEL_AT) && | ||
| 1276 | (filters & PM_FILT_CHANNEL_AFTERTOUCH)) | ||
| 1277 | || ((status == MIDI_POLY_AT) && (filters & PM_FILT_POLY_AFTERTOUCH)) | ||
| 1278 | || ((status == MIDI_PROGRAM) && (filters & PM_FILT_PROGRAM)) | ||
| 1279 | || ((status == MIDI_CONTROL) && (filters & PM_FILT_CONTROL)) | ||
| 1280 | || ((status == MIDI_PITCHBEND) && (filters & PM_FILT_PITCHBEND)); | ||
| 1281 | |||
| 1282 | } | ||
| 1283 | */ | ||
| 1284 | |||
| 1285 | static void pm_flush_sysex(PmInternal *midi, PmTimestamp timestamp) | ||
| 1286 | { | ||
| 1287 | PmEvent event; | ||
| 1288 | |||
| 1289 | /* there may be nothing in the buffer */ | ||
| 1290 | if (midi->message_count == 0) return; /* nothing to flush */ | ||
| 1291 | |||
| 1292 | event.message = midi->message; | ||
| 1293 | event.timestamp = timestamp; | ||
| 1294 | /* copied from pm_read_short, avoids filtering */ | ||
| 1295 | if (Pm_Enqueue(midi->queue, &event) == pmBufferOverflow) { | ||
| 1296 | midi->sysex_in_progress = FALSE; | ||
| 1297 | } | ||
| 1298 | midi->message_count = 0; | ||
| 1299 | midi->message = 0; | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | |||
| 1303 | /* pm_read_short and pm_read_bytes | ||
| 1304 | are the interface between system-dependent MIDI input handlers | ||
| 1305 | and the system-independent PortMIDI code. | ||
| 1306 | The input handler MUST obey these rules: | ||
| 1307 | 1) all short input messages must be sent to pm_read_short, which | ||
| 1308 | enqueues them to a FIFO for the application. | ||
| 1309 | 2) each buffer of sysex bytes should be reported by calling pm_read_bytes | ||
| 1310 | (which sets midi->sysex_in_progress). After the eox byte, | ||
| 1311 | pm_read_bytes will clear sysex_in_progress | ||
| 1312 | */ | ||
| 1313 | |||
| 1314 | /* pm_read_short is the place where all input messages arrive from | ||
| 1315 | system-dependent code such as pmwinmm.c. Here, the messages | ||
| 1316 | are entered into the PortMidi input buffer. | ||
| 1317 | */ | ||
| 1318 | void pm_read_short(PmInternal *midi, PmEvent *event) | ||
| 1319 | { | ||
| 1320 | int status; | ||
| 1321 | /* arg checking */ | ||
| 1322 | assert(midi != NULL); | ||
| 1323 | /* midi filtering is applied here */ | ||
| 1324 | status = Pm_MessageStatus(event->message); | ||
| 1325 | if (!pm_status_filtered(status, midi->filters) | ||
| 1326 | && (!is_real_time(status) || | ||
| 1327 | !pm_realtime_filtered(status, midi->filters)) | ||
| 1328 | && !pm_channel_filtered(status, midi->channel_mask)) { | ||
| 1329 | /* if sysex is in progress and we get a status byte, it had | ||
| 1330 | better be a realtime message or the starting SYSEX byte; | ||
| 1331 | otherwise, we exit the sysex_in_progress state | ||
| 1332 | */ | ||
| 1333 | if (midi->sysex_in_progress && (status & MIDI_STATUS_MASK)) { | ||
| 1334 | /* two choices: real-time or not. If it's real-time, then | ||
| 1335 | * this should be delivered as a sysex byte because it is | ||
| 1336 | * embedded in a sysex message | ||
| 1337 | */ | ||
| 1338 | if (is_real_time(status)) { | ||
| 1339 | midi->message |= (status << (8 * midi->message_count++)); | ||
| 1340 | if (midi->message_count == 4) { | ||
| 1341 | pm_flush_sysex(midi, event->timestamp); | ||
| 1342 | } | ||
| 1343 | } else { /* otherwise, it's not real-time. This interrupts | ||
| 1344 | * a sysex message in progress */ | ||
| 1345 | midi->sysex_in_progress = FALSE; | ||
| 1346 | } | ||
| 1347 | } else if (Pm_Enqueue(midi->queue, event) == pmBufferOverflow) { | ||
| 1348 | midi->sysex_in_progress = FALSE; | ||
| 1349 | } | ||
| 1350 | } | ||
| 1351 | } | ||
| 1352 | |||
| 1353 | |||
| 1354 | /* pm_read_bytes -- a sequence of bytes has been read from a device. | ||
| 1355 | * parse the bytes into PmEvents and put them in the queue. | ||
| 1356 | * midi - the midi device | ||
| 1357 | * data - the bytes | ||
| 1358 | * len - the number of bytes | ||
| 1359 | * timestamp - when were the bytes received? | ||
| 1360 | * | ||
| 1361 | * returns how many bytes processed, which is always the len parameter | ||
| 1362 | */ | ||
| 1363 | unsigned int pm_read_bytes(PmInternal *midi, const unsigned char *data, | ||
| 1364 | int len, PmTimestamp timestamp) | ||
| 1365 | { | ||
| 1366 | int i = 0; /* index into data, must not be unsigned (!) */ | ||
| 1367 | PmEvent event; | ||
| 1368 | event.timestamp = timestamp; | ||
| 1369 | assert(midi); | ||
| 1370 | |||
| 1371 | /* Since sysex messages may have embedded real-time messages, we | ||
| 1372 | * cannot simply send every consecutive group of 4 bytes as sysex | ||
| 1373 | * data. Instead, we insert each data byte into midi->message and | ||
| 1374 | * keep count using midi->message_count. If we encounter a | ||
| 1375 | * real-time message, it is sent immediately as a 1-byte PmEvent, | ||
| 1376 | * while sysex bytes are sent as PmEvents in groups of 4 bytes | ||
| 1377 | * until the sysex is either terminated by EOX (F7) or a | ||
| 1378 | * non-real-time message is encountered, indicating that the EOX | ||
| 1379 | * was dropped. | ||
| 1380 | */ | ||
| 1381 | |||
| 1382 | /* This is a finite state machine so that we can accept any number | ||
| 1383 | * of bytes, even if they contain partial messages. | ||
| 1384 | * | ||
| 1385 | * midi->sysex_in_progress says we are expecting sysex message bytes | ||
| 1386 | * (otherwise, expect a short message or real-time message) | ||
| 1387 | * midi->message accumulates bytes to enqueue for application | ||
| 1388 | * midi->message_count is the number of bytes accumulated | ||
| 1389 | * midi->short_message_count is how many bytes we need in midi->message, | ||
| 1390 | * therefore midi->message_count, before we have a complete message | ||
| 1391 | * midi->running_status is running status or 0 if there is none | ||
| 1392 | * | ||
| 1393 | * Set running status when: A status byte < F0 is received. | ||
| 1394 | * Clear running status when: A status byte from F0 through F7 is | ||
| 1395 | * received. | ||
| 1396 | * Ignore (drop) data bytes when running status is 0. | ||
| 1397 | * | ||
| 1398 | * Our output buffer (the application input buffer) can overflow | ||
| 1399 | * at any time. If that occurs, we have to clear sysex_in_progress | ||
| 1400 | * (otherwise, the buffer could be flushed and we could resume | ||
| 1401 | * inserting sysex bytes into the buffer, resulting in a continuation | ||
| 1402 | * of a sysex message even though a buffer full of bytes was dropped.) | ||
| 1403 | * | ||
| 1404 | * Since we have to parse everything and form <=4-byte PmMessages, | ||
| 1405 | * we send all messages via pm_read_short, which filters messages | ||
| 1406 | * according to midi->filters and clears sysex_in_progress on | ||
| 1407 | * buffer overflow. This also provides a "short cut" for short | ||
| 1408 | * messages that are already parsed, allowing API-specific code | ||
| 1409 | * to bypass this more expensive state machine. What if we are | ||
| 1410 | * getting a sysex message, but it is interrupted by a short | ||
| 1411 | * message (status 80-EF) and a direct call to pm_read_short? | ||
| 1412 | * Without some care, the state machine would still be in | ||
| 1413 | * sysex_in_progress mode, and subsequent data bytes would be | ||
| 1414 | * accumulated as more sysex data, which is wrong since you | ||
| 1415 | * cannot have a short message in the middle of a sysex message. | ||
| 1416 | * To avoid this problem, pm_read_short clears sysex_in_progress | ||
| 1417 | * when a non-real-time short message arrives. | ||
| 1418 | */ | ||
| 1419 | |||
| 1420 | while (i < len) { | ||
| 1421 | unsigned char byte = data[i++]; | ||
| 1422 | if (is_real_time(byte)) { | ||
| 1423 | event.message = byte; | ||
| 1424 | pm_read_short(midi, &event); | ||
| 1425 | } else if (byte & MIDI_STATUS_MASK && byte != MIDI_EOX) { | ||
| 1426 | midi->message = byte; | ||
| 1427 | midi->message_count = 1; | ||
| 1428 | if (byte == MIDI_SYSEX) { | ||
| 1429 | midi->sysex_in_progress = TRUE; | ||
| 1430 | } else { | ||
| 1431 | midi->sysex_in_progress = FALSE; | ||
| 1432 | midi->short_message_count = pm_midi_length(midi->message); | ||
| 1433 | /* maybe we're done already with a 1-byte message: */ | ||
| 1434 | if (midi->short_message_count == 1) { | ||
| 1435 | pm_read_short(midi, &event); | ||
| 1436 | midi->message_count = 0; | ||
| 1437 | } | ||
| 1438 | } | ||
| 1439 | } else if (midi->sysex_in_progress) { /* sysex data byte */ | ||
| 1440 | /* accumulate sysex message data or EOX */ | ||
| 1441 | midi->message |= (byte << (8 * midi->message_count++)); | ||
| 1442 | if (midi->message_count == 4 || byte == MIDI_EOX) { | ||
| 1443 | event.message = midi->message; | ||
| 1444 | /* enqueue if not filtered, and then if there is overflow, | ||
| 1445 | stop sysex_in_progress */ | ||
| 1446 | if (!(midi->filters & PM_FILT_SYSEX) && | ||
| 1447 | Pm_Enqueue(midi->queue, &event) == pmBufferOverflow) { | ||
| 1448 | midi->sysex_in_progress = FALSE; | ||
| 1449 | } else if (byte == MIDI_EOX) { /* continue unless EOX */ | ||
| 1450 | midi->sysex_in_progress = FALSE; | ||
| 1451 | } | ||
| 1452 | midi->message_count = 0; | ||
| 1453 | midi->message = 0; | ||
| 1454 | } | ||
| 1455 | } else { /* no sysex in progress, must be short message */ | ||
| 1456 | if (midi->message_count == 0) { /* need a running status */ | ||
| 1457 | if (midi->running_status) { | ||
| 1458 | midi->message = midi->running_status; | ||
| 1459 | midi->message_count = 1; | ||
| 1460 | } else { /* drop data byte - not sysex and no status byte */ | ||
| 1461 | continue; | ||
| 1462 | } | ||
| 1463 | } | ||
| 1464 | midi->message |= (byte << (8 * midi->message_count++)); | ||
| 1465 | if (midi->message_count == midi->short_message_count) { | ||
| 1466 | event.message = midi->message; | ||
| 1467 | pm_read_short(midi, &event); | ||
| 1468 | } | ||
| 1469 | } | ||
| 1470 | } | ||
| 1471 | return i; | ||
| 1472 | } | ||
diff --git a/portmidi/pm_common/portmidi.h b/portmidi/pm_common/portmidi.h new file mode 100755 index 0000000..8696a73 --- /dev/null +++ b/portmidi/pm_common/portmidi.h | |||
| @@ -0,0 +1,974 @@ | |||
| 1 | #ifndef PORTMIDI_PORTMIDI_H | ||
| 2 | #define PORTMIDI_PORTMIDI_H | ||
| 3 | |||
| 4 | #ifdef __cplusplus | ||
| 5 | extern "C" { | ||
| 6 | #endif /* __cplusplus */ | ||
| 7 | |||
| 8 | /* | ||
| 9 | * PortMidi Portable Real-Time MIDI Library | ||
| 10 | * PortMidi API Header File | ||
| 11 | * Latest version available at: http://sourceforge.net/projects/portmedia | ||
| 12 | * | ||
| 13 | * Copyright (c) 1999-2000 Ross Bencina and Phil Burk | ||
| 14 | * Copyright (c) 2001-2006 Roger B. Dannenberg | ||
| 15 | * | ||
| 16 | * Permission is hereby granted, free of charge, to any person obtaining | ||
| 17 | * a copy of this software and associated documentation files | ||
| 18 | * (the "Software"), to deal in the Software without restriction, | ||
| 19 | * including without limitation the rights to use, copy, modify, merge, | ||
| 20 | * publish, distribute, sublicense, and/or sell copies of the Software, | ||
| 21 | * and to permit persons to whom the Software is furnished to do so, | ||
| 22 | * subject to the following conditions: | ||
| 23 | * | ||
| 24 | * The above copyright notice and this permission notice shall be | ||
| 25 | * included in all copies or substantial portions of the Software. | ||
| 26 | * | ||
| 27 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 28 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 29 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| 30 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR | ||
| 31 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | ||
| 32 | * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
| 33 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 34 | */ | ||
| 35 | |||
| 36 | /* | ||
| 37 | * The text above constitutes the entire PortMidi license; however, | ||
| 38 | * the PortMusic community also makes the following non-binding requests: | ||
| 39 | * | ||
| 40 | * Any person wishing to distribute modifications to the Software is | ||
| 41 | * requested to send the modifications to the original developer so that | ||
| 42 | * they can be incorporated into the canonical version. It is also | ||
| 43 | * requested that these non-binding requests be included along with the | ||
| 44 | * license above. | ||
| 45 | */ | ||
| 46 | |||
| 47 | /* CHANGELOG FOR PORTMIDI | ||
| 48 | * (see ../CHANGELOG.txt) | ||
| 49 | * | ||
| 50 | * NOTES ON HOST ERROR REPORTING: | ||
| 51 | * | ||
| 52 | * PortMidi errors (of type PmError) are generic, | ||
| 53 | * system-independent errors. When an error does not map to one of | ||
| 54 | * the more specific PmErrors, the catch-all code pmHostError is | ||
| 55 | * returned. This means that PortMidi has retained a more specific | ||
| 56 | * system-dependent error code. The caller can get more information | ||
| 57 | * by calling Pm_GetHostErrorText() to get a text string describing | ||
| 58 | * the error. Host errors can arise asynchronously from callbacks, | ||
| 59 | * * so there is no specific return code. Asynchronous errors are | ||
| 60 | * checked and reported by Pm_Poll. You can also check by calling | ||
| 61 | * Pm_HasHostError(). If this returns TRUE, Pm_GetHostErrorText() | ||
| 62 | * will return a text description of the error. | ||
| 63 | * | ||
| 64 | * NOTES ON COMPILE-TIME SWITCHES | ||
| 65 | * | ||
| 66 | * DEBUG assumes stdio and a console. Use this if you want | ||
| 67 | * automatic, simple error reporting, e.g. for prototyping. If | ||
| 68 | * you are using MFC or some other graphical interface with no | ||
| 69 | * console, DEBUG probably should be undefined. | ||
| 70 | * PM_CHECK_ERRORS more-or-less takes over error checking for | ||
| 71 | * return values, stopping your program and printing error | ||
| 72 | * messages when an error occurs. This also uses stdio for | ||
| 73 | * console text I/O. You can selectively disable this error | ||
| 74 | * checking by declaring extern int pm_check_errors; and | ||
| 75 | * setting pm_check_errors = FALSE; You can also reenable. | ||
| 76 | */ | ||
| 77 | /** | ||
| 78 | \defgroup grp_basics Basic Definitions | ||
| 79 | @{ | ||
| 80 | */ | ||
| 81 | |||
| 82 | #include <stdint.h> | ||
| 83 | |||
| 84 | #ifdef _WINDLL | ||
| 85 | #define PMEXPORT __declspec(dllexport) | ||
| 86 | #else | ||
| 87 | #define PMEXPORT | ||
| 88 | #endif | ||
| 89 | |||
| 90 | #ifndef FALSE | ||
| 91 | #define FALSE 0 | ||
| 92 | #endif | ||
| 93 | #ifndef TRUE | ||
| 94 | #define TRUE 1 | ||
| 95 | #endif | ||
| 96 | |||
| 97 | /* default size of buffers for sysex transmission: */ | ||
| 98 | #define PM_DEFAULT_SYSEX_BUFFER_SIZE 1024 | ||
| 99 | |||
| 100 | |||
| 101 | typedef enum { | ||
| 102 | pmNoError = 0, /**< Normal return value indicating no error. */ | ||
| 103 | pmNoData = 0, /**< @brief No error, also indicates no data available. | ||
| 104 | * Use this constant where a value greater than zero would | ||
| 105 | * indicate data is available. | ||
| 106 | */ | ||
| 107 | pmGotData = 1, /**< A "no error" return also indicating data available. */ | ||
| 108 | pmHostError = -10000, | ||
| 109 | pmInvalidDeviceId, /**< Out of range or | ||
| 110 | * output device when input is requested or | ||
| 111 | * input device when output is requested or | ||
| 112 | * device is already opened. | ||
| 113 | */ | ||
| 114 | pmInsufficientMemory, | ||
| 115 | pmBufferTooSmall, | ||
| 116 | pmBufferOverflow, | ||
| 117 | pmBadPtr, /**< #PortMidiStream parameter is NULL or | ||
| 118 | * stream is not opened or | ||
| 119 | * stream is output when input is required or | ||
| 120 | * stream is input when output is required. */ | ||
| 121 | pmBadData, /**< Illegal midi data, e.g., missing EOX. */ | ||
| 122 | pmInternalError, | ||
| 123 | pmBufferMaxSize, /**< Buffer is already as large as it can be. */ | ||
| 124 | pmNotImplemented, /**< The function is not implemented, nothing was done. */ | ||
| 125 | pmInterfaceNotSupported, /**< The requested interface is not supported. */ | ||
| 126 | pmNameConflict, /**< Cannot create virtual device because name is taken. */ | ||
| 127 | pmDeviceRemoved /**< Output attempted after (USB) device was removed. */ | ||
| 128 | /* NOTE: If you add a new error type, you must update Pm_GetErrorText(). */ | ||
| 129 | } PmError; /**< @brief @enum PmError PortMidi error code; a common return type. | ||
| 130 | * No error is indicated by zero; errors are indicated by < 0. | ||
| 131 | */ | ||
| 132 | |||
| 133 | /** | ||
| 134 | Pm_Initialize() is the library initialization function - call this before | ||
| 135 | using the library. | ||
| 136 | |||
| 137 | *NOTE:* PortMidi scans for available devices when #Pm_Initialize | ||
| 138 | is called. To observe subsequent changes in the available | ||
| 139 | devices, you must shut down PortMidi by calling #Pm_Terminate and | ||
| 140 | then restart by calling #Pm_Initialize again. *IMPORTANT*: On | ||
| 141 | MacOS, #Pm_Initialize *must* always be called on the same | ||
| 142 | thread. Otherwise, changes in the available MIDI devices will | ||
| 143 | *not* be seen by PortMidi. As an example, if you start PortMidi in | ||
| 144 | a thread for processing MIDI, do not try to rescan devices by | ||
| 145 | calling #Pm_Initialize in a GUI thread. Instead, start PortMidi | ||
| 146 | the first time and every time in the GUI thread. Alternatively, | ||
| 147 | let the GUI request a restart in the MIDI thread. (These | ||
| 148 | restrictions only apply to macOS.) Speaking of threads, on all | ||
| 149 | platforms, you are allowed to call #Pm_Initialize in one thread, | ||
| 150 | yet send MIDI or poll for incoming MIDI in another | ||
| 151 | thread. However, PortMidi is not "thread safe," which means you | ||
| 152 | cannot allow threads to call PortMidi functions concurrently. | ||
| 153 | |||
| 154 | @return pmNoError. | ||
| 155 | |||
| 156 | PortMidi is designed to support multiple interfaces (such as ALSA, | ||
| 157 | CoreMIDI and WinMM). It is possible to return pmNoError because there | ||
| 158 | are no supported interfaces. In that case, zero devices will be | ||
| 159 | available. | ||
| 160 | */ | ||
| 161 | PMEXPORT PmError Pm_Initialize(void); | ||
| 162 | |||
| 163 | /** | ||
| 164 | Pm_Terminate() is the library termination function - call this after | ||
| 165 | using the library. | ||
| 166 | */ | ||
| 167 | PMEXPORT PmError Pm_Terminate(void); | ||
| 168 | |||
| 169 | /** Represents an open MIDI device. */ | ||
| 170 | typedef void PortMidiStream; | ||
| 171 | |||
| 172 | /** A shorter form of #PortMidiStream. */ | ||
| 173 | #define PmStream PortMidiStream | ||
| 174 | |||
| 175 | /** Test whether stream has a pending host error. Normally, the client | ||
| 176 | finds out about errors through returned error codes, but some | ||
| 177 | errors can occur asynchronously where the client does not | ||
| 178 | explicitly call a function, and therefore cannot receive an error | ||
| 179 | code. The client can test for a pending error using | ||
| 180 | Pm_HasHostError(). If true, the error can be accessed by calling | ||
| 181 | Pm_GetHostErrorText(). Pm_Poll() is similar to Pm_HasHostError(), | ||
| 182 | but if there is no error, it will return TRUE (1) if there is a | ||
| 183 | pending input message. | ||
| 184 | */ | ||
| 185 | PMEXPORT int Pm_HasHostError(PortMidiStream * stream); | ||
| 186 | |||
| 187 | |||
| 188 | /** Translate portmidi error number into human readable message. | ||
| 189 | These strings are constants (set at compile time) so client has | ||
| 190 | no need to allocate storage. | ||
| 191 | */ | ||
| 192 | PMEXPORT const char *Pm_GetErrorText(PmError errnum); | ||
| 193 | |||
| 194 | /** Translate portmidi host error into human readable message. | ||
| 195 | These strings are computed at run time, so client has to allocate storage. | ||
| 196 | After this routine executes, the host error is cleared. | ||
| 197 | */ | ||
| 198 | PMEXPORT void Pm_GetHostErrorText(char * msg, unsigned int len); | ||
| 199 | |||
| 200 | /** Any host error msg has at most this many characters, including EOS. */ | ||
| 201 | #define PM_HOST_ERROR_MSG_LEN 256u | ||
| 202 | |||
| 203 | /** Devices are represented as small integers. Device ids range from 0 | ||
| 204 | to Pm_CountDevices()-1. Pm_GetDeviceInfo() is used to get information | ||
| 205 | about the device, and Pm_OpenInput() and PmOpenOutput() are used to | ||
| 206 | open the device. | ||
| 207 | */ | ||
| 208 | typedef int PmDeviceID; | ||
| 209 | |||
| 210 | /** This PmDeviceID (constant) value represents no device and may be | ||
| 211 | returned by Pm_GetDefaultInputDeviceID() or | ||
| 212 | Pm_GetDefaultOutputDeviceID() if no default exists. | ||
| 213 | */ | ||
| 214 | #define pmNoDevice -1 | ||
| 215 | |||
| 216 | /** MIDI device information is returned in this structure, which is | ||
| 217 | owned by PortMidi and read-only to applications. See Pm_GetDeviceInfo(). | ||
| 218 | */ | ||
| 219 | #define PM_DEVICEINFO_VERS 200 | ||
| 220 | typedef struct { | ||
| 221 | int structVersion; /**< @brief this internal structure version */ | ||
| 222 | const char *interf; /**< @brief underlying MIDI API, e.g. | ||
| 223 | "MMSystem" or "DirectX" */ | ||
| 224 | char *name; /**< @brief device name, e.g. "USB MidiSport 1x1" */ | ||
| 225 | int input; /**< @brief true iff input is available */ | ||
| 226 | int output; /**< @brief true iff output is available */ | ||
| 227 | int opened; /**< @brief used by generic PortMidi for error checking */ | ||
| 228 | int is_virtual; /**< @brief true iff this is/was a virtual device */ | ||
| 229 | } PmDeviceInfo; | ||
| 230 | |||
| 231 | /** MIDI system-dependent device or driver info is passed in this | ||
| 232 | structure, which is owned by the caller. | ||
| 233 | */ | ||
| 234 | #define PM_SYSDEPINFO_VERS 210 | ||
| 235 | |||
| 236 | enum PmSysDepPropertyKey { | ||
| 237 | pmKeyNone = 0, /**< a "noop" key value */ | ||
| 238 | /** CoreMIDI Manufacturer name, value is string */ | ||
| 239 | pmKeyCoreMidiManufacturer = 1, | ||
| 240 | /** Linux ALSA snd_seq_port_info_set_name, value is a string. Can be | ||
| 241 | passed in PmSysDepInfo to Pm_OpenInput or Pm_OpenOutput when opening | ||
| 242 | a device. The created port will be named accordingly and will be | ||
| 243 | visible for externally made connections (subscriptions). (Linux ALSA | ||
| 244 | ports are always enabled for this, but only get application-specific | ||
| 245 | names if you give it one.) This key/value is ignored when opening | ||
| 246 | virtual ports, which are named when they are created.) */ | ||
| 247 | pmKeyAlsaPortName = 2, | ||
| 248 | /** Linux ALSA snd_seq_set_client_name, value is a string. | ||
| 249 | Can be passed in PmSysDepInfo to Pm_OpenInput or Pm_OpenOutput. | ||
| 250 | Pm_CreateVirtualInput or Pm_CreateVirtualOutput. Will override | ||
| 251 | any previously set client name and applies to all ports. */ | ||
| 252 | pmKeyAlsaClientName = 3 | ||
| 253 | /* if system-dependent code introduces more options, register | ||
| 254 | the key here to avoid conflicts. */ | ||
| 255 | }; | ||
| 256 | |||
| 257 | /** System-dependent information can be passed when creating and opening | ||
| 258 | ports using this data structure, which stores alternating keys and | ||
| 259 | values (addresses). See `pm_test/sendvirtual.c`, `pm_test/recvvirtual.c`, | ||
| 260 | and `pm_test/testio.c` for examples. | ||
| 261 | */ | ||
| 262 | typedef struct { | ||
| 263 | int structVersion; /**< @brief this structure version */ | ||
| 264 | int length; /**< @brief number of properties in this structure */ | ||
| 265 | struct { | ||
| 266 | enum PmSysDepPropertyKey key; | ||
| 267 | const void *value; | ||
| 268 | } properties[]; | ||
| 269 | } PmSysDepInfo; | ||
| 270 | |||
| 271 | |||
| 272 | /** Get devices count, ids range from 0 to Pm_CountDevices()-1. */ | ||
| 273 | PMEXPORT int Pm_CountDevices(void); | ||
| 274 | |||
| 275 | /** | ||
| 276 | Return the default device ID or pmNoDevice if there are no devices. | ||
| 277 | The result (but not pmNoDevice) can be passed to Pm_OpenMidi(). | ||
| 278 | |||
| 279 | The use of these functions is not recommended. There is no natural | ||
| 280 | "default device" on any system, so defaults must be set by users. | ||
| 281 | (Currently, PortMidi just returns the first device it finds as | ||
| 282 | "default", so if there *is* a default, implementors should use | ||
| 283 | pm_add_device to add system default input and output devices | ||
| 284 | first.) | ||
| 285 | |||
| 286 | The recommended solution is pass the burden to applications. It is | ||
| 287 | easy to scan devices with PortMidi and build a device menu, and to | ||
| 288 | save menu selections in application preferences for next | ||
| 289 | time. This is my recommendation for any GUI program. For simple | ||
| 290 | command-line applications and utilities, see pm_test where all the | ||
| 291 | test programs now accept device numbers on the command line and/or | ||
| 292 | prompt for their entry. | ||
| 293 | |||
| 294 | On linux, you can create virtual ports and use an external program | ||
| 295 | to set up inter-application and device connections. | ||
| 296 | |||
| 297 | Some advice for preferences: MIDI devices used to be built-in or | ||
| 298 | plug-in cards, so the numbers rarely changed. Now MIDI devices are | ||
| 299 | often plug-in USB devices, so device numbers change, and you | ||
| 300 | probably need to design to reinitialize PortMidi to rescan | ||
| 301 | devices. MIDI is pretty stateless, so this isn't a big problem, | ||
| 302 | although it means you cannot find a new device while playing or | ||
| 303 | recording MIDI. | ||
| 304 | |||
| 305 | Since device numbering can change whenever a USB device is plugged | ||
| 306 | in, preferences should record *names* of devices rather than | ||
| 307 | device numbers. It is simple enough to use string matching to find | ||
| 308 | a prefered device, so PortMidi does not provide any built-in | ||
| 309 | lookup function. | ||
| 310 | */ | ||
| 311 | PMEXPORT PmDeviceID Pm_GetDefaultInputDeviceID(void); | ||
| 312 | |||
| 313 | /** @brief see PmDeviceID Pm_GetDefaultInputDeviceID() */ | ||
| 314 | PMEXPORT PmDeviceID Pm_GetDefaultOutputDeviceID(void); | ||
| 315 | |||
| 316 | /** Find a device that matches a pattern. | ||
| 317 | |||
| 318 | @param pattern a substring of the device name, or if the pattern | ||
| 319 | contains the two-character separator ", ", then the first part of | ||
| 320 | the pattern represents a device interface substring and the second | ||
| 321 | part after the separator represents a device name substring. | ||
| 322 | |||
| 323 | @param is_input restricts the search to an input when true, or an | ||
| 324 | output when false. | ||
| 325 | |||
| 326 | @return the number of the first device whose device interface | ||
| 327 | contains the interface pattern (if any), whose device name | ||
| 328 | contains the name pattern, and whose direction (input or output) | ||
| 329 | matches the #is_input parameter. If no match is found, #pmNoDevice | ||
| 330 | (-1) is returned. | ||
| 331 | */ | ||
| 332 | PMEXPORT PmDeviceID Pm_FindDevice(char *pattern, int is_input); | ||
| 333 | |||
| 334 | |||
| 335 | /** Represents a millisecond clock with arbitrary start time. | ||
| 336 | This type is used for all MIDI timestamps and clocks. | ||
| 337 | */ | ||
| 338 | typedef int32_t PmTimestamp; | ||
| 339 | typedef PmTimestamp (*PmTimeProcPtr)(void *time_info); | ||
| 340 | |||
| 341 | /** TRUE if t1 before t2 */ | ||
| 342 | #define PmBefore(t1,t2) (((t1)-(t2)) < 0) | ||
| 343 | /** @} */ | ||
| 344 | /** | ||
| 345 | \defgroup grp_device Input/Output Devices Handling | ||
| 346 | @{ | ||
| 347 | */ | ||
| 348 | /** Get a PmDeviceInfo structure describing a MIDI device. | ||
| 349 | |||
| 350 | @param id the device to be queried. | ||
| 351 | |||
| 352 | If \p id is out of range or if the device designates a deleted | ||
| 353 | virtual device, the function returns NULL. | ||
| 354 | |||
| 355 | The returned structure is owned by the PortMidi implementation and | ||
| 356 | must not be manipulated or freed. The pointer is guaranteed to be | ||
| 357 | valid between calls to Pm_Initialize() and Pm_Terminate(). | ||
| 358 | */ | ||
| 359 | PMEXPORT const PmDeviceInfo *Pm_GetDeviceInfo(PmDeviceID id); | ||
| 360 | |||
| 361 | /** Open a MIDI device for input. | ||
| 362 | |||
| 363 | @param stream the address of a #PortMidiStream pointer which will | ||
| 364 | receive a pointer to the newly opened stream. | ||
| 365 | |||
| 366 | @param inputDevice the ID of the device to be opened (see #PmDeviceID). | ||
| 367 | |||
| 368 | @param inputSysDepInfo a pointer to an optional system-dependent | ||
| 369 | data structure (a #PmSysDepInfo struct) containing additional | ||
| 370 | information for device setup or handle processing. This parameter | ||
| 371 | is never required for correct operation. If not used, specify | ||
| 372 | NULL. Declared `void *` here for backward compatibility. Note that | ||
| 373 | with Linux ALSA, you can use this parameter to specify a client name | ||
| 374 | and port name. | ||
| 375 | |||
| 376 | @param bufferSize the number of input events to be buffered | ||
| 377 | waiting to be read using Pm_Read(). Messages will be lost if the | ||
| 378 | number of unread messages exceeds this value. | ||
| 379 | |||
| 380 | @param time_proc (address of) a procedure that returns time in | ||
| 381 | milliseconds. It may be NULL, in which case a default millisecond | ||
| 382 | timebase (PortTime) is used. If the application wants to use | ||
| 383 | PortTime, it should start the timer (call Pt_Start) before calling | ||
| 384 | Pm_OpenInput or Pm_OpenOutput. If the application tries to start | ||
| 385 | the timer *after* Pm_OpenInput or Pm_OpenOutput, it may get a | ||
| 386 | ptAlreadyStarted error from Pt_Start, and the application's | ||
| 387 | preferred time resolution and callback function will be ignored. | ||
| 388 | \p time_proc result values are appended to incoming MIDI data, | ||
| 389 | normally by mapping system-provided timestamps to the \p time_proc | ||
| 390 | timestamps to maintain the precision of system-provided | ||
| 391 | timestamps. | ||
| 392 | |||
| 393 | @param time_info is a pointer passed to time_proc. | ||
| 394 | |||
| 395 | @return #pmNoError and places a pointer to a valid | ||
| 396 | #PortMidiStream in the stream argument. If the open operation | ||
| 397 | fails, a nonzero error code is returned (see #PMError) and | ||
| 398 | the value of stream is invalid. | ||
| 399 | |||
| 400 | Any stream that is successfully opened should eventually be closed | ||
| 401 | by calling Pm_Close(). | ||
| 402 | */ | ||
| 403 | PMEXPORT PmError Pm_OpenInput(PortMidiStream** stream, | ||
| 404 | PmDeviceID inputDevice, | ||
| 405 | void *inputSysDepInfo, | ||
| 406 | int32_t bufferSize, | ||
| 407 | PmTimeProcPtr time_proc, | ||
| 408 | void *time_info); | ||
| 409 | |||
| 410 | /** Open a MIDI device for output. | ||
| 411 | |||
| 412 | @param stream the address of a #PortMidiStream pointer which will | ||
| 413 | receive a pointer to the newly opened stream. | ||
| 414 | |||
| 415 | @param outputDevice the ID of the device to be opened (see #PmDeviceID). | ||
| 416 | |||
| 417 | @param inputSysDepInfo a pointer to an optional system-specific | ||
| 418 | data structure (a #PmSysDepInfo struct) containing additional | ||
| 419 | information for device setup or handle processing. This parameter | ||
| 420 | is never required for correct operation. If not used, specify | ||
| 421 | NULL. Declared `void *` here for backward compatibility. Note that | ||
| 422 | with Linux ALSA, you can use this parameter to specify a client name | ||
| 423 | and port name. | ||
| 424 | |||
| 425 | @param bufferSize the number of output events to be buffered | ||
| 426 | waiting for output. In some cases -- see below -- PortMidi does | ||
| 427 | not buffer output at all and merely passes data to a lower-level | ||
| 428 | API, in which case \p bufferSize is ignored. Since MIDI speeds now | ||
| 429 | vary from 1 to 50 or more messages per ms (over USB), put some | ||
| 430 | thought into this number. E.g. if latency is 20ms and you want to | ||
| 431 | burst 100 messages in that time (5000 messages per second), you | ||
| 432 | should set \p bufferSize to at least 100. The default on Windows | ||
| 433 | assumes an average rate of 500 messages per second and in this | ||
| 434 | example, output would be slowed waiting for free buffers. | ||
| 435 | |||
| 436 | @param latency the delay in milliseconds applied to timestamps | ||
| 437 | to determine when the output should actually occur. (If latency is | ||
| 438 | < 0, 0 is assumed.) If latency is zero, timestamps are ignored | ||
| 439 | and all output is delivered immediately. If latency is greater | ||
| 440 | than zero, output is delayed until the message timestamp plus the | ||
| 441 | latency. (NOTE: the time is measured relative to the time source | ||
| 442 | indicated by time_proc. Timestamps are absolute, not relative | ||
| 443 | delays or offsets.) In some cases, PortMidi can obtain better | ||
| 444 | timing than your application by passing timestamps along to the | ||
| 445 | device driver or hardware, so the best strategy to minimize jitter | ||
| 446 | is: wait until the real time to send the message, compute the | ||
| 447 | message, attach the *ideal* output time (not the current real | ||
| 448 | time, because some time may have elapsed), and send the | ||
| 449 | message. The \p latency will be added to the timestamp, and | ||
| 450 | provided the elapsed computation time has not exceeded \p latency, | ||
| 451 | the message will be delivered according to the timestamp. If the | ||
| 452 | real time is already past the timestamp, the message will be | ||
| 453 | delivered as soon as possible. Latency may also help you to | ||
| 454 | synchronize MIDI data to audio data by matching \p latency to the | ||
| 455 | audio buffer latency. | ||
| 456 | |||
| 457 | @param time_proc (address of) a pointer to a procedure that | ||
| 458 | returns time in milliseconds. It may be NULL, in which case a | ||
| 459 | default millisecond timebase (PortTime) is used. If the | ||
| 460 | application wants to use PortTime, it should start the timer (call | ||
| 461 | Pt_Start) before calling #Pm_OpenInput or #Pm_OpenOutput. If the | ||
| 462 | application tries to start the timer *after* #Pm_OpenInput or | ||
| 463 | #Pm_OpenOutput, it may get a #ptAlreadyStarted error from #Pt_Start, | ||
| 464 | and the application's preferred time resolution and callback | ||
| 465 | function will be ignored. \p time_proc times are used to schedule | ||
| 466 | outgoing MIDI data (when latency is non-zero), usually by mapping | ||
| 467 | from time_proc timestamps to internal system timestamps to | ||
| 468 | maintain the precision of system-supported timing. | ||
| 469 | |||
| 470 | @param time_info a pointer passed to time_proc. | ||
| 471 | |||
| 472 | @return #pmNoError and places a pointer to a valid #PortMidiStream | ||
| 473 | in the stream argument. If the operation fails, a nonzero error | ||
| 474 | code is returned (see PMError) and the value of \p stream is | ||
| 475 | invalid. | ||
| 476 | |||
| 477 | Note: ALSA appears to have a fixed-size priority queue for timed | ||
| 478 | output messages. Testing indicates the queue can hold a little | ||
| 479 | over 400 3-byte MIDI messages. Thus, you can send 10,000 | ||
| 480 | messages/second if the latency is 30ms (30ms * 10000 msgs/sec * | ||
| 481 | 0.001 sec/ms = 300 msgs), but not if the latency is 50ms | ||
| 482 | (resulting in about 500 pending messages, which is greater than | ||
| 483 | the 400 message limit). Since timestamps in ALSA are relative, | ||
| 484 | they are of less value than absolute timestamps in macOS and | ||
| 485 | Windows. This is a limitation of ALSA and apparently a design | ||
| 486 | flaw. | ||
| 487 | |||
| 488 | Example 1: If I provide a timestamp of 5000, latency is 1, and | ||
| 489 | time_proc returns 4990, then the desired output time will be when | ||
| 490 | time_proc returns timestamp+latency = 5001. This will be 5001-4990 | ||
| 491 | = 11ms from now. | ||
| 492 | |||
| 493 | Example 2: If I want to send at exactly 5010, and latency is 10, I | ||
| 494 | should wait until 5000, compute the messages and provide a | ||
| 495 | timestamp of 5000. As long as computation takes less than 10ms, | ||
| 496 | the message will be delivered at time 5010. | ||
| 497 | |||
| 498 | Example 3 (recommended): It is often convenient to ignore latency. | ||
| 499 | E.g. if a sequence says to output at time 5010, just wait until | ||
| 500 | 5010, compute the message and use 5010 for the timestamp. Delivery | ||
| 501 | will then be at 5010+latency, but unless you are synchronizing to | ||
| 502 | something else, the absolute delay by latency will not matter. | ||
| 503 | |||
| 504 | Any stream that is successfully opened should eventually be closed | ||
| 505 | by calling Pm_Close(). | ||
| 506 | */ | ||
| 507 | PMEXPORT PmError Pm_OpenOutput(PortMidiStream** stream, | ||
| 508 | PmDeviceID outputDevice, | ||
| 509 | void *outputSysDepInfo, | ||
| 510 | int32_t bufferSize, | ||
| 511 | PmTimeProcPtr time_proc, | ||
| 512 | void *time_info, | ||
| 513 | int32_t latency); | ||
| 514 | |||
| 515 | /** Create a virtual input device. | ||
| 516 | |||
| 517 | @param name gives the virtual device name, which is visible to | ||
| 518 | other applications. | ||
| 519 | |||
| 520 | @param interf is the interface (System API) used to create the | ||
| 521 | device Default interfaces are "MMSystem", "CoreMIDI" and | ||
| 522 | "ALSA". Currently, these are the only ones implemented, but future | ||
| 523 | implementations could support DirectMusic, Jack, sndio, or others. | ||
| 524 | |||
| 525 | @param sysDepInfo contains interface-dependent additional | ||
| 526 | information (a #PmSysDepInfo struct), e.g., hints or options. This | ||
| 527 | parameter is never required for correct operation. If not used, | ||
| 528 | specify NULL. Declared `void *` here for backward compatibility. | ||
| 529 | |||
| 530 | @return a device ID or #pmNameConflict (\p name is invalid or | ||
| 531 | already exists) or #pmInterfaceNotSupported (\p interf is does not | ||
| 532 | match a supported interface). | ||
| 533 | |||
| 534 | The created virtual device appears to other applications as if it | ||
| 535 | is an output device. The device must be opened to obtain a stream | ||
| 536 | and read from it. | ||
| 537 | |||
| 538 | Virtual devices are not supported by Windows (Multimedia API). Calls | ||
| 539 | on Windows do nothing except return #pmNotImplemented. | ||
| 540 | */ | ||
| 541 | PMEXPORT PmError Pm_CreateVirtualInput(const char *name, | ||
| 542 | const char *interf, | ||
| 543 | void *sysDepInfo); | ||
| 544 | |||
| 545 | /** Create a virtual output device. | ||
| 546 | |||
| 547 | @param name gives the virtual device name, which is visible to | ||
| 548 | other applications. | ||
| 549 | |||
| 550 | @param interf is the interface (System API) used to create the | ||
| 551 | device Default interfaces are "MMSystem", "CoreMIDI" and | ||
| 552 | "ALSA". Currently, these are the only ones implemented, but future | ||
| 553 | implementations could support DirectMusic, Jack, sndio, or others. | ||
| 554 | |||
| 555 | @param sysDepInfo contains interface-dependent additional | ||
| 556 | information (a #PmSysDepInfo struct), e.g., hints or options. This | ||
| 557 | parameter is never required for correct operation. If not used, | ||
| 558 | specify NULL. Declared `void *` here for backward compatibility. | ||
| 559 | |||
| 560 | @return a device ID or #pmInvalidDeviceId (\p name is invalid or | ||
| 561 | already exists) or #pmInterfaceNotSupported (\p interf is does not | ||
| 562 | match a supported interface). | ||
| 563 | |||
| 564 | The created virtual device appears to other applications as if it | ||
| 565 | is an input device. The device must be opened to obtain a stream | ||
| 566 | and write to it. | ||
| 567 | |||
| 568 | Virtual devices are not supported by Windows (Multimedia API). Calls | ||
| 569 | on Windows do nothing except return #pmNotImplemented. | ||
| 570 | */ | ||
| 571 | PMEXPORT PmError Pm_CreateVirtualOutput(const char *name, | ||
| 572 | const char *interf, | ||
| 573 | void *sysDepInfo); | ||
| 574 | |||
| 575 | /** Remove a virtual device. | ||
| 576 | |||
| 577 | @param device a device ID (small integer) designating the device. | ||
| 578 | |||
| 579 | The device is removed; other applications can no longer see or open | ||
| 580 | this virtual device, which may be either for input or output. The | ||
| 581 | device must not be open. The device ID may be reused, but existing | ||
| 582 | devices are not renumbered. This means that the device ID could be | ||
| 583 | in the range from 0 to #Pm_CountDevices(), yet the device ID does | ||
| 584 | not designate a device. In that case, passing the ID to | ||
| 585 | #Pm_GetDeviceInfo() will return NULL. | ||
| 586 | |||
| 587 | @return #pmNoError if the device was deleted or #pmInvalidDeviceId | ||
| 588 | if the device is open, already deleted, or \p device is out of | ||
| 589 | range. | ||
| 590 | */ | ||
| 591 | PMEXPORT PmError Pm_DeleteVirtualDevice(PmDeviceID device); | ||
| 592 | /** @} */ | ||
| 593 | |||
| 594 | /** | ||
| 595 | @defgroup grp_events_filters Events and Filters Handling | ||
| 596 | @{ | ||
| 597 | */ | ||
| 598 | |||
| 599 | /* Filter bit-mask definitions */ | ||
| 600 | /** filter active sensing messages (0xFE): */ | ||
| 601 | #define PM_FILT_ACTIVE (1 << 0x0E) | ||
| 602 | /** filter system exclusive messages (0xF0): */ | ||
| 603 | #define PM_FILT_SYSEX (1 << 0x00) | ||
| 604 | /** filter MIDI clock message (0xF8) */ | ||
| 605 | #define PM_FILT_CLOCK (1 << 0x08) | ||
| 606 | /** filter play messages (start 0xFA, stop 0xFC, continue 0xFB) */ | ||
| 607 | #define PM_FILT_PLAY ((1 << 0x0A) | (1 << 0x0C) | (1 << 0x0B)) | ||
| 608 | /** filter tick messages (0xF9) */ | ||
| 609 | #define PM_FILT_TICK (1 << 0x09) | ||
| 610 | /** filter undefined FD messages */ | ||
| 611 | #define PM_FILT_FD (1 << 0x0D) | ||
| 612 | /** filter undefined real-time messages */ | ||
| 613 | #define PM_FILT_UNDEFINED PM_FILT_FD | ||
| 614 | /** filter reset messages (0xFF) */ | ||
| 615 | #define PM_FILT_RESET (1 << 0x0F) | ||
| 616 | /** filter all real-time messages */ | ||
| 617 | #define PM_FILT_REALTIME (PM_FILT_ACTIVE | PM_FILT_SYSEX | PM_FILT_CLOCK | \ | ||
| 618 | PM_FILT_PLAY | PM_FILT_UNDEFINED | PM_FILT_RESET | PM_FILT_TICK) | ||
| 619 | /** filter note-on and note-off (0x90-0x9F and 0x80-0x8F */ | ||
| 620 | #define PM_FILT_NOTE ((1 << 0x19) | (1 << 0x18)) | ||
| 621 | /** filter channel aftertouch (most midi controllers use this) (0xD0-0xDF)*/ | ||
| 622 | #define PM_FILT_CHANNEL_AFTERTOUCH (1 << 0x1D) | ||
| 623 | /** per-note aftertouch (0xA0-0xAF) */ | ||
| 624 | #define PM_FILT_POLY_AFTERTOUCH (1 << 0x1A) | ||
| 625 | /** filter both channel and poly aftertouch */ | ||
| 626 | #define PM_FILT_AFTERTOUCH (PM_FILT_CHANNEL_AFTERTOUCH | \ | ||
| 627 | PM_FILT_POLY_AFTERTOUCH) | ||
| 628 | /** Program changes (0xC0-0xCF) */ | ||
| 629 | #define PM_FILT_PROGRAM (1 << 0x1C) | ||
| 630 | /** Control Changes (CC's) (0xB0-0xBF)*/ | ||
| 631 | #define PM_FILT_CONTROL (1 << 0x1B) | ||
| 632 | /** Pitch Bender (0xE0-0xEF*/ | ||
| 633 | #define PM_FILT_PITCHBEND (1 << 0x1E) | ||
| 634 | /** MIDI Time Code (0xF1)*/ | ||
| 635 | #define PM_FILT_MTC (1 << 0x01) | ||
| 636 | /** Song Position (0xF2) */ | ||
| 637 | #define PM_FILT_SONG_POSITION (1 << 0x02) | ||
| 638 | /** Song Select (0xF3)*/ | ||
| 639 | #define PM_FILT_SONG_SELECT (1 << 0x03) | ||
| 640 | /** Tuning request (0xF6) */ | ||
| 641 | #define PM_FILT_TUNE (1 << 0x06) | ||
| 642 | /** All System Common messages (mtc, song position, song select, tune request) */ | ||
| 643 | #define PM_FILT_SYSTEMCOMMON (PM_FILT_MTC | PM_FILT_SONG_POSITION | \ | ||
| 644 | PM_FILT_SONG_SELECT | PM_FILT_TUNE) | ||
| 645 | |||
| 646 | |||
| 647 | /* Set filters on an open input stream to drop selected input types. | ||
| 648 | |||
| 649 | @param stream an open MIDI input stream. | ||
| 650 | |||
| 651 | @param filters indicate message types to filter (block). | ||
| 652 | |||
| 653 | @return #pmNoError or an error code. | ||
| 654 | |||
| 655 | By default, only active sensing messages are filtered. | ||
| 656 | To prohibit, say, active sensing and sysex messages, call | ||
| 657 | Pm_SetFilter(stream, PM_FILT_ACTIVE | PM_FILT_SYSEX); | ||
| 658 | |||
| 659 | Filtering is useful when midi routing or midi thru functionality | ||
| 660 | is being provided by the user application. | ||
| 661 | For example, you may want to exclude timing messages (clock, MTC, | ||
| 662 | start/stop/continue), while allowing note-related messages to pass. | ||
| 663 | Or you may be using a sequencer or drum-machine for MIDI clock | ||
| 664 | information but want to exclude any notes it may play. | ||
| 665 | */ | ||
| 666 | PMEXPORT PmError Pm_SetFilter(PortMidiStream* stream, int32_t filters); | ||
| 667 | |||
| 668 | /** Create a mask that filters one channel. */ | ||
| 669 | #define Pm_Channel(channel) (1<<(channel)) | ||
| 670 | |||
| 671 | /** Filter incoming messages based on channel. | ||
| 672 | |||
| 673 | @param stream an open MIDI input stream. | ||
| 674 | |||
| 675 | @param mask indicates channels to be received. | ||
| 676 | |||
| 677 | @return #pmNoError or an error code. | ||
| 678 | |||
| 679 | The \p mask is a 16-bit bitfield corresponding to appropriate channels. | ||
| 680 | The #Pm_Channel macro can assist in calling this function. | ||
| 681 | I.e. to receive only input on channel 1, call with | ||
| 682 | Pm_SetChannelMask(Pm_Channel(1)); | ||
| 683 | Multiple channels should be OR'd together, like | ||
| 684 | Pm_SetChannelMask(Pm_Channel(10) | Pm_Channel(11)) | ||
| 685 | |||
| 686 | Note that channels are numbered 0 to 15 (not 1 to 16). Most | ||
| 687 | synthesizer and interfaces number channels starting at 1, but | ||
| 688 | PortMidi numbers channels starting at 0. | ||
| 689 | |||
| 690 | All channels are allowed by default | ||
| 691 | */ | ||
| 692 | PMEXPORT PmError Pm_SetChannelMask(PortMidiStream *stream, int mask); | ||
| 693 | |||
| 694 | /** Terminate outgoing messages immediately. | ||
| 695 | |||
| 696 | @param stream an open MIDI output stream. | ||
| 697 | |||
| 698 | @result #pmNoError or an error code. | ||
| 699 | |||
| 700 | The caller should immediately close the output port; this call may | ||
| 701 | result in transmission of a partial MIDI message. There is no | ||
| 702 | abort for Midi input because the user can simply ignore messages | ||
| 703 | in the buffer and close an input device at any time. If the | ||
| 704 | specified behavior cannot be achieved through the system-level | ||
| 705 | interface (ALSA, CoreMIDI, etc.), the behavior may be that of | ||
| 706 | Pm_Close(). | ||
| 707 | */ | ||
| 708 | PMEXPORT PmError Pm_Abort(PortMidiStream* stream); | ||
| 709 | |||
| 710 | /** Close a midi stream, flush any pending buffers if possible. | ||
| 711 | |||
| 712 | @param stream an open MIDI input or output stream. | ||
| 713 | |||
| 714 | @result #pmNoError or an error code. | ||
| 715 | |||
| 716 | If the system-level interface (ALSA, CoreMIDI, etc.) does not | ||
| 717 | support flushing remaining messages, the behavior may be one of | ||
| 718 | the following (most preferred first): block until all pending | ||
| 719 | timestamped messages are delivered; deliver messages to a server | ||
| 720 | or kernel process for later delivery but return immediately; drop | ||
| 721 | messages (as in Pm_Abort()). Therefore, to be safe, applications | ||
| 722 | should wait until the output queue is empty before calling | ||
| 723 | Pm_Close(). E.g. calling Pt_Sleep(100 + latency); will give a | ||
| 724 | 100ms "cushion" beyond latency (if any) before closing. | ||
| 725 | */ | ||
| 726 | PMEXPORT PmError Pm_Close(PortMidiStream* stream); | ||
| 727 | |||
| 728 | /** (re)synchronize to the time_proc passed when the stream was opened. | ||
| 729 | |||
| 730 | @param stream an open MIDI input or output stream. | ||
| 731 | |||
| 732 | @result #pmNoError or an error code. | ||
| 733 | |||
| 734 | Typically, this is used when the stream must be opened before the | ||
| 735 | time_proc reference is actually advancing. In this case, message | ||
| 736 | timing may be erratic, but since timestamps of zero mean "send | ||
| 737 | immediately," initialization messages with zero timestamps can be | ||
| 738 | written without a functioning time reference and without | ||
| 739 | problems. Before the first MIDI message with a non-zero timestamp | ||
| 740 | is written to the stream, the time reference must begin to advance | ||
| 741 | (for example, if the time_proc computes time based on audio | ||
| 742 | samples, time might begin to advance when an audio stream becomes | ||
| 743 | active). After time_proc return values become valid, and BEFORE | ||
| 744 | writing the first non-zero timestamped MIDI message, call | ||
| 745 | Pm_Synchronize() so that PortMidi can observe the difference | ||
| 746 | between the current time_proc value and its MIDI stream time. | ||
| 747 | |||
| 748 | In the more normal case where time_proc values advance | ||
| 749 | continuously, there is no need to call #Pm_Synchronize. PortMidi | ||
| 750 | will always synchronize at the first output message and | ||
| 751 | periodically thereafter. | ||
| 752 | */ | ||
| 753 | PMEXPORT PmError Pm_Synchronize(PortMidiStream* stream); | ||
| 754 | |||
| 755 | |||
| 756 | /** Encode a short Midi message into a 32-bit word. If data1 | ||
| 757 | and/or data2 are not present, use zero. | ||
| 758 | */ | ||
| 759 | #define Pm_Message(status, data1, data2) \ | ||
| 760 | ((((data2) << 16) & 0xFF0000) | \ | ||
| 761 | (((data1) << 8) & 0xFF00) | \ | ||
| 762 | ((status) & 0xFF)) | ||
| 763 | /** Extract the status field from a 32-bit midi message. */ | ||
| 764 | #define Pm_MessageStatus(msg) ((msg) & 0xFF) | ||
| 765 | /** Extract the 1st data field (e.g., pitch) from a 32-bit midi message. */ | ||
| 766 | #define Pm_MessageData1(msg) (((msg) >> 8) & 0xFF) | ||
| 767 | /** Extract the 2nd data field (e.g., velocity) from a 32-bit midi message. */ | ||
| 768 | #define Pm_MessageData2(msg) (((msg) >> 16) & 0xFF) | ||
| 769 | |||
| 770 | typedef uint32_t PmMessage; /**< @brief see #PmEvent */ | ||
| 771 | /** | ||
| 772 | All MIDI data comes in the form of PmEvent structures. A sysex | ||
| 773 | message is encoded as a sequence of PmEvent structures, with each | ||
| 774 | structure carrying 4 bytes of the message, i.e. only the first | ||
| 775 | PmEvent carries the status byte. | ||
| 776 | |||
| 777 | All other MIDI messages take 1 to 3 bytes and are encoded in a whole | ||
| 778 | PmMessage with status in the low-order byte and remaining bytes | ||
| 779 | unused, i.e., a 3-byte note-on message will occupy 3 low-order bytes | ||
| 780 | of PmMessage, leaving the high-order byte unused. | ||
| 781 | |||
| 782 | Note that MIDI allows nested messages: the so-called "real-time" MIDI | ||
| 783 | messages can be inserted into the MIDI byte stream at any location, | ||
| 784 | including within a sysex message. MIDI real-time messages are one-byte | ||
| 785 | messages used mainly for timing (see the MIDI spec). PortMidi retains | ||
| 786 | the order of non-real-time MIDI messages on both input and output, but | ||
| 787 | it does not specify exactly how real-time messages are processed. This | ||
| 788 | is particulary problematic for MIDI input, because the input parser | ||
| 789 | must either prepare to buffer an unlimited number of sysex message | ||
| 790 | bytes or to buffer an unlimited number of real-time messages that | ||
| 791 | arrive embedded in a long sysex message. To simplify things, the input | ||
| 792 | parser is allowed to pass real-time MIDI messages embedded within a | ||
| 793 | sysex message, and it is up to the client to detect, process, and | ||
| 794 | remove these messages as they arrive. | ||
| 795 | |||
| 796 | When receiving sysex messages, the sysex message is terminated | ||
| 797 | by either an EOX status byte (anywhere in the 4 byte messages) or | ||
| 798 | by a non-real-time status byte in the low order byte of the message. | ||
| 799 | If you get a non-real-time status byte but there was no EOX byte, it | ||
| 800 | means the sysex message was somehow truncated. This is not | ||
| 801 | considered an error; e.g., a missing EOX can result from the user | ||
| 802 | disconnecting a MIDI cable during sysex transmission. | ||
| 803 | |||
| 804 | A real-time message can occur within a sysex message. A real-time | ||
| 805 | message will always occupy a full PmEvent with the status byte in | ||
| 806 | the low-order byte of the PmEvent message field. (This implies that | ||
| 807 | the byte-order of sysex bytes and real-time message bytes may not | ||
| 808 | be preserved -- for example, if a real-time message arrives after | ||
| 809 | 3 bytes of a sysex message, the real-time message will be delivered | ||
| 810 | first. The first word of the sysex message will be delivered only | ||
| 811 | after the 4th byte arrives, filling the 4-byte PmEvent message field. | ||
| 812 | |||
| 813 | The timestamp field is observed when the output port is opened with | ||
| 814 | a non-zero latency. A timestamp of zero means "use the current time", | ||
| 815 | which in turn means to deliver the message with a delay of | ||
| 816 | latency (the latency parameter used when opening the output port.) | ||
| 817 | Do not expect PortMidi to sort data according to timestamps -- | ||
| 818 | messages should be sent in the correct order, and timestamps MUST | ||
| 819 | be non-decreasing. See also "Example" for Pm_OpenOutput() above. | ||
| 820 | |||
| 821 | A sysex message will generally fill many #PmEvent structures. On | ||
| 822 | output to a #PortMidiStream with non-zero latency, the first timestamp | ||
| 823 | on sysex message data will determine the time to begin sending the | ||
| 824 | message. PortMidi implementations may ignore timestamps for the | ||
| 825 | remainder of the sysex message. | ||
| 826 | |||
| 827 | On input, the timestamp ideally denotes the arrival time of the | ||
| 828 | status byte of the message. The first timestamp on sysex message | ||
| 829 | data will be valid. Subsequent timestamps may denote | ||
| 830 | when message bytes were actually received, or they may be simply | ||
| 831 | copies of the first timestamp. | ||
| 832 | |||
| 833 | Timestamps for nested messages: If a real-time message arrives in | ||
| 834 | the middle of some other message, it is enqueued immediately with | ||
| 835 | the timestamp corresponding to its arrival time. The interrupted | ||
| 836 | non-real-time message or 4-byte packet of sysex data will be enqueued | ||
| 837 | later. The timestamp of interrupted data will be equal to that of | ||
| 838 | the interrupting real-time message to insure that timestamps are | ||
| 839 | non-decreasing. | ||
| 840 | */ | ||
| 841 | typedef struct { | ||
| 842 | PmMessage message; | ||
| 843 | PmTimestamp timestamp; | ||
| 844 | } PmEvent; | ||
| 845 | |||
| 846 | /** @} */ | ||
| 847 | |||
| 848 | /** \defgroup grp_io Reading and Writing Midi Messages | ||
| 849 | @{ | ||
| 850 | */ | ||
| 851 | /** Retrieve midi data into a buffer. | ||
| 852 | |||
| 853 | @param stream the open input stream. | ||
| 854 | |||
| 855 | @return the number of events read, or, if the result is negative, | ||
| 856 | a #PmError value will be returned. | ||
| 857 | |||
| 858 | The Buffer Overflow Problem | ||
| 859 | |||
| 860 | The problem: if an input overflow occurs, data will be lost, | ||
| 861 | ultimately because there is no flow control all the way back to | ||
| 862 | the data source. When data is lost, the receiver should be | ||
| 863 | notified and some sort of graceful recovery should take place, | ||
| 864 | e.g. you shouldn't resume receiving in the middle of a long sysex | ||
| 865 | message. | ||
| 866 | |||
| 867 | With a lock-free fifo, which is pretty much what we're stuck with | ||
| 868 | to enable portability to the Mac, it's tricky for the producer and | ||
| 869 | consumer to synchronously reset the buffer and resume normal | ||
| 870 | operation. | ||
| 871 | |||
| 872 | Solution: the entire buffer managed by PortMidi will be flushed | ||
| 873 | when an overflow occurs. The consumer (Pm_Read()) gets an error | ||
| 874 | message (#pmBufferOverflow) and ordinary processing resumes as | ||
| 875 | soon as a new message arrives. The remainder of a partial sysex | ||
| 876 | message is not considered to be a "new message" and will be | ||
| 877 | flushed as well. | ||
| 878 | */ | ||
| 879 | PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length); | ||
| 880 | |||
| 881 | /** Test whether input is available. | ||
| 882 | |||
| 883 | @param stream an open input stream. | ||
| 884 | |||
| 885 | @return TRUE, FALSE, or an error value. | ||
| 886 | |||
| 887 | If there was an asynchronous error, pmHostError is returned and you must | ||
| 888 | call again to determine if input is (also) available. | ||
| 889 | |||
| 890 | You should probably *not* use this function. Call Pm_Read() | ||
| 891 | instead. If it returns 0, then there is no data available. It is | ||
| 892 | possible for Pm_Poll() to return TRUE before the complete message | ||
| 893 | is available, so Pm_Read() could return 0 even after Pm_Poll() | ||
| 894 | returns TRUE. Only call Pm_Poll() if you want to know that data is | ||
| 895 | probably available even though you are not ready to receive data. | ||
| 896 | */ | ||
| 897 | PMEXPORT PmError Pm_Poll(PortMidiStream *stream); | ||
| 898 | |||
| 899 | /** Write MIDI data from a buffer. | ||
| 900 | |||
| 901 | @param stream an open output stream. | ||
| 902 | |||
| 903 | @param buffer (address of) an array of MIDI event data. | ||
| 904 | |||
| 905 | @param length the length of the \p buffer. | ||
| 906 | |||
| 907 | @return TRUE, FALSE, or an error value. | ||
| 908 | |||
| 909 | \b buffer may contain: | ||
| 910 | - short messages | ||
| 911 | - sysex messages that are converted into a sequence of PmEvent | ||
| 912 | structures, e.g. sending data from a file or forwarding them | ||
| 913 | from midi input, with 4 SysEx bytes per PmEvent message, | ||
| 914 | low-order byte first, until the last message, which may | ||
| 915 | contain from 1 to 4 bytes ending in MIDI EOX (0xF7). | ||
| 916 | - PortMidi allows 1-byte real-time messages to be embedded | ||
| 917 | within SysEx messages, but only on 4-byte boundaries so | ||
| 918 | that SysEx data always uses a full 4 bytes (except possibly | ||
| 919 | at the end). Each real-time message always occupies a full | ||
| 920 | PmEvent (3 of the 4 bytes in the PmEvent's message are | ||
| 921 | ignored) even when embedded in a SysEx message. | ||
| 922 | |||
| 923 | Use Pm_WriteSysEx() to write a sysex message stored as a contiguous | ||
| 924 | array of bytes. | ||
| 925 | |||
| 926 | Sysex data may contain embedded real-time messages. | ||
| 927 | |||
| 928 | \p buffer is managed by the caller. The buffer may be destroyed | ||
| 929 | as soon as this call returns. | ||
| 930 | */ | ||
| 931 | PMEXPORT PmError Pm_Write(PortMidiStream *stream, PmEvent *buffer, | ||
| 932 | int32_t length); | ||
| 933 | |||
| 934 | /** Write a timestamped non-system-exclusive midi message. | ||
| 935 | |||
| 936 | @param stream an open output stream. | ||
| 937 | |||
| 938 | @param when timestamp for the event. | ||
| 939 | |||
| 940 | @param msg the data for the event. | ||
| 941 | |||
| 942 | @result #pmNoError or an error code. | ||
| 943 | |||
| 944 | Messages are delivered in order, and timestamps must be | ||
| 945 | non-decreasing. (But timestamps are ignored if the stream was | ||
| 946 | opened with latency = 0, and otherwise, non-decreasing timestamps | ||
| 947 | are "corrected" to the lowest valid value.) | ||
| 948 | */ | ||
| 949 | PMEXPORT PmError Pm_WriteShort(PortMidiStream *stream, PmTimestamp when, | ||
| 950 | PmMessage msg); | ||
| 951 | |||
| 952 | /** Write a timestamped system-exclusive midi message. | ||
| 953 | |||
| 954 | @param stream an open output stream. | ||
| 955 | |||
| 956 | @param when timestamp for the event. | ||
| 957 | |||
| 958 | @param msg the sysex message, terminated with an EOX status byte. | ||
| 959 | |||
| 960 | @result #pmNoError or an error code. | ||
| 961 | |||
| 962 | \p msg is managed by the caller and may be destroyed when this | ||
| 963 | call returns. | ||
| 964 | */ | ||
| 965 | PMEXPORT PmError Pm_WriteSysEx(PortMidiStream *stream, PmTimestamp when, | ||
| 966 | unsigned char *msg); | ||
| 967 | |||
| 968 | /** @} */ | ||
| 969 | |||
| 970 | #ifdef __cplusplus | ||
| 971 | } | ||
| 972 | #endif /* __cplusplus */ | ||
| 973 | |||
| 974 | #endif /* PORTMIDI_PORTMIDI_H */ | ||
