commit
fed7fad012
46 changed files with 10386 additions and 0 deletions
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
# Copyright (C) 2019 Alexandros Theodotou <alex at zrythm dot org> |
||||
# |
||||
# This file is part of Zrythm |
||||
# |
||||
# Zrythm is free software: you can redistribute it and/or modify |
||||
# it under the terms of the GNU Affero General Public License as published by |
||||
# the Free Software Foundation, either version 3 of the License, or |
||||
# (at your option) any later version. |
||||
# |
||||
# Zrythm is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU Affero General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU Affero General Public License |
||||
# along with Zrythm. If not, see <https://www.gnu.org/licenses/>. |
||||
|
||||
# Build files |
||||
build |
||||
builddir |
||||
_build |
||||
|
||||
# -- C++ |
||||
# Prerequisites |
||||
*.d |
||||
|
||||
# Compiled Object files |
||||
*.slo |
||||
*.lo |
||||
*.o |
||||
*.obj |
||||
**/*/*.so* |
||||
|
||||
# Precompiled Headers |
||||
*.gch |
||||
*.pch |
||||
|
||||
# Compiled Dynamic libraries |
||||
*.so |
||||
*.dylib |
||||
build/*.dll |
||||
|
||||
# Fortran module files |
||||
*.mod |
||||
*.smod |
||||
|
||||
# Compiled Static libraries |
||||
*.lai |
||||
*.la |
||||
*.a |
||||
*.lib |
||||
|
||||
# Executables |
||||
*.exe |
||||
*.out |
||||
*.app |
||||
|
||||
# -- Vim |
||||
# Swap |
||||
[._]*.s[a-v][a-z] |
||||
[._]*.sw[a-p] |
||||
[._]s[a-rt-v][a-z] |
||||
[._]ss[a-gi-z] |
||||
[._]sw[a-p] |
||||
.vimrc |
||||
|
||||
# Session |
||||
Session.vim |
||||
|
||||
# Temporary |
||||
.netrwhist |
||||
*~ |
||||
*.ui# |
||||
**/.deps |
||||
|
||||
# Auto-generated tag files |
||||
tags |
||||
# Persistent undo |
||||
[._]*.un~ |
||||
|
||||
# Backup files |
||||
*.bak |
||||
|
||||
# Valgrind |
||||
vgcore.* |
@ -0,0 +1,273 @@
@@ -0,0 +1,273 @@
|
||||
# 2018 (c) Juan G. Victores, Bartek ลukawski, Stephen Sinclair |
||||
# CopyPolicy: RtMidi license. |
||||
|
||||
# Set minimum CMake required version for this project. |
||||
cmake_minimum_required(VERSION 3.10 FATAL_ERROR) |
||||
|
||||
# Define a C++ project. |
||||
project(RtMidi LANGUAGES CXX) |
||||
|
||||
# Check for Jack (any OS) |
||||
find_library(JACK_LIB jack) |
||||
find_package(PkgConfig) |
||||
pkg_check_modules(jack jack) |
||||
if(JACK_LIB OR jack_FOUND) |
||||
set(HAVE_JACK TRUE) |
||||
endif() |
||||
|
||||
# Necessary for Windows |
||||
if(WIN32) |
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) |
||||
endif() |
||||
|
||||
# Standard CMake options |
||||
option(BUILD_SHARED_LIBS "Build as shared library" ON) |
||||
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) |
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;RelWithDebInfo;MinSizeRel") |
||||
endif() |
||||
if(WINDOWS) |
||||
set(CMAKE_DEBUG_POSTFIX d CACHE STRING "Postfix for debug version of library") |
||||
endif() |
||||
|
||||
# Build Options |
||||
set(RTMIDI_TARGETNAME_UNINSTALL "uninstall" CACHE STRING "Name of 'uninstall' build target") |
||||
|
||||
# API Options |
||||
option(RTMIDI_API_JACK "Compile with JACK support." ${HAVE_JACK}) |
||||
if(UNIX AND NOT APPLE) |
||||
option(RTMIDI_API_ALSA "Compile with ALSA support." ON) |
||||
endif() |
||||
option(RTMIDI_API_WINMM "Compile with WINMM support." ${WIN32}) |
||||
option(RTMIDI_API_CORE "Compile with CoreMIDI support." ${APPLE}) |
||||
|
||||
# Add -Wall if possible |
||||
if (CMAKE_COMPILER_IS_GNUCXX) |
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") |
||||
endif (CMAKE_COMPILER_IS_GNUCXX) |
||||
|
||||
# Add debug flags |
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug") |
||||
add_definitions(-D__RTMIDI_DEBUG__) |
||||
if (CMAKE_COMPILER_IS_GNUCXX) |
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") |
||||
endif (CMAKE_COMPILER_IS_GNUCXX) |
||||
endif () |
||||
|
||||
# Read libtool version info from configure.ac |
||||
set(R "m4_define\\(\\[lt_([a-z]+)\\], ([0-9]+)\\)") |
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGAC |
||||
REGEX ${R}) |
||||
foreach(_S ${CONFIGAC}) |
||||
string(REGEX REPLACE ${R} "\\1" k ${_S}) |
||||
string(REGEX REPLACE ${R} "\\2" v ${_S}) |
||||
set(SO_${k} ${v}) |
||||
endforeach() |
||||
math(EXPR SO_current_minus_age "${SO_current} - ${SO_age}") |
||||
set(SO_VER "${SO_current_minus_age}") |
||||
set(FULL_VER "${SO_current_minus_age}.${SO_revision}.${SO_age}") |
||||
|
||||
# Read package version info from configure.ac |
||||
set(R "AC_INIT\\(RtMidi, ([0-9\\.]+),.*\\)") |
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGAC |
||||
REGEX ${R}) |
||||
string(REGEX REPLACE ${R} "\\1" PACKAGE_VERSION ${CONFIGAC}) |
||||
|
||||
# Init variables |
||||
set(rtmidi_SOURCES RtMidi.cpp RtMidi.h rtmidi_c.cpp rtmidi_c.h) |
||||
set(LINKLIBS) |
||||
set(INCDIRS) |
||||
set(PKGCONFIG_REQUIRES) |
||||
set(API_DEFS) |
||||
set(API_LIST) |
||||
|
||||
# Tweak API-specific configuration. |
||||
|
||||
# Jack |
||||
if(RTMIDI_API_JACK) |
||||
if (NOT HAVE_JACK) |
||||
message(FATAL_ERROR "Jack API requested but no Jack dev libraries found") |
||||
endif() |
||||
set(NEED_PTHREAD ON) |
||||
list(APPEND PKGCONFIG_REQUIRES "jack") |
||||
list(APPEND API_DEFS "-D__UNIX_JACK__") |
||||
list(APPEND API_LIST "jack") |
||||
if(jack_FOUND) |
||||
list(APPEND LINKLIBS ${jack_LIBRARIES}) |
||||
list(APPEND INCDIRS ${jack_INCLUDEDIR}) |
||||
else() |
||||
list(APPEND LINKLIBS ${JACK_LIB}) |
||||
endif() |
||||
|
||||
# Check for jack_port_rename |
||||
include(CheckSymbolExists) |
||||
set(tmp_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) |
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES jack) |
||||
check_symbol_exists(jack_port_rename ${jack_INCLUDEDIR}/jack/jack.h JACK_HAS_PORT_RENAME) |
||||
set(CMAKE_REQUIRED_LIBRARIES ${tmp_CMAKE_REQUIRED_LIBRARIES}) |
||||
if(JACK_HAS_PORT_RENAME) |
||||
list(APPEND API_DEFS "JACK_HAS_PORT_RENAME") |
||||
endif() |
||||
endif() |
||||
|
||||
# ALSA |
||||
if(RTMIDI_API_ALSA) |
||||
set(NEED_PTHREAD ON) |
||||
find_package(ALSA) |
||||
if (NOT ALSA_FOUND) |
||||
message(FATAL_ERROR "ALSA API requested but no ALSA dev libraries found") |
||||
endif() |
||||
list(APPEND INCDIRS ${ALSA_INCLUDE_DIR}) |
||||
list(APPEND LINKLIBS ${ALSA_LIBRARY}) |
||||
list(APPEND PKGCONFIG_REQUIRES "alsa") |
||||
list(APPEND API_DEFS "-D__LINUX_ALSA__") |
||||
list(APPEND API_LIST "alsa") |
||||
endif() |
||||
|
||||
# WinMM |
||||
if(RTMIDI_API_WINMM) |
||||
list(APPEND API_DEFS "-D__WINDOWS_MM__") |
||||
list(APPEND API_LIST "winmm") |
||||
list(APPEND LINKLIBS winmm) |
||||
endif() |
||||
|
||||
# CoreMIDI |
||||
if(RTMIDI_API_CORE) |
||||
list(APPEND API_DEFS "-D__MACOSX_CORE__") |
||||
list(APPEND API_LIST "coremidi") |
||||
list(APPEND LINKLIBS "-framework CoreServices") |
||||
list(APPEND LINKLIBS "-framework CoreAudio") |
||||
list(APPEND LINKLIBS "-framework CoreMIDI") |
||||
list(APPEND LINKLIBS "-framework CoreFoundation") |
||||
list(APPEND LINKFLAGS "-Wl,-F/Library/Frameworks") |
||||
endif() |
||||
|
||||
# pthread |
||||
if (NEED_PTHREAD) |
||||
find_package(Threads REQUIRED |
||||
CMAKE_THREAD_PREFER_PTHREAD |
||||
THREADS_PREFER_PTHREAD_FLAG) |
||||
list(APPEND LINKLIBS Threads::Threads) |
||||
endif() |
||||
|
||||
# Create library targets. |
||||
cmake_policy(SET CMP0042 OLD) |
||||
set(LIB_TARGETS) |
||||
|
||||
# Use RTMIDI_BUILD_SHARED_LIBS / RTMIDI_BUILD_STATIC_LIBS if they |
||||
# are defined, otherwise default to standard BUILD_SHARED_LIBS. |
||||
if (DEFINED RTMIDI_BUILD_SHARED_LIBS AND NOT RTMIDI_BUILD_SHARED_LIBS STREQUAL "") |
||||
if (RTMIDI_BUILD_SHARED_LIBS) |
||||
add_library(rtmidi SHARED ${rtmidi_SOURCES}) |
||||
else() |
||||
add_library(rtmidi STATIC ${rtmidi_SOURCES}) |
||||
endif() |
||||
elseif (DEFINED RTMIDI_BUILD_STATIC_LIBS AND NOT RTMIDI_BUILD_STATIC_LIBS STREQUAL "") |
||||
if (RTMIDI_BUILD_STATIC_LIBS) |
||||
add_library(rtmidi STATIC ${rtmidi_SOURCES}) |
||||
else() |
||||
add_library(rtmidi SHARED ${rtmidi_SOURCES}) |
||||
endif() |
||||
else() |
||||
add_library(rtmidi ${rtmidi_SOURCES}) |
||||
endif() |
||||
list(APPEND LIB_TARGETS rtmidi) |
||||
|
||||
# Add headers destination for install rule. |
||||
set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h |
||||
SOVERSION ${SO_VER} |
||||
VERSION ${FULL_VER}) |
||||
|
||||
# Set include paths, populate target interface. |
||||
target_include_directories(rtmidi PRIVATE |
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> |
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> |
||||
${INCDIRS}) |
||||
|
||||
# Set compile-time definitions |
||||
target_compile_definitions(rtmidi PRIVATE ${API_DEFS}) |
||||
target_compile_definitions(rtmidi PRIVATE RTMIDI_EXPORT) |
||||
target_link_libraries(rtmidi ${LINKLIBS}) |
||||
|
||||
# Set standard installation directories. |
||||
include(GNUInstallDirs) |
||||
|
||||
# Add tests if requested. |
||||
include(CTest) |
||||
if (NOT DEFINED RTMIDI_BUILD_TESTING OR RTMIDI_BUILD_TESTING STREQUAL "") |
||||
set(RTMIDI_BUILD_TESTING ${BUILD_TESTING}) |
||||
endif() |
||||
if (RTMIDI_BUILD_TESTING) |
||||
add_executable(cmidiin tests/cmidiin.cpp) |
||||
add_executable(midiclock tests/midiclock.cpp) |
||||
add_executable(midiout tests/midiout.cpp) |
||||
add_executable(midiprobe tests/midiprobe.cpp) |
||||
add_executable(qmidiin tests/qmidiin.cpp) |
||||
add_executable(sysextest tests/sysextest.cpp) |
||||
add_executable(apinames tests/apinames.cpp) |
||||
list(GET LIB_TARGETS 0 LIBRTMIDI) |
||||
set_target_properties(cmidiin midiclock midiout midiprobe qmidiin sysextest apinames |
||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY tests |
||||
INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} |
||||
LINK_LIBRARIES ${LIBRTMIDI}) |
||||
add_test(NAME apinames COMMAND apinames) |
||||
endif() |
||||
|
||||
# Set standard installation directories. |
||||
include(GNUInstallDirs) |
||||
|
||||
# Message |
||||
string(REPLACE ";" " " apilist "${API_LIST}") |
||||
message(STATUS "Compiling with support for: ${apilist}") |
||||
|
||||
# PkgConfig file |
||||
string(REPLACE ";" " " req "${PKGCONFIG_REQUIRES}") |
||||
string(REPLACE ";" " " api "${API_DEFS}") |
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/rtmidi.pc.in" "rtmidi.pc" @ONLY) |
||||
|
||||
# Add install rule. |
||||
install(TARGETS ${LIB_TARGETS} |
||||
EXPORT RtMidiTargets |
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} |
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} |
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} |
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) |
||||
|
||||
# Store the package in the user registry. |
||||
export(PACKAGE RtMidi) |
||||
|
||||
# Set installation path for CMake files. |
||||
set(RTMIDI_CMAKE_DESTINATION share/rtmidi) |
||||
|
||||
# Create CMake configuration export file. |
||||
if(NEED_PTHREAD) |
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/RtMidiConfig.cmake "find_package(Threads REQUIRED)\n") |
||||
endif() |
||||
|
||||
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/RtMidiConfig.cmake "include(\${CMAKE_CURRENT_LIST_DIR}/RtMidiTargets.cmake)") |
||||
|
||||
# Install CMake configuration export file. |
||||
install(FILES ${CMAKE_BINARY_DIR}/RtMidiConfig.cmake |
||||
DESTINATION ${RTMIDI_CMAKE_DESTINATION}) |
||||
|
||||
# Export library target (build-tree). |
||||
export(EXPORT RtMidiTargets |
||||
NAMESPACE RtMidi::) |
||||
|
||||
# Export library target (install-tree). |
||||
install(EXPORT RtMidiTargets |
||||
DESTINATION ${RTMIDI_CMAKE_DESTINATION} |
||||
NAMESPACE RtMidi::) |
||||
|
||||
# Configure uninstall target. |
||||
configure_file( |
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/RtMidiConfigUninstall.cmake.in" |
||||
"${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake" @ONLY) |
||||
|
||||
# Create uninstall target. |
||||
add_custom_target(${RTMIDI_TARGETNAME_UNINSTALL} |
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake) |
||||
|
||||
install( |
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/rtmidi.pc |
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
SUBDIRS = . tests |
||||
if MAKE_DOC |
||||
SUBDIRS += doc |
||||
endif |
||||
|
||||
lib_LTLIBRARIES = %D%/librtmidi.la |
||||
%C%_librtmidi_la_CXXFLAGS = -DRTMIDI_EXPORT |
||||
%C%_librtmidi_la_LDFLAGS = -no-undefined -export-dynamic -version-info @SO_VERSION@ |
||||
%C%_librtmidi_la_SOURCES = \
|
||||
%D%/RtMidi.cpp \
|
||||
%D%/rtmidi_c.cpp |
||||
|
||||
rtmidi_incdir = $(includedir)/rtmidi |
||||
rtmidi_inc_HEADERS = \
|
||||
%D%/RtMidi.h \
|
||||
%D%/rtmidi_c.h |
||||
|
||||
pkgconfigdatadir = $(libdir)/pkgconfig |
||||
pkgconfigdata_DATA = rtmidi.pc |
||||
|
||||
EXTRA_DIST = autogen.sh README.md msw rtmidi-config.in contrib cmake CMakeLists.txt |
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
# RtMidi |
||||
|
||||
[](https://travis-ci.org/thestk/rtmidi) |
||||
|
||||
A set of C++ classes that provide a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMIDI & JACK) and Windows (Multimedia). |
||||
|
||||
By Gary P. Scavone, 2003-2019. |
||||
|
||||
This distribution of RtMidi contains the following: |
||||
|
||||
- `doc`: RtMidi documentation (also online at http://www.music.mcgill.ca/~gary/rtmidi/) |
||||
- `tests`: example RtMidi programs |
||||
|
||||
On Unix systems, type `./configure` in the top level directory, then `make` in the `tests/` directory to compile the test programs. In Windows, open the Visual C++ workspace file located in the `tests/` directory. |
||||
|
||||
If you checked out the code from git, please run `./autogen.sh` before `./configure`. |
||||
|
||||
## Overview |
||||
|
||||
RtMidi is a set of C++ classes (`RtMidiIn`, `RtMidiOut`, and API specific classes) that provide a common API (Application Programming Interface) for realtime MIDI input/output across Linux (ALSA, JACK), Macintosh OS X (CoreMIDI, JACK), and Windows (Multimedia Library) operating systems. RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software. It was designed with the following goals: |
||||
|
||||
- object oriented C++ design |
||||
- simple, common API across all supported platforms |
||||
- only one header and one source file for easy inclusion in programming projects |
||||
- MIDI device enumeration |
||||
|
||||
MIDI input and output functionality are separated into two classes, `RtMidiIn` and `RtMidiOut`. Each class instance supports only a single MIDI connection. RtMidi does not provide timing functionality (i.e., output messages are sent immediately). Input messages are timestamped with delta times in seconds (via a `double` floating point type). MIDI data is passed to the user as raw bytes using an `std::vector<unsigned char>`. |
||||
|
||||
## Windows |
||||
|
||||
In some cases, for example to use RtMidi with GS Synth, it may be necessary for your program to call `CoInitializeEx` and `CoUninitialize` on entry to and exit from the thread that uses RtMidi. |
||||
|
||||
## Further reading |
||||
|
||||
For complete documentation on RtMidi, see the `doc` directory of the distribution or surf to http://www.music.mcgill.ca/~gary/rtmidi/. |
||||
|
||||
## Legal and ethical |
||||
|
||||
The RtMidi license is similar to the MIT License, with the added *feature* that modifications be sent to the developer. |
||||
|
||||
RtMidi: realtime MIDI i/o C++ classes |
||||
Copyright (c) 2003-2019 Gary P. Scavone |
||||
|
||||
Permission is hereby granted, free of charge, to any person |
||||
obtaining a copy of this software and associated documentation files |
||||
(the "Software"), to deal in the Software without restriction, |
||||
including without limitation the rights to use, copy, modify, merge, |
||||
publish, distribute, sublicense, and/or sell copies of the Software, |
||||
and to permit persons to whom the Software is furnished to do so, |
||||
subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be |
||||
included in all copies or substantial portions of the Software. |
||||
|
||||
Any person wishing to distribute modifications to the Software is |
||||
asked to send the modifications to the original developer so that |
||||
they can be incorporated into the canonical version. This is, |
||||
however, not a binding provision of this license. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR |
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@ -0,0 +1,633 @@
@@ -0,0 +1,633 @@
|
||||
/**********************************************************************/ |
||||
/*! \class RtMidi
|
||||
\brief An abstract base class for realtime MIDI input/output. |
||||
|
||||
This class implements some common functionality for the realtime |
||||
MIDI input/output subclasses RtMidiIn and RtMidiOut. |
||||
|
||||
RtMidi GitHub site: https://github.com/thestk/rtmidi
|
||||
RtMidi WWW site: http://www.music.mcgill.ca/~gary/rtmidi/
|
||||
|
||||
RtMidi: realtime MIDI i/o C++ classes |
||||
Copyright (c) 2003-2019 Gary P. Scavone |
||||
|
||||
Permission is hereby granted, free of charge, to any person |
||||
obtaining a copy of this software and associated documentation files |
||||
(the "Software"), to deal in the Software without restriction, |
||||
including without limitation the rights to use, copy, modify, merge, |
||||
publish, distribute, sublicense, and/or sell copies of the Software, |
||||
and to permit persons to whom the Software is furnished to do so, |
||||
subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be |
||||
included in all copies or substantial portions of the Software. |
||||
|
||||
Any person wishing to distribute modifications to the Software is |
||||
asked to send the modifications to the original developer so that |
||||
they can be incorporated into the canonical version. This is, |
||||
however, not a binding provision of this license. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR |
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
/**********************************************************************/ |
||||
|
||||
/*!
|
||||
\file RtMidi.h |
||||
*/ |
||||
|
||||
#ifndef RTMIDI_H |
||||
#define RTMIDI_H |
||||
|
||||
#if defined _WIN32 || defined __CYGWIN__ |
||||
#if defined(RTMIDI_EXPORT) |
||||
#define RTMIDI_DLL_PUBLIC __declspec(dllexport) |
||||
#else |
||||
#define RTMIDI_DLL_PUBLIC |
||||
#endif |
||||
#else |
||||
#if __GNUC__ >= 4 |
||||
#define RTMIDI_DLL_PUBLIC __attribute__( (visibility( "default" )) ) |
||||
#else |
||||
#define RTMIDI_DLL_PUBLIC |
||||
#endif |
||||
#endif |
||||
|
||||
#define RTMIDI_VERSION "4.0.0" |
||||
|
||||
#include <exception> |
||||
#include <iostream> |
||||
#include <string> |
||||
#include <vector> |
||||
|
||||
/************************************************************************/ |
||||
/*! \class RtMidiError
|
||||
\brief Exception handling class for RtMidi. |
||||
|
||||
The RtMidiError class is quite simple but it does allow errors to be |
||||
"caught" by RtMidiError::Type. See the RtMidi documentation to know |
||||
which methods can throw an RtMidiError. |
||||
*/ |
||||
/************************************************************************/ |
||||
|
||||
class RTMIDI_DLL_PUBLIC RtMidiError : public std::exception |
||||
{ |
||||
public: |
||||
//! Defined RtMidiError types.
|
||||
enum Type { |
||||
WARNING, /*!< A non-critical error. */ |
||||
DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ |
||||
UNSPECIFIED, /*!< The default, unspecified error type. */ |
||||
NO_DEVICES_FOUND, /*!< No devices found on system. */ |
||||
INVALID_DEVICE, /*!< An invalid device ID was specified. */ |
||||
MEMORY_ERROR, /*!< An error occured during memory allocation. */ |
||||
INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ |
||||
INVALID_USE, /*!< The function was called incorrectly. */ |
||||
DRIVER_ERROR, /*!< A system driver error occured. */ |
||||
SYSTEM_ERROR, /*!< A system error occured. */ |
||||
THREAD_ERROR /*!< A thread error occured. */ |
||||
}; |
||||
|
||||
//! The constructor.
|
||||
RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw() |
||||
: message_(message), type_(type) {} |
||||
|
||||
//! The destructor.
|
||||
virtual ~RtMidiError( void ) throw() {} |
||||
|
||||
//! Prints thrown error message to stderr.
|
||||
virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } |
||||
|
||||
//! Returns the thrown error message type.
|
||||
virtual const Type& getType( void ) const throw() { return type_; } |
||||
|
||||
//! Returns the thrown error message string.
|
||||
virtual const std::string& getMessage( void ) const throw() { return message_; } |
||||
|
||||
//! Returns the thrown error message as a c-style string.
|
||||
virtual const char* what( void ) const throw() { return message_.c_str(); } |
||||
|
||||
protected: |
||||
std::string message_; |
||||
Type type_; |
||||
}; |
||||
|
||||
//! RtMidi error callback function prototype.
|
||||
/*!
|
||||
\param type Type of error. |
||||
\param errorText Error description. |
||||
|
||||
Note that class behaviour is undefined after a critical error (not |
||||
a warning) is reported. |
||||
*/ |
||||
typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText, void *userData ); |
||||
|
||||
class MidiApi; |
||||
|
||||
class RTMIDI_DLL_PUBLIC RtMidi |
||||
{ |
||||
public: |
||||
//! MIDI API specifier arguments.
|
||||
enum Api { |
||||
UNSPECIFIED, /*!< Search for a working compiled API. */ |
||||
MACOSX_CORE, /*!< Macintosh OS-X CoreMIDI API. */ |
||||
LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ |
||||
UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ |
||||
WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ |
||||
RTMIDI_DUMMY, /*!< A compilable but non-functional API. */ |
||||
NUM_APIS /*!< Number of values in this enum. */ |
||||
}; |
||||
|
||||
//! A static function to determine the current RtMidi version.
|
||||
static std::string getVersion( void ) throw(); |
||||
|
||||
//! A static function to determine the available compiled MIDI APIs.
|
||||
/*!
|
||||
The values returned in the std::vector can be compared against |
||||
the enumerated list values. Note that there can be more than one |
||||
API compiled for certain operating systems. |
||||
*/ |
||||
static void getCompiledApi( std::vector<RtMidi::Api> &apis ) throw(); |
||||
|
||||
//! Return the name of a specified compiled MIDI API.
|
||||
/*!
|
||||
This obtains a short lower-case name used for identification purposes. |
||||
This value is guaranteed to remain identical across library versions. |
||||
If the API is unknown, this function will return the empty string. |
||||
*/ |
||||
static std::string getApiName( RtMidi::Api api ); |
||||
|
||||
//! Return the display name of a specified compiled MIDI API.
|
||||
/*!
|
||||
This obtains a long name used for display purposes. |
||||
If the API is unknown, this function will return the empty string. |
||||
*/ |
||||
static std::string getApiDisplayName( RtMidi::Api api ); |
||||
|
||||
//! Return the compiled MIDI API having the given name.
|
||||
/*!
|
||||
A case insensitive comparison will check the specified name |
||||
against the list of compiled APIs, and return the one which |
||||
matches. On failure, the function returns UNSPECIFIED. |
||||
*/ |
||||
static RtMidi::Api getCompiledApiByName( const std::string &name ); |
||||
|
||||
//! Pure virtual openPort() function.
|
||||
virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0; |
||||
|
||||
//! Pure virtual openVirtualPort() function.
|
||||
virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi" ) ) = 0; |
||||
|
||||
//! Pure virtual getPortCount() function.
|
||||
virtual unsigned int getPortCount() = 0; |
||||
|
||||
//! Pure virtual getPortName() function.
|
||||
virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; |
||||
|
||||
//! Pure virtual closePort() function.
|
||||
virtual void closePort( void ) = 0; |
||||
|
||||
void setClientName( const std::string &clientName ); |
||||
void setPortName( const std::string &portName ); |
||||
|
||||
//! Returns true if a port is open and false if not.
|
||||
/*!
|
||||
Note that this only applies to connections made with the openPort() |
||||
function, not to virtual ports. |
||||
*/ |
||||
virtual bool isPortOpen( void ) const = 0; |
||||
|
||||
//! Set an error callback function to be invoked when an error has occured.
|
||||
/*!
|
||||
The callback function will be called whenever an error has occured. It is best |
||||
to set the error callback function before opening a port. |
||||
*/ |
||||
virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ) = 0; |
||||
|
||||
protected: |
||||
RtMidi(); |
||||
virtual ~RtMidi(); |
||||
MidiApi *rtapi_; |
||||
}; |
||||
|
||||
/**********************************************************************/ |
||||
/*! \class RtMidiIn
|
||||
\brief A realtime MIDI input class. |
||||
|
||||
This class provides a common, platform-independent API for |
||||
realtime MIDI input. It allows access to a single MIDI input |
||||
port. Incoming MIDI messages are either saved to a queue for |
||||
retrieval using the getMessage() function or immediately passed to |
||||
a user-specified callback function. Create multiple instances of |
||||
this class to connect to more than one MIDI device at the same |
||||
time. With the OS-X, Linux ALSA, and JACK MIDI APIs, it is also |
||||
possible to open a virtual input port to which other MIDI software |
||||
clients can connect. |
||||
|
||||
by Gary P. Scavone, 2003-2017. |
||||
*/ |
||||
/**********************************************************************/ |
||||
|
||||
// **************************************************************** //
|
||||
//
|
||||
// RtMidiIn and RtMidiOut class declarations.
|
||||
//
|
||||
// RtMidiIn / RtMidiOut are "controllers" used to select an available
|
||||
// MIDI input or output interface. They present common APIs for the
|
||||
// user to call but all functionality is implemented by the classes
|
||||
// MidiInApi, MidiOutApi and their subclasses. RtMidiIn and RtMidiOut
|
||||
// each create an instance of a MidiInApi or MidiOutApi subclass based
|
||||
// on the user's API choice. If no choice is made, they attempt to
|
||||
// make a "logical" API selection.
|
||||
//
|
||||
// **************************************************************** //
|
||||
|
||||
class RTMIDI_DLL_PUBLIC RtMidiIn : public RtMidi |
||||
{ |
||||
public: |
||||
|
||||
//! User callback function type definition.
|
||||
typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData ); |
||||
|
||||
//! Default constructor that allows an optional api, client name and queue size.
|
||||
/*!
|
||||
An exception will be thrown if a MIDI system initialization |
||||
error occurs. The queue size defines the maximum number of |
||||
messages that can be held in the MIDI queue (when not using a |
||||
callback function). If the queue size limit is reached, |
||||
incoming messages will be ignored. |
||||
|
||||
If no API argument is specified and multiple API support has been |
||||
compiled, the default order of use is ALSA, JACK (Linux) and CORE, |
||||
JACK (OS-X). |
||||
|
||||
\param api An optional API id can be specified. |
||||
\param clientName An optional client name can be specified. This |
||||
will be used to group the ports that are created |
||||
by the application. |
||||
\param queueSizeLimit An optional size of the MIDI input queue can be specified. |
||||
*/ |
||||
RtMidiIn( RtMidi::Api api=UNSPECIFIED, |
||||
const std::string& clientName = "RtMidi Input Client", |
||||
unsigned int queueSizeLimit = 100 ); |
||||
|
||||
//! If a MIDI connection is still open, it will be closed by the destructor.
|
||||
~RtMidiIn ( void ) throw(); |
||||
|
||||
//! Returns the MIDI API specifier for the current instance of RtMidiIn.
|
||||
RtMidi::Api getCurrentApi( void ) throw(); |
||||
|
||||
//! Open a MIDI input connection given by enumeration number.
|
||||
/*!
|
||||
\param portNumber An optional port number greater than 0 can be specified. |
||||
Otherwise, the default or first port found is opened. |
||||
\param portName An optional name for the application port that is used to connect to portId can be specified. |
||||
*/ |
||||
void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Input" ) ); |
||||
|
||||
//! Create a virtual input port, with optional name, to allow software connections (OS X, JACK and ALSA only).
|
||||
/*!
|
||||
This function creates a virtual MIDI input port to which other |
||||
software applications can connect. This type of functionality |
||||
is currently only supported by the Macintosh OS-X, any JACK, |
||||
and Linux ALSA APIs (the function returns an error for the other APIs). |
||||
|
||||
\param portName An optional name for the application port that is |
||||
used to connect to portId can be specified. |
||||
*/ |
||||
void openVirtualPort( const std::string &portName = std::string( "RtMidi Input" ) ); |
||||
|
||||
//! Set a callback function to be invoked for incoming MIDI messages.
|
||||
/*!
|
||||
The callback function will be called whenever an incoming MIDI |
||||
message is received. While not absolutely necessary, it is best |
||||
to set the callback function before opening a MIDI port to avoid |
||||
leaving some messages in the queue. |
||||
|
||||
\param callback A callback function must be given. |
||||
\param userData Optionally, a pointer to additional data can be |
||||
passed to the callback function whenever it is called. |
||||
*/ |
||||
void setCallback( RtMidiCallback callback, void *userData = 0 ); |
||||
|
||||
//! Cancel use of the current callback function (if one exists).
|
||||
/*!
|
||||
Subsequent incoming MIDI messages will be written to the queue |
||||
and can be retrieved with the \e getMessage function. |
||||
*/ |
||||
void cancelCallback(); |
||||
|
||||
//! Close an open MIDI connection (if one exists).
|
||||
void closePort( void ); |
||||
|
||||
//! Returns true if a port is open and false if not.
|
||||
/*!
|
||||
Note that this only applies to connections made with the openPort() |
||||
function, not to virtual ports. |
||||
*/ |
||||
virtual bool isPortOpen() const; |
||||
|
||||
//! Return the number of available MIDI input ports.
|
||||
/*!
|
||||
\return This function returns the number of MIDI ports of the selected API. |
||||
*/ |
||||
unsigned int getPortCount(); |
||||
|
||||
//! Return a string identifier for the specified MIDI input port number.
|
||||
/*!
|
||||
\return The name of the port with the given Id is returned. |
||||
\retval An empty string is returned if an invalid port specifier |
||||
is provided. User code should assume a UTF-8 encoding. |
||||
*/ |
||||
std::string getPortName( unsigned int portNumber = 0 ); |
||||
|
||||
//! Specify whether certain MIDI message types should be queued or ignored during input.
|
||||
/*!
|
||||
By default, MIDI timing and active sensing messages are ignored |
||||
during message input because of their relative high data rates. |
||||
MIDI sysex messages are ignored by default as well. Variable |
||||
values of "true" imply that the respective message type will be |
||||
ignored. |
||||
*/ |
||||
void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true ); |
||||
|
||||
//! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds.
|
||||
/*!
|
||||
This function returns immediately whether a new message is |
||||
available or not. A valid message is indicated by a non-zero |
||||
vector size. An exception is thrown if an error occurs during |
||||
message retrieval or an input connection was not previously |
||||
established. |
||||
*/ |
||||
double getMessage( std::vector<unsigned char> *message ); |
||||
|
||||
//! Set an error callback function to be invoked when an error has occured.
|
||||
/*!
|
||||
The callback function will be called whenever an error has occured. It is best |
||||
to set the error callback function before opening a port. |
||||
*/ |
||||
virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ); |
||||
|
||||
protected: |
||||
void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ); |
||||
}; |
||||
|
||||
/**********************************************************************/ |
||||
/*! \class RtMidiOut
|
||||
\brief A realtime MIDI output class. |
||||
|
||||
This class provides a common, platform-independent API for MIDI |
||||
output. It allows one to probe available MIDI output ports, to |
||||
connect to one such port, and to send MIDI bytes immediately over |
||||
the connection. Create multiple instances of this class to |
||||
connect to more than one MIDI device at the same time. With the |
||||
OS-X, Linux ALSA and JACK MIDI APIs, it is also possible to open a |
||||
virtual port to which other MIDI software clients can connect. |
||||
|
||||
by Gary P. Scavone, 2003-2017. |
||||
*/ |
||||
/**********************************************************************/ |
||||
|
||||
class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi |
||||
{ |
||||
public: |
||||
//! Default constructor that allows an optional client name.
|
||||
/*!
|
||||
An exception will be thrown if a MIDI system initialization error occurs. |
||||
|
||||
If no API argument is specified and multiple API support has been |
||||
compiled, the default order of use is ALSA, JACK (Linux) and CORE, |
||||
JACK (OS-X). |
||||
*/ |
||||
RtMidiOut( RtMidi::Api api=UNSPECIFIED, |
||||
const std::string& clientName = "RtMidi Output Client" ); |
||||
|
||||
//! The destructor closes any open MIDI connections.
|
||||
~RtMidiOut( void ) throw(); |
||||
|
||||
//! Returns the MIDI API specifier for the current instance of RtMidiOut.
|
||||
RtMidi::Api getCurrentApi( void ) throw(); |
||||
|
||||
//! Open a MIDI output connection.
|
||||
/*!
|
||||
An optional port number greater than 0 can be specified. |
||||
Otherwise, the default or first port found is opened. An |
||||
exception is thrown if an error occurs while attempting to make |
||||
the port connection. |
||||
*/ |
||||
void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Output" ) ); |
||||
|
||||
//! Close an open MIDI connection (if one exists).
|
||||
void closePort( void ); |
||||
|
||||
//! Returns true if a port is open and false if not.
|
||||
/*!
|
||||
Note that this only applies to connections made with the openPort() |
||||
function, not to virtual ports. |
||||
*/ |
||||
virtual bool isPortOpen() const; |
||||
|
||||
//! Create a virtual output port, with optional name, to allow software connections (OS X, JACK and ALSA only).
|
||||
/*!
|
||||
This function creates a virtual MIDI output port to which other |
||||
software applications can connect. This type of functionality |
||||
is currently only supported by the Macintosh OS-X, Linux ALSA |
||||
and JACK APIs (the function does nothing with the other APIs). |
||||
An exception is thrown if an error occurs while attempting to |
||||
create the virtual port. |
||||
*/ |
||||
void openVirtualPort( const std::string &portName = std::string( "RtMidi Output" ) ); |
||||
|
||||
//! Return the number of available MIDI output ports.
|
||||
unsigned int getPortCount( void ); |
||||
|
||||
//! Return a string identifier for the specified MIDI port type and number.
|
||||
/*!
|
||||
\return The name of the port with the given Id is returned. |
||||
\retval An empty string is returned if an invalid port specifier |
||||
is provided. User code should assume a UTF-8 encoding. |
||||
*/ |
||||
std::string getPortName( unsigned int portNumber = 0 ); |
||||
|
||||
//! Immediately send a single message out an open MIDI output port.
|
||||
/*!
|
||||
An exception is thrown if an error occurs during output or an |
||||
output connection was not previously established. |
||||
*/ |
||||
void sendMessage( const std::vector<unsigned char> *message ); |
||||
|
||||
//! Immediately send a single message out an open MIDI output port.
|
||||
/*!
|
||||
An exception is thrown if an error occurs during output or an |
||||
output connection was not previously established. |
||||
|
||||
\param message A pointer to the MIDI message as raw bytes |
||||
\param size Length of the MIDI message in bytes |
||||
*/ |
||||
void sendMessage( const unsigned char *message, size_t size ); |
||||
|
||||
//! Set an error callback function to be invoked when an error has occured.
|
||||
/*!
|
||||
The callback function will be called whenever an error has occured. It is best |
||||
to set the error callback function before opening a port. |
||||
*/ |
||||
virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ); |
||||
|
||||
protected: |
||||
void openMidiApi( RtMidi::Api api, const std::string &clientName ); |
||||
}; |
||||
|
||||
|
||||
// **************************************************************** //
|
||||
//
|
||||
// MidiInApi / MidiOutApi class declarations.
|
||||
//
|
||||
// Subclasses of MidiInApi and MidiOutApi contain all API- and
|
||||
// OS-specific code necessary to fully implement the RtMidi API.
|
||||
//
|
||||
// Note that MidiInApi and MidiOutApi are abstract base classes and
|
||||
// cannot be explicitly instantiated. RtMidiIn and RtMidiOut will
|
||||
// create instances of a MidiInApi or MidiOutApi subclass.
|
||||
//
|
||||
// **************************************************************** //
|
||||
|
||||
class RTMIDI_DLL_PUBLIC MidiApi |
||||
{ |
||||
public: |
||||
|
||||
MidiApi(); |
||||
virtual ~MidiApi(); |
||||
virtual RtMidi::Api getCurrentApi( void ) = 0; |
||||
virtual void openPort( unsigned int portNumber, const std::string &portName ) = 0; |
||||
virtual void openVirtualPort( const std::string &portName ) = 0; |
||||
virtual void closePort( void ) = 0; |
||||
virtual void setClientName( const std::string &clientName ) = 0; |
||||
virtual void setPortName( const std::string &portName ) = 0; |
||||
|
||||
virtual unsigned int getPortCount( void ) = 0; |
||||
virtual std::string getPortName( unsigned int portNumber ) = 0; |
||||
|
||||
inline bool isPortOpen() const { return connected_; } |
||||
void setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ); |
||||
|
||||
//! A basic error reporting function for RtMidi classes.
|
||||
void error( RtMidiError::Type type, std::string errorString ); |
||||
|
||||
protected: |
||||
virtual void initialize( const std::string& clientName ) = 0; |
||||
|
||||
void *apiData_; |
||||
bool connected_; |
||||
std::string errorString_; |
||||
RtMidiErrorCallback errorCallback_; |
||||
bool firstErrorOccurred_; |
||||
void *errorCallbackUserData_; |
||||
}; |
||||
|
||||
class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi |
||||
{ |
||||
public: |
||||
|
||||
MidiInApi( unsigned int queueSizeLimit ); |
||||
virtual ~MidiInApi( void ); |
||||
void setCallback( RtMidiIn::RtMidiCallback callback, void *userData ); |
||||
void cancelCallback( void ); |
||||
virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); |
||||
double getMessage( std::vector<unsigned char> *message ); |
||||
|
||||
// A MIDI structure used internally by the class to store incoming
|
||||
// messages. Each message represents one and only one MIDI message.
|
||||
struct MidiMessage { |
||||
std::vector<unsigned char> bytes; |
||||
|
||||
//! Time in seconds elapsed since the previous message
|
||||
double timeStamp; |
||||
|
||||
// Default constructor.
|
||||
MidiMessage() |
||||
: bytes(0), timeStamp(0.0) {} |
||||
}; |
||||
|
||||
struct MidiQueue { |
||||
unsigned int front; |
||||
unsigned int back; |
||||
unsigned int ringSize; |
||||
MidiMessage *ring; |
||||
|
||||
// Default constructor.
|
||||
MidiQueue() |
||||
: front(0), back(0), ringSize(0), ring(0) {} |
||||
bool push( const MidiMessage& ); |
||||
bool pop( std::vector<unsigned char>*, double* ); |
||||
unsigned int size( unsigned int *back=0, unsigned int *front=0 ); |
||||
}; |
||||
|
||||
// The RtMidiInData structure is used to pass private class data to
|
||||
// the MIDI input handling function or thread.
|
||||
struct RtMidiInData { |
||||
MidiQueue queue; |
||||
MidiMessage message; |
||||
unsigned char ignoreFlags; |
||||
bool doInput; |
||||
bool firstMessage; |
||||
void *apiData; |
||||
bool usingCallback; |
||||
RtMidiIn::RtMidiCallback userCallback; |
||||
void *userData; |
||||
bool continueSysex; |
||||
|
||||
// Default constructor.
|
||||
RtMidiInData() |
||||
: ignoreFlags(7), doInput(false), firstMessage(true), apiData(0), usingCallback(false), |
||||
userCallback(0), userData(0), continueSysex(false) {} |
||||
}; |
||||
|
||||
protected: |
||||
RtMidiInData inputData_; |
||||
}; |
||||
|
||||
class RTMIDI_DLL_PUBLIC MidiOutApi : public MidiApi |
||||
{ |
||||
public: |
||||
|
||||
MidiOutApi( void ); |
||||
virtual ~MidiOutApi( void ); |
||||
virtual void sendMessage( const unsigned char *message, size_t size ) = 0; |
||||
}; |
||||
|
||||
// **************************************************************** //
|
||||
//
|
||||
// Inline RtMidiIn and RtMidiOut definitions.
|
||||
//
|
||||
// **************************************************************** //
|
||||
|
||||
inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } |
||||
inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); } |
||||
inline void RtMidiIn :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); } |
||||
inline void RtMidiIn :: closePort( void ) { rtapi_->closePort(); } |
||||
inline bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); } |
||||
inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { static_cast<MidiInApi *>(rtapi_)->setCallback( callback, userData ); } |
||||
inline void RtMidiIn :: cancelCallback( void ) { static_cast<MidiInApi *>(rtapi_)->cancelCallback(); } |
||||
inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); } |
||||
inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } |
||||
inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { static_cast<MidiInApi *>(rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); } |
||||
inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return static_cast<MidiInApi *>(rtapi_)->getMessage( message ); } |
||||
inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } |
||||
|
||||
inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } |
||||
inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); } |
||||
inline void RtMidiOut :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); } |
||||
inline void RtMidiOut :: closePort( void ) { rtapi_->closePort(); } |
||||
inline bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); } |
||||
inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); } |
||||
inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } |
||||
inline void RtMidiOut :: sendMessage( const std::vector<unsigned char> *message ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( &message->at(0), message->size() ); } |
||||
inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( message, size ); } |
||||
inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } |
||||
|
||||
#endif |
@ -0,0 +1,107 @@
@@ -0,0 +1,107 @@
|
||||
#!/bin/sh |
||||
# Run this to generate all the initial makefiles, etc. |
||||
|
||||
srcdir=`dirname $0` |
||||
test -z "$srcdir" && srcdir=. |
||||
|
||||
DIE=0 |
||||
|
||||
if test -z "$*"; then |
||||
echo "**Warning**: I am going to run \`configure' with arguments for" |
||||
echo "developer/maintainer mode. If you wish to pass extra arguments," |
||||
echo "(such as --prefix), please specify them on the \`$0'" |
||||
echo "command line." |
||||
echo "If you wish to run configure yourself, please specify --no-configure." |
||||
echo |
||||
fi |
||||
|
||||
(test -f $srcdir/configure.ac) || { |
||||
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" |
||||
echo " top-level package directory" |
||||
exit 1 |
||||
} |
||||
|
||||
# Make some directories required by automake, if they don't exist |
||||
if ! [ -d config ]; then mkdir -v config; fi |
||||
if ! [ -d m4 ]; then mkdir -v m4; fi |
||||
|
||||
if ! autoreconf --version </dev/null >/dev/null 2>&1 |
||||
then |
||||
|
||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || { |
||||
echo |
||||
echo "**Error**: You must have \`autoconf' installed." |
||||
echo "Download the appropriate package for your distribution," |
||||
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" |
||||
DIE=1 |
||||
} |
||||
|
||||
(grep "^LT_INIT" $srcdir/configure.ac >/dev/null) && { |
||||
(libtoolize --version) < /dev/null > /dev/null 2>&1 \ |
||||
&& LIBTOOLIZE=libtoolize || { |
||||
(glibtoolize --version) < /dev/null > /dev/null 2>&1 \ |
||||
&& LIBTOOLIZE=glibtoolize || { |
||||
echo |
||||
echo "**Error**: You must have \`libtool' installed." |
||||
echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" |
||||
DIE=1 |
||||
} |
||||
} |
||||
} |
||||
|
||||
(automake --version) < /dev/null > /dev/null 2>&1 || { |
||||
echo |
||||
echo "**Error**: You must have \`automake' installed." |
||||
echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" |
||||
DIE=1 |
||||
NO_AUTOMAKE=yes |
||||
} |
||||
|
||||
|
||||
# if no automake, don't bother testing for aclocal |
||||
test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { |
||||
echo |
||||
echo "**Error**: Missing \`aclocal'. The version of \`automake'" |
||||
echo "installed doesn't appear recent enough." |
||||
echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/" |
||||
DIE=1 |
||||
} |
||||
|
||||
if test "$DIE" -eq 1; then |
||||
exit 1 |
||||
fi |
||||
|
||||
case $CC in |
||||
xlc ) |
||||
am_opt=--include-deps;; |
||||
esac |
||||
|
||||
echo "Running aclocal $aclocalinclude ..." |
||||
aclocal $ACLOCAL_FLAGS || exit 1 |
||||
echo "Running $LIBTOOLIZE ..." |
||||
$LIBTOOLIZE || exit 1 |
||||
echo "Running automake --gnu $am_opt ..." |
||||
automake --add-missing --gnu $am_opt || exit 1 |
||||
echo "Running autoconf ..." |
||||
autoconf || exit 1 |
||||
|
||||
else # autoreconf instead |
||||
|
||||
echo "Running autoreconf --verbose --install ..." |
||||
autoreconf --verbose --install || exit 1 |
||||
|
||||
fi |
||||
|
||||
if ( echo "$@" | grep -q -e "--no-configure" ); then |
||||
NOCONFIGURE=1 |
||||
fi |
||||
|
||||
conf_flags="--enable-maintainer-mode --enable-debug --disable-silent-rules" |
||||
|
||||
if test x$NOCONFIGURE = x; then |
||||
echo Running $srcdir/configure $conf_flags "$@" ... |
||||
$srcdir/configure $conf_flags "$@" \ |
||||
&& echo Now type \`make\' to compile. || exit 1 |
||||
else |
||||
echo Skipping configure process. |
||||
fi |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") |
||||
message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") |
||||
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") |
||||
|
||||
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) |
||||
string(REGEX REPLACE "\n" ";" files "${files}") |
||||
foreach(file ${files}) |
||||
message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") |
||||
if(EXISTS "$ENV{DESTDIR}${file}") |
||||
exec_program( |
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" |
||||
OUTPUT_VARIABLE rm_out |
||||
RETURN_VALUE rm_retval |
||||
) |
||||
if(NOT "${rm_retval}" STREQUAL 0) |
||||
message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") |
||||
endif(NOT "${rm_retval}" STREQUAL 0) |
||||
else(EXISTS "$ENV{DESTDIR}${file}") |
||||
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") |
||||
endif(EXISTS "$ENV{DESTDIR}${file}") |
||||
endforeach(file) |
@ -0,0 +1,238 @@
@@ -0,0 +1,238 @@
|
||||
# Process this file with autoconf to produce a configure script. |
||||
AC_INIT(RtMidi, 4.0.0, gary@music.mcgill.ca, rtmidi) |
||||
AC_CONFIG_AUX_DIR(config) |
||||
AC_CONFIG_SRCDIR(RtMidi.cpp) |
||||
AC_CONFIG_FILES([rtmidi-config rtmidi.pc Makefile tests/Makefile doc/Makefile doc/doxygen/Doxyfile]) |
||||
AM_INIT_AUTOMAKE([1.14 -Wall -Werror foreign subdir-objects]) |
||||
|
||||
# libtool version: current:revision:age |
||||
# |
||||
# If the library source code has changed at all since the last update, then |
||||
# increment revision (`c:r:a' becomes `c:r+1:a'). |
||||
# |
||||
# If any interfaces have been added, removed, or changed since the last update, |
||||
# increment current, and set revision to 0. |
||||
# |
||||
# If any interfaces have been added since the last public release, then |
||||
# increment age. |
||||
# |
||||
# If any interfaces have been removed since the last public release, then set |
||||
# age to 0. |
||||
m4_define([lt_current], 5) |
||||
m4_define([lt_revision], 0) |
||||
m4_define([lt_age], 0) |
||||
|
||||
m4_define([lt_version_info], [lt_current:lt_revision:lt_age]) |
||||
m4_define([lt_current_minus_age], [m4_eval(lt_current - lt_age)]) |
||||
|
||||
SO_VERSION=lt_version_info |
||||
AC_SUBST(SO_VERSION) |
||||
AC_SUBST(LIBS) |
||||
AC_SUBST(api) |
||||
AC_SUBST(req) |
||||
|
||||
api="" |
||||
req="" |
||||
|
||||
# Fill GXX with something before test. |
||||
GXX="no" |
||||
|
||||
# if the user did not provide any CXXFLAGS, we can override them |
||||
AS_IF([test "x$CXXFLAGS" = "x" ], [override_cxx=yes], [override_cxx=no]) |
||||
AS_IF([test "x$CFLAGS" = "x" ], [override_c=yes], [override_c=no]) |
||||
|
||||
# Check version number coherency between RtMidi.h and configure.ac |
||||
AC_MSG_CHECKING([that version numbers are coherent]) |
||||
RTMIDI_VERSION=`sed -n 's/#define RTMIDI_VERSION "\(.*\)"/\1/p' $srcdir/RtMidi.h` |
||||
AS_IF( |
||||
[test "x$RTMIDI_VERSION" != "x$PACKAGE_VERSION"], |
||||
[AC_MSG_FAILURE([testing RTMIDI_VERSION==PACKAGE_VERSION failed, check that RtMidi.h defines RTMIDI_VERSION as "$PACKAGE_VERSION" or that the first line of configure.ac has been updated.])]) |
||||
|
||||
# Enable some nice automake features if they are available |
||||
m4_ifdef([AM_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) |
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) |
||||
|
||||
# configure flags |
||||
AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], [enable various debugging output])]) |
||||
AC_ARG_WITH(jack, [AS_HELP_STRING([--with-jack], [choose JACK server support])]) |
||||
AC_ARG_WITH(alsa, [AS_HELP_STRING([--with-alsa], [choose native ALSA sequencer API support (linux only)])]) |
||||
AC_ARG_WITH(core, [AS_HELP_STRING([--with-core], [ choose CoreMIDI API support (mac only)])]) |
||||
AC_ARG_WITH(winmm, [AS_HELP_STRING([--with-winmm], [ choose Windows MultiMedia (MM) API support (win32 only)])]) |
||||
AC_ARG_WITH(winks, [AS_HELP_STRING([--with-winks], [ choose kernel streaming support (win32 only)])]) |
||||
|
||||
|
||||
# Checks for programs. |
||||
AC_PROG_CXX(g++ CC c++ cxx) |
||||
AM_PROG_AR |
||||
AC_PATH_PROG(AR, ar, no) |
||||
AS_IF([test "x$AR" = "xno"], [ |
||||
AC_MSG_ERROR([Could not find ar - needed to create a library]) |
||||
]) |
||||
|
||||
LT_INIT([win32-dll]) |
||||
AC_CONFIG_MACRO_DIR([m4]) |
||||
|
||||
# Checks for header files. |
||||
AC_HEADER_STDC |
||||
#AC_CHECK_HEADERS(sys/ioctl.h unistd.h) |
||||
|
||||
# Check for POSIX semaphore support |
||||
AC_CHECK_HEADER([semaphore.h], [ |
||||
AC_CHECK_LIB(pthread, sem_init, |
||||
AC_DEFINE([HAVE_SEMAPHORE],[1],[Define to 1 if you have POSIX semaphore support on your system.]), |
||||
AC_MSG_WARN([POSIX semaphore support not found; data may be lost on closePort])) |
||||
]) |
||||
|
||||
|
||||
# check for debug |
||||
AC_MSG_CHECKING(whether to compile debug version) |
||||
debugflags="" |
||||
object_path=Release |
||||
AS_CASE([${enable_debug}], |
||||
[ yes ], [ |
||||
AC_MSG_RESULT([yes]) |
||||
CPPFLAGS="-D__RTMIDI_DEBUG ${CPPFLAGS}" |
||||
debugflags="${debugflags} -g" |
||||
object_path=Debug |
||||
], |
||||
[ no ], [ |
||||
AC_MSG_RESULT([no!]) |
||||
debugflags="${debugflags} -O3" |
||||
], [ |
||||
AC_MSG_RESULT([no]) |
||||
]) |
||||
# For debugging and optimization ... overwrite default because it has both -g and -O2 |
||||
AS_IF([test "x$debugflags" != x], |
||||
AS_IF([test "x$override_cxx" = "xyes" ], CXXFLAGS="$CXXFLAGS $debugflags", CXXFLAGS="$debugflags $CXXFLAGS") |
||||
AS_IF([test "x$override_c" = "xyes" ], CFLAGS="$CFLAGS $debugflags", CFLAGS="$debugflags $CFLAGS") |
||||
) |
||||
|
||||
# Check compiler and use -Wall if gnu. |
||||
AS_IF([test "x$GXX" = "xyes"], [ |
||||
CXXFLAGS="-Wall -Wextra ${CXXFLAGS}" |
||||
]) |
||||
|
||||
# Checks for doxygen |
||||
AC_CHECK_PROG( DOXYGEN, [doxygen], [doxygen] ) |
||||
AM_CONDITIONAL( MAKE_DOC, [test "x${DOXYGEN}" != x] ) |
||||
|
||||
# Copy doc files to build dir if necessary |
||||
AC_CONFIG_LINKS( [doc/doxygen/footer.html:doc/doxygen/footer.html] ) |
||||
AC_CONFIG_LINKS( [doc/doxygen/header.html:doc/doxygen/header.html] ) |
||||
AC_CONFIG_LINKS( [doc/doxygen/tutorial.txt:doc/doxygen/tutorial.txt] ) |
||||
AC_CONFIG_LINKS( [doc/images/ccrma.gif:doc/images/ccrma.gif] ) |
||||
AC_CONFIG_LINKS( [doc/images/mcgill.gif:doc/images/mcgill.gif] ) |
||||
|
||||
# Checks for package options and external software |
||||
AC_CANONICAL_HOST |
||||
|
||||
# Aggregate options into a single string. |
||||
AS_IF([test "x$with_jack" = "xyes"], [systems="$systems jack"]) |
||||
AS_IF([test "x$with_alsa" = "xyes"], [systems="$systems alsa"]) |
||||
AS_IF([test "x$with_core" = "xyes"], [systems="$systems core"]) |
||||
AS_IF([test "x$with_winmm" = "xyes"], [systems="$systems winmm"]) |
||||
AS_IF([test "x$with_winks" = "xyes"], [systems="$systems winks"]) |
||||
AS_IF([test "x$with_dummy" = "xyes"], [systems="$systems dummy"]) |
||||
required=" $systems " |
||||
|
||||
# If none, assign defaults if any are known for this OS. |
||||
# User must specified with-* options for any unknown OS. |
||||
AS_IF([test "x$systems" = "x"], |
||||
AS_CASE([$host], |
||||
[*-*-linux*], [systems="alsa jack"], |
||||
[*-*-gnu], [systems="jack"], |
||||
[*-*-kfreebsd*-gnu], [systems="jack"], |
||||
[*-apple*], [systems="core jack"], |
||||
[*-mingw32*], [systems="winmm winks jack"], |
||||
[*-mingw64*], [systems="winmm winks jack"] |
||||
)) |
||||
|
||||
# If any were specifically requested disabled, do it. |
||||
AS_IF([test "x$with_jack" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v jack`]) |
||||
AS_IF([test "x$with_alsa" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v alsa`]) |
||||
AS_IF([test "x$with_winmm" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v winmm`]) |
||||
AS_IF([test "x$with_winks" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v winks`]) |
||||
AS_IF([test "x$with_core" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v core`]) |
||||
AS_IF([test "x$with_dummy" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v dummy`]) |
||||
systems=" `echo $systems|tr \\\\n ' '` " |
||||
|
||||
# For each MIDI system, check if it is selected and found. |
||||
# Note: Order specified above is not necessarily respected. However, |
||||
# *actual* priority is set at run-time, see RtMidiIn::openMidiApi and RtMidiOut::openMidiApi. |
||||
# One AS_CASE per system, since they are not mutually-exclusive. |
||||
|
||||
AS_CASE(["$systems"], [*" jack "*], [ |
||||
AC_CHECK_LIB(jack, jack_client_open, |
||||
[api="$api -D__UNIX_JACK__" |
||||
req="$req jack" |
||||
need_pthread=yes |
||||
found="$found Jack" |
||||
LIBS="-ljack $LIBS"], |
||||
AS_CASE(["$required"], [*" jack "*], |
||||
AC_MSG_ERROR([JACK support requires the jack library!]))) |
||||
AC_CHECK_LIB(jack, jack_port_rename, AC_DEFINE(JACK_HAS_PORT_RENAME), ) |
||||
]) |
||||
|
||||
AS_CASE(["$systems"], [*" alsa "*], [ |
||||
AC_CHECK_LIB(asound, snd_seq_open, |
||||
[api="$api -D__LINUX_ALSA__" |
||||
req="$req alsa" |
||||
need_pthread=yes |
||||
found="$found ALSA" |
||||
LIBS="-lasound $LIBS"], |
||||
AS_CASE(["$required"], [*" alsa "*], |
||||
AC_MSG_ERROR([ALSA support requires the asound library!]))) |
||||
]) |
||||
|
||||
AS_CASE(["$systems"], [*" core "*], [ |
||||
AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, |
||||
[api="$api -D__MACOSX_CORE__" |
||||
need_pthread=yes |
||||
found="$found CoreMIDI", |
||||
LIBS="$LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio"], |
||||
AS_CASE(["$required"], [*" core "*], |
||||
AC_MSG_ERROR([CoreMIDI header files not found!]))) |
||||
]) |
||||
|
||||
AS_CASE(["$systems"], [*" winmm "*], [ |
||||
AC_CHECK_HEADERS(windows.h mmsystem.h, |
||||
[api="$api -D__WINDOWS_MM__" |
||||
CPPFLAGS="-I$srcdir/include $CPPFLAGS" |
||||
need_ole32=yes |
||||
found="$found WinMM" |
||||
api="$api -D__WINDOWS_MM__" |
||||
LIBS="-lwinmm ${LIBS}"]) |
||||
]) |
||||
|
||||
AS_CASE(["$systems"], [*" winks "*], [ |
||||
AC_CHECK_HEADERS(windows.h audioclient.h avrt.h mmdeviceapi.h, |
||||
[api="$api -D__WINDOWS_WINKS__" |
||||
CPPFLAGS="-I$srcdir/include $CPPFLAGS" |
||||
need_ole32=yes |
||||
found="$found kernel-streaming" |
||||
api="$api -D__WINDOWS_WINKS__" |
||||
LIBS="-lsetupapi -lksuser ${LIBS}"]) |
||||
]) |
||||
|
||||
AS_IF([test -n "$need_ole32"], [LIBS="-lole32 $LIBS"]) |
||||
|
||||
AS_IF([test -n "$need_pthread"],[ |
||||
AC_MSG_CHECKING([for pthread]) |
||||
AC_CHECK_LIB(pthread, pthread_create, , |
||||
AC_MSG_ERROR([RtAudio requires the pthread library!]))]) |
||||
|
||||
AC_MSG_CHECKING([for MIDI API]) |
||||
|
||||
# Error case: no known realtime systems found. |
||||
AS_IF([test x"$api" = "x"], [ |
||||
AC_MSG_RESULT([none]) |
||||
AC_MSG_ERROR([No known system type found for MIDI support!]) |
||||
], [ |
||||
AC_MSG_RESULT([$found]) |
||||
]) |
||||
|
||||
CPPFLAGS="$CPPFLAGS $api" |
||||
|
||||
AC_OUTPUT |
||||
|
||||
chmod oug+x rtmidi-config |
@ -0,0 +1,355 @@
@@ -0,0 +1,355 @@
|
||||
package rtmidi |
||||
|
||||
/* |
||||
#cgo CXXFLAGS: -g |
||||
#cgo LDFLAGS: -g |
||||
|
||||
#cgo linux CXXFLAGS: -D__LINUX_ALSA__ |
||||
#cgo linux LDFLAGS: -lasound -pthread |
||||
#cgo windows CXXFLAGS: -D__WINDOWS_MM__ |
||||
#cgo windows LDFLAGS: -luuid -lksuser -lwinmm -lole32 |
||||
#cgo darwin CXXFLAGS: -D__MACOSX_CORE__ |
||||
#cgo darwin LDFLAGS: -framework CoreServices -framework CoreAudio -framework CoreMIDI -framework CoreFoundation |