Skip to content

Commit

Permalink
API names, and conversion from/to API identifier
Browse files Browse the repository at this point in the history
  • Loading branch information
jpcima committed Aug 17, 2018
1 parent 3155671 commit 37e900b
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 27 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ 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()
Expand Down Expand Up @@ -189,8 +190,9 @@ if(BUILD_TESTING)
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 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
72 changes: 62 additions & 10 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
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
41 changes: 29 additions & 12 deletions rtmidi_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,40 @@ class CallbackProxyUserData
void *user_data;
};

extern "C" const enum RtMidiApi rtmidi_compiled_apis[]; // casting from RtMidi::Api[]
extern "C" const unsigned int rtmidi_num_compiled_apis;

/* RtMidi API */
int rtmidi_get_compiled_api (enum RtMidiApi *apis, unsigned int apis_size)
{
std::vector<RtMidi::Api> v;
try {
RtMidi::getCompiledApi(v);
} catch (...) {
return -1;
}
unsigned num = rtmidi_num_compiled_apis;
if (apis) {
unsigned int i;
for (i = 0; i < v.size() && i < apis_size; i++)
apis[i] = (RtMidiApi) v[i];
return (int)i;
num = (num < apis_size) ? num : apis_size;
memcpy(apis, rtmidi_compiled_apis, num * sizeof(enum RtMidiApi));
}
return (int)num;
}

extern "C" const char* rtmidi_api_names[][2];
const char *rtmidi_api_name(enum RtMidiApi api) {
if (api < 0 || api >= RT_MIDI_API_NUM)
return NULL;
return rtmidi_api_names[api][0];
}

const char *rtmidi_api_display_name(enum RtMidiApi api)
{
if (api < 0 || api >= RT_MIDI_API_NUM)
return "Unknown";
return rtmidi_api_names[api][1];
}

enum RtMidiApi rtmidi_compiled_api_by_name(const char *name) {
RtMidi::Api api = RtMidi::UNSPECIFIED;
if (name) {
api = RtMidi::getCompiledApiByName(name);
}
// return length for NULL argument.
return v.size();
return (enum RtMidiApi)api;
}

void rtmidi_error (MidiApi *api, enum RtMidiErrorType type, const char* errorString)
Expand Down
16 changes: 15 additions & 1 deletion rtmidi_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
#define RTMIDI_C_H

#if defined(RTMIDI_EXPORT)
#if defined _WIN32 || defined __CYGWIN__
#define RTMIDIAPI __declspec(dllexport)
#else
#define RTMIDIAPI __attribute__((visibility("default")))
#endif
#else
#define RTMIDIAPI //__declspec(dllimport)
#endif

Expand Down Expand Up @@ -43,7 +47,8 @@ enum RtMidiApi {
RT_MIDI_API_LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */
RT_MIDI_API_UNIX_JACK, /*!< The Jack Low-Latency MIDI Server API. */
RT_MIDI_API_WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */
RT_MIDI_API_RTMIDI_DUMMY /*!< A compilable but non-functional API. */
RT_MIDI_API_RTMIDI_DUMMY, /*!< A compilable but non-functional API. */
RT_MIDI_API_NUM /*!< Number of values in this enum. */
};

enum RtMidiErrorType {
Expand Down Expand Up @@ -75,6 +80,15 @@ typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message,
*/
RTMIDIAPI int rtmidi_get_compiled_api (enum RtMidiApi *apis, unsigned int apis_size);

//! Return the name of a specified compiled MIDI API.
RTMIDIAPI const char *rtmidi_api_name(enum RtMidiApi api);

//! Return the display name of a specified compiled MIDI API.
RTMIDIAPI const char *rtmidi_api_display_name(enum RtMidiApi api);

//! Return the compiled MIDI API having the given name.
RTMIDIAPI enum RtMidiApi rtmidi_compiled_api_by_name(const char *name);

//! Report an error.
RTMIDIAPI void rtmidi_error (enum RtMidiErrorType type, const char* errorString);

Expand Down
5 changes: 4 additions & 1 deletion tests/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

noinst_PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiclock_in midiclock_out
noinst_PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiclock_in midiclock_out apinames

AM_CXXFLAGS = -Wall -I$(top_srcdir)

Expand All @@ -24,5 +24,8 @@ midiclock_in_LDADD = $(top_builddir)/librtmidi.la
midiclock_out_SOURCES = midiclock.cpp
midiclock_out_LDADD = $(top_builddir)/librtmidi.la

apinames_SOURCES = apinames.cpp
apinames_LDADD = $(top_builddir)/librtmidi.la

EXTRA_DIST = cmidiin.dsp midiout.dsp midiprobe.dsp qmidiin.dsp \
sysextest.dsp RtMidi.dsw
Loading

0 comments on commit 37e900b

Please sign in to comment.