Skip to content

Commit

Permalink
Merge branch 'master' into fix-tutorial-link
Browse files Browse the repository at this point in the history
  • Loading branch information
garyscavone authored Apr 12, 2019
2 parents d3f958b + a3b11ff commit 8a683f2
Show file tree
Hide file tree
Showing 12 changed files with 416 additions and 52 deletions.
57 changes: 54 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,61 @@
/config
/configure
/Makefile.in
/aclocal.m4
/autom4te.cache
/config
/config.log
/config.status
/configure
/libtool
/rtmidi-config
/rtmidi.pc
/m4

/Makefile
/Makefile.in
/doc/Makefile
/doc/Makefile.in
/tests/Makefile
/tests/Makefile.in

/doc/html
/doc/doxygen-build.stamp
/doc/doxygen/Doxyfile

/build*/

/.deps
/.libs
/tests/.deps
/tests/.libs

# Prerequisites
*.d

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app
21 changes: 12 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ if(WIN32)
endif()

# Build Options
option(BUILD_SHARED_LIBS "Compile library shared lib." TRUE)
option(BUILD_STATIC_LIBS "Compile library static lib." TRUE)
option(BUILD_TESTING "Compile test programs." TRUE)
option(RTMIDI_BUILD_SHARED_LIBS "Compile library shared lib." TRUE)
option(RTMIDI_BUILD_STATIC_LIBS "Compile library static lib." TRUE)
option(RTMIDI_BUILD_TESTING "Compile test programs." TRUE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type (Release,Debug)")
set(RTMIDI_TARGETNAME_UNINSTALL "uninstall" CACHE STRING "Name of 'uninstall' build target")

# API Options
option(RTMIDI_API_JACK "Compile with JACK support." ${HAVE_JACK})
Expand Down Expand Up @@ -136,7 +137,7 @@ endif()
# Create library targets.
cmake_policy(SET CMP0042 OLD)
set(LIB_TARGETS)
if(BUILD_SHARED_LIBS)
if(RTMIDI_BUILD_SHARED_LIBS)
add_library(rtmidi SHARED ${rtmidi_SOURCES})
list(APPEND LIB_TARGETS rtmidi)

Expand All @@ -153,11 +154,12 @@ if(BUILD_SHARED_LIBS)

# Set compile-time definitions
target_compile_definitions(rtmidi PRIVATE ${API_DEFS})
target_compile_definitions(rtmidi PRIVATE RTMIDI_EXPORT)

target_link_libraries(rtmidi ${LINKLIBS})
endif()

if(BUILD_STATIC_LIBS)
if(RTMIDI_BUILD_STATIC_LIBS)
add_library(rtmidi_static STATIC ${rtmidi_SOURCES})
list(APPEND LIB_TARGETS rtmidi_static)

Expand All @@ -182,15 +184,16 @@ endif()
include(GNUInstallDirs)

# Add tests if requested.
if(BUILD_TESTING)
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
set_target_properties(cmidiin midiclock midiout midiprobe qmidiin sysextest apinames
PROPERTIES RUNTIME_OUTPUT_DIRECTORY tests
INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}
LINK_LIBRARIES ${LIBRTMIDI})
Expand All @@ -206,7 +209,7 @@ message(STATUS "Compiling with support for: ${apilist}")
# PkgConfig file
string(REPLACE ";" " " req "${PKGCONFIG_REQUIRES}")
string(REPLACE ";" " " api "${API_DEFS}")
configure_file("rtmidi.pc.in" "rtmidi.pc" @ONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/rtmidi.pc.in" "rtmidi.pc" @ONLY)

# Add install rule.
install(TARGETS ${LIB_TARGETS}
Expand Down Expand Up @@ -248,7 +251,7 @@ configure_file(
"${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake" @ONLY)

# Create uninstall target.
add_custom_target(uninstall
add_custom_target(${RTMIDI_TARGETNAME_UNINSTALL}
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake)

install(
Expand Down
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ 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 \
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ In some cases, for example to use RtMidi with GS Synth, it may be necessary for

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.
Expand Down
125 changes: 106 additions & 19 deletions RtMidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,27 +289,79 @@ std::string RtMidi :: getVersion( void ) throw()
return std::string( RTMIDI_VERSION );
}

void RtMidi :: getCompiledApi( std::vector<RtMidi::Api> &apis ) throw()
{
apis.clear();
// Define API names and display names.
// Must be in same order as API enum.
extern "C" {
const char* rtmidi_api_names[][2] = {
{ "unspecified" , "Unknown" },
{ "core" , "CoreMidi" },
{ "alsa" , "ALSA" },
{ "jack" , "Jack" },
{ "winmm" , "Windows MultiMedia" },
{ "dummy" , "Dummy" },
};
const unsigned int rtmidi_num_api_names =
sizeof(rtmidi_api_names)/sizeof(rtmidi_api_names[0]);

// The order here will control the order of RtMidi's API search in
// the constructor.
// The order here will control the order of RtMidi's API search in
// the constructor.
extern "C" const RtMidi::Api rtmidi_compiled_apis[] = {
#if defined(__MACOSX_CORE__)
apis.push_back( MACOSX_CORE );
RtMidi::MACOSX_CORE,
#endif
#if defined(__LINUX_ALSA__)
apis.push_back( LINUX_ALSA );
RtMidi::LINUX_ALSA,
#endif
#if defined(__UNIX_JACK__)
apis.push_back( UNIX_JACK );
RtMidi::UNIX_JACK,
#endif
#if defined(__WINDOWS_MM__)
apis.push_back( WINDOWS_MM );
RtMidi::WINDOWS_MM,
#endif
#if defined(__RTMIDI_DUMMY__)
apis.push_back( RTMIDI_DUMMY );
RtMidi::RTMIDI_DUMMY,
#endif
RtMidi::UNSPECIFIED,
};
extern "C" const unsigned int rtmidi_num_compiled_apis =
sizeof(rtmidi_compiled_apis)/sizeof(rtmidi_compiled_apis[0])-1;
}

// This is a compile-time check that rtmidi_num_api_names == RtMidi::NUM_APIS.
// If the build breaks here, check that they match.
template<bool b> class StaticAssert { private: StaticAssert() {} };
template<> class StaticAssert<true>{ public: StaticAssert() {} };
class StaticAssertions { StaticAssertions() {
StaticAssert<rtmidi_num_api_names == RtMidi::NUM_APIS>();
}};

void RtMidi :: getCompiledApi( std::vector<RtMidi::Api> &apis ) throw()
{
apis = std::vector<RtMidi::Api>(rtmidi_compiled_apis,
rtmidi_compiled_apis + rtmidi_num_compiled_apis);
}

std::string RtMidi :: getApiName( RtMidi::Api api )
{
if (api < 0 || api >= RtMidi::NUM_APIS)
return "";
return rtmidi_api_names[api][0];
}

std::string RtMidi :: getApiDisplayName( RtMidi::Api api )
{
if (api < 0 || api >= RtMidi::NUM_APIS)
return "Unknown";
return rtmidi_api_names[api][1];
}

RtMidi::Api RtMidi :: getCompiledApiByName( const std::string &name )
{
unsigned int i=0;
for (i = 0; i < rtmidi_num_compiled_apis; ++i)
if (name == rtmidi_api_names[rtmidi_compiled_apis[i]][0])
return rtmidi_compiled_apis[i];
return RtMidi::UNSPECIFIED;
}

void RtMidi :: setClientName( const std::string &clientName )
Expand Down Expand Up @@ -2914,29 +2966,64 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg )

// Is port created?
if ( jData->port == NULL ) return 0;

void *buff = jack_port_get_buffer( jData->port, nframes );
bool& continueSysex = rtData->continueSysex;
unsigned char& ignoreFlags = rtData->ignoreFlags;

// We have midi events in buffer
int evCount = jack_midi_get_event_count( buff );
for (int j = 0; j < evCount; j++) {
MidiInApi::MidiMessage message;
message.bytes.clear();

MidiInApi::MidiMessage& message = rtData->message;
jack_midi_event_get( &event, buff, j );

for ( unsigned int i = 0; i < event.size; i++ )
message.bytes.push_back( event.buffer[i] );

// Compute the delta time.
time = jack_get_time();
if ( rtData->firstMessage == true )
if ( rtData->firstMessage == true ) {
message.timeStamp = 0.0;
rtData->firstMessage = false;
else
} else
message.timeStamp = ( time - jData->lastTime ) * 0.000001;

jData->lastTime = time;

if ( !rtData->continueSysex ) {
if ( !continueSysex )
message.bytes.clear();

if ( !( ( continueSysex || event.buffer[0] == 0xF0 ) && ( ignoreFlags & 0x01 ) ) ) {
// Unless this is a (possibly continued) SysEx message and we're ignoring SysEx,
// copy the event buffer into the MIDI message struct.
for ( unsigned int i = 0; i < event.size; i++ )
message.bytes.push_back( event.buffer[i] );
}

switch ( event.buffer[0] ) {
case 0xF0:
// Start of a SysEx message
continueSysex = event.buffer[event.size - 1] != 0xF7;
if ( ignoreFlags & 0x01 ) continue;
break;
case 0xF1:
case 0xF8:
// MIDI Time Code or Timing Clock message
if ( ignoreFlags & 0x02 ) continue;
break;
case 0xFE:
// Active Sensing message
if ( ignoreFlags & 0x04 ) continue;
break;
default:
if ( continueSysex ) {
// Continuation of a SysEx message
continueSysex = event.buffer[event.size - 1] != 0xF7;
if ( ignoreFlags & 0x01 ) continue;
}
// All other MIDI messages
}

if ( !continueSysex ) {
// If not a continuation of a SysEx message,
// invoke the user callback function or queue the message.
if ( rtData->usingCallback ) {
RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) rtData->userCallback;
callback( message.timeStamp, &message.bytes, rtData->userData );
Expand Down
32 changes: 30 additions & 2 deletions RtMidi.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@
#define RTMIDI_H

#if defined _WIN32 || defined __CYGWIN__
#define RTMIDI_DLL_PUBLIC
#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" )) )
Expand Down Expand Up @@ -134,7 +138,8 @@ class RTMIDI_DLL_PUBLIC RtMidi
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. */
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.
Expand All @@ -148,6 +153,29 @@ class RTMIDI_DLL_PUBLIC RtMidi
*/
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;

Expand Down
2 changes: 1 addition & 1 deletion contrib/go/rtmidi/rtmidi.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (api API) String() string {
func CompiledAPI() (apis []API) {
n := C.rtmidi_get_compiled_api(nil, 0)
capis := make([]C.enum_RtMidiApi, n, n)
C.rtmidi_get_compiled_api(&capis[0], _Ctype_uint(n))
C.rtmidi_get_compiled_api(&capis[0], C.uint(n))
for _, capi := range capis {
apis = append(apis, API(capi))
}
Expand Down
4 changes: 3 additions & 1 deletion doc/doxygen/tutorial.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ associated with caught exceptions can be displayed with, for example,
the RtMidiError::printMessage() function.


\section probing Probing Ports
\section probing Probing Ports / Devices

A client generally must query the available MIDI ports before deciding which to use. The following example outlines how this can be done.

Expand Down Expand Up @@ -128,6 +128,8 @@ int main()
}
\endcode

Note that the port enumeration is system specific and will change if any devices are unplugged or plugged (or a new virtual port opened or closed) by the user. Thus, the port numbers should be verified immediately before opening a stream. As well, if a user unplugs a device (or closes a virtual port) while a port connection exists to that device/port, a MIDI system error will be generated.

\section output MIDI Output

The RtMidiOut class provides simple functionality to immediately send messages over a MIDI connection. No timing functionality is provided. Note that there is an overloaded RtMidiOut::sendMessage() function that does not use std::vectors.
Expand Down
Loading

0 comments on commit 8a683f2

Please sign in to comment.