Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add C API.
  • Loading branch information
atsushieno committed Aug 29, 2015
1 parent 28321c0 commit a5c375c
Show file tree
Hide file tree
Showing 4 changed files with 254 additions and 1 deletion.
4 changes: 3 additions & 1 deletion Makefile.am
Expand Up @@ -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
8 changes: 8 additions & 0 deletions msw/rtmidilib.vcproj
Expand Up @@ -151,6 +151,10 @@
RelativePath="..\RtMidi.cpp"
>
</File>
<File
RelativePath="..\rtmidi_c.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Expand All @@ -165,6 +169,10 @@
RelativePath="..\RtMidi.h"
>
</File>
<File
RelativePath="..\rtmidi_c.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Expand Down
177 changes: 177 additions & 0 deletions rtmidi_c.cpp
@@ -0,0 +1,177 @@
#include <string.h>
#include <stdlib.h>
#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<RtMidi::Api> *v = new std::vector<RtMidi::Api> ();
try {
RtMidi::getCompiledApi (*v);
int size = v->size ();
delete v;
return size;
} catch (...) {
return -1;
}
} else {
try {
std::vector<RtMidi::Api> *v = new std::vector<RtMidi::Api> ();
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<unsigned char> *message, void *userData)
{
CallbackProxyUserData* data = reinterpret_cast<CallbackProxyUserData*> (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<unsigned char> *v = new std::vector<unsigned char> ();
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<unsigned char> *v = new std::vector<unsigned char> (length);
memcpy (v->data (), message, length);
((RtMidiOut*) device)->sendMessage (v);
delete v;
return 0;
} catch (...) {
return -1;
}
}
66 changes: 66 additions & 0 deletions rtmidi_c.h
@@ -0,0 +1,66 @@

#include <stdbool.h>

#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

0 comments on commit a5c375c

Please sign in to comment.