From a5c375c7280e2134391a7d840f4fbda0a7f684bb Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Sat, 29 Aug 2015 20:44:00 +0800 Subject: Add C API. --- Makefile.am | 4 +- msw/rtmidilib.vcproj | 8 +++ rtmidi_c.cpp | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++ rtmidi_c.h | 66 +++++++++++++++++++ 4 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 rtmidi_c.cpp create mode 100644 rtmidi_c.h diff --git a/Makefile.am b/Makefile.am index 4851619..706daf0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,4 +2,6 @@ lib_LTLIBRARIES = %D%/librtmidi.la %C%_librtmidi_la_LDFLAGS = -no-undefined %C%_librtmidi_la_SOURCES = \ %D%/RtMidi.cpp \ - %D%/RtMidi.h + %D%/RtMidi.h \ + %D%/rtmidi_c.cpp \ + %D%/rtmidi_c.h diff --git a/msw/rtmidilib.vcproj b/msw/rtmidilib.vcproj index af1f75c..20a458f 100755 --- a/msw/rtmidilib.vcproj +++ b/msw/rtmidilib.vcproj @@ -151,6 +151,10 @@ RelativePath="..\RtMidi.cpp" > + + + + +#include +#include "rtmidi_c.h" +#include "RtMidi.h" + +/* misc */ +int rtmidi_sizeof_rtmidi_api () +{ + return sizeof (RtMidiApi); +} + +/* RtMidi API */ +int rtmidi_get_compiled_api (enum RtMidiApi **apis) // return length for NULL argument. +{ + if (!apis || !(*apis)) { + std::vector *v = new std::vector (); + try { + RtMidi::getCompiledApi (*v); + int size = v->size (); + delete v; + return size; + } catch (...) { + return -1; + } + } else { + try { + std::vector *v = new std::vector (); + RtMidi::getCompiledApi (*v); + for (unsigned int i = 0; i < v->size (); i++) + (*apis) [i] = (RtMidiApi) v->at (i); + delete v; + return 0; + } catch (...) { + return -1; + } + } +} + +void rtmidi_error (MidiApi *api, enum RtMidiErrorType type, const char* errorString) +{ + std::string msg = errorString; + api->error ((RtMidiError::Type) type, msg); +} + +void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName) +{ + std::string name = portName; + ((RtMidi*) device)->openPort (portNumber, name); +} + +void rtmidi_open_virtual_port (RtMidiPtr device, const char *portName) +{ + std::string name = portName; + ((RtMidi*) device)->openVirtualPort (name); +} + +void rtmidi_close_port (RtMidiPtr device) +{ + ((RtMidi*) device)->closePort (); +} + +unsigned int rtmidi_get_port_count (RtMidiPtr device) +{ + return ((RtMidi*) device)->getPortCount (); +} + +const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber) +{ + std::string name = ((RtMidi*) device)->getPortName (portNumber); + return name.c_str (); +} + +/* RtMidiIn API */ +RtMidiInPtr rtmidi_in_create_default () +{ + return new RtMidiIn (); +} + +RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsigned int queueSizeLimit) +{ + std::string name = clientName; + return new RtMidiIn ((RtMidi::Api) api, name, queueSizeLimit); +} + +void rtmidi_in_free (RtMidiInPtr device) +{ + delete (RtMidiIn*) device; +} + +enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device) +{ + return (RtMidiApi) ((RtMidiIn*) device)->getCurrentApi (); +} + +class CallbackProxyUserData +{ + public: + CallbackProxyUserData (RtMidiCCallback cCallback, void *userData) + : c_callback (cCallback), user_data (userData) + { + } + RtMidiCCallback c_callback; + void *user_data; +}; + +void callback_proxy (double timeStamp, std::vector *message, void *userData) +{ + CallbackProxyUserData* data = reinterpret_cast (userData); + data->c_callback (timeStamp, message->data (), data->user_data); +} + +void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData) +{ + void *data = (void *) new CallbackProxyUserData (callback, userData); + ((RtMidiIn*) device)->setCallback (callback_proxy, data); +} + +void rtmidi_in_cancel_callback (RtMidiInPtr device) +{ + ((RtMidiIn*) device)->cancelCallback (); +} + +void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense) +{ + ((RtMidiIn*) device)->ignoreTypes (midiSysex, midiTime, midiSense); +} + +double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message) +{ + try { + // FIXME: use allocator to achieve efficient buffering + std::vector *v = new std::vector (); + double ret = ((RtMidiIn*) device)->getMessage (v); + *message = (unsigned char *) malloc ((int) ret); + memcpy (*message, v->data (), (int) ret); + delete v; + return ret; + } catch (...) { + return -1; + } +} + +/* RtMidiOut API */ +RtMidiOutPtr rtmidi_out_create_default () +{ + return new RtMidiOut (); +} + +RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName) +{ + std::string name = clientName; + return new RtMidiOut ((RtMidi::Api) api, name); +} + +void rtmidi_out_free (RtMidiOutPtr device) +{ + delete (RtMidiOut*) device; +} + +enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device) +{ + return (RtMidiApi) ((RtMidiOut*) device)->getCurrentApi (); +} + +int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length) +{ + try { + // FIXME: use allocator to achieve efficient buffering + std::vector *v = new std::vector (length); + memcpy (v->data (), message, length); + ((RtMidiOut*) device)->sendMessage (v); + delete v; + return 0; + } catch (...) { + return -1; + } +} diff --git a/rtmidi_c.h b/rtmidi_c.h new file mode 100644 index 0000000..6630c44 --- /dev/null +++ b/rtmidi_c.h @@ -0,0 +1,66 @@ + +#include + +#ifndef RTMIDI_C_H +#define RTMIDI_C_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* RtMidiPtr; +typedef void* RtMidiInPtr; +typedef void* RtMidiOutPtr; + + enum RtMidiApi { + RT_MIDI_API_UNSPECIFIED, /*!< Search for a working compiled API. */ + RT_MIDI_API_MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ + 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_WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ + RT_MIDI_API_RTMIDI_DUMMY /*!< A compilable but non-functional API. */ + }; + +enum RtMidiErrorType { + RT_ERROR_WARNING, RT_ERROR_DEBUG_WARNING, RT_ERROR_UNSPECIFIED, RT_ERROR_NO_DEVICES_FOUND, + RT_ERROR_INVALID_DEVICE, RT_ERROR_MEMORY_ERROR, RT_ERROR_INVALID_PARAMETER, RT_ERROR_INVALID_USE, + RT_ERROR_DRIVER_ERROR, RT_ERROR_SYSTEM_ERROR, RT_ERROR_THREAD_ERROR +}; + +typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message, void *userData); + +int rtmidi_sizeof_rtmidi_api (); + +/* RtMidi API */ +int rtmidi_get_compiled_api (enum RtMidiApi **apis); // return length for NULL argument. +void rtmidi_error (enum RtMidiErrorType type, const char* errorString); + +void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName); +void rtmidi_open_virtual_port (RtMidiPtr device, const char *portName); +void rtmidi_close_port (RtMidiPtr device); +unsigned int rtmidi_get_port_count (RtMidiPtr device); +const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber); + +/* RtMidiIn API */ +RtMidiInPtr rtmidi_in_create_default (); +RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsigned int queueSizeLimit); +void rtmidi_in_free (RtMidiInPtr device); +enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device); +void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData); +void rtmidi_in_cancel_callback (RtMidiInPtr device); +void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense); +double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message); + +/* RtMidiOut API */ +RtMidiOutPtr rtmidi_out_create_default (); +RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName); +void rtmidi_out_free (RtMidiOutPtr device); +enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device); +int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length); + + +#ifdef __cplusplus +} +#endif +#endif -- cgit v1.2.3