add rtaudio c api wrappers (#98)
authorSerge Zaitsev <zaitsev.serge@gmail.com>
Mon, 2 Oct 2017 13:20:13 +0000 (16:20 +0300)
committerStephen Sinclair <radarsat1@users.noreply.github.com>
Mon, 2 Oct 2017 13:20:13 +0000 (10:20 -0300)
add rtaudio c api wrappers

CMakeLists.txt
Makefile.am
rtaudio_c.cpp [new file with mode: 0644]
rtaudio_c.h [new file with mode: 0644]

index 812d4d307666e7fa9ab37ccc6de609f19d36e6d5..54f8816966122093393af3ae5afe7cc059c4c069 100644 (file)
@@ -28,7 +28,7 @@ if (CMAKE_COMPILER_IS_GNUCXX)
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
 endif (CMAKE_COMPILER_IS_GNUCXX)
 
-set(rtaudio_SOURCES RtAudio.cpp)
+set(rtaudio_SOURCES RtAudio.cpp rtaudio_c.cpp)
 
 set(LINKLIBS)
 if (CMAKE_SYSTEM_NAME MATCHES "kNetBSD.*|NetBSD.*")
index 00927e8b17068784db2035b2620bf511f15bd312..d4fa5388361718af0886ece6673a008067f99564 100644 (file)
@@ -6,11 +6,13 @@ endif
 lib_LTLIBRARIES = %D%/librtaudio.la
 %C%_librtaudio_la_LDFLAGS = -no-undefined -export-dynamic -version-info @SO_VERSION@
 %C%_librtaudio_la_SOURCES = \
-  %D%/RtAudio.cpp
+  %D%/RtAudio.cpp \
+  %D%/rtaudio_c.cpp
 
 rtaudio_incdir = $(includedir)/rtaudio
 rtaudio_inc_HEADERS = \
-  %D%/RtAudio.h
+  %D%/RtAudio.h \
+  %D%/rtaudio_c.h
 
 pkgconfigdatadir = $(libdir)/pkgconfig
 pkgconfigdata_DATA = rtaudio.pc
diff --git a/rtaudio_c.cpp b/rtaudio_c.cpp
new file mode 100644 (file)
index 0000000..090cbf9
--- /dev/null
@@ -0,0 +1,261 @@
+#include "rtaudio_c.h"
+#include "RtAudio.h"
+
+#include <cstring>
+
+#define MAX_ERROR_MESSAGE_LENGTH 512
+
+struct rtaudio {
+  RtAudio *audio;
+
+  rtaudio_cb_t cb;
+  void *userdata;
+
+  int has_error;
+  char errmsg[MAX_ERROR_MESSAGE_LENGTH];
+};
+
+static const rtaudio_api_t compiled_api[] = {
+#if defined(__UNIX_JACK__)
+    RTAUDIO_API_UNIX_JACK,
+#endif
+#if defined(__LINUX_ALSA__)
+    RTAUDIO_API_LINUX_ALSA,
+#endif
+#if defined(__LINUX_PULSE__)
+    RTAUDIO_API_LINUX_PULSE,
+#endif
+#if defined(__LINUX_OSS__)
+    RTAUDIO_API_LINUX_OSS,
+#endif
+#if defined(__WINDOWS_ASIO__)
+    RTAUDIO_API_WINDOWS_ASIO,
+#endif
+#if defined(__WINDOWS_WASAPI__)
+    RTAUDIO_API_WINDOWS_WASAPI,
+#endif
+#if defined(__WINDOWS_DS__)
+    RTAUDIO_API_WINDOWS_DS,
+#endif
+#if defined(__MACOSX_CORE__)
+    RTAUDIO_API_MACOSX_CORE,
+#endif
+#if defined(__RTAUDIO_DUMMY__)
+    RTAUDIO_API_DUMMY,
+#endif
+    RTAUDIO_API_UNSPECIFIED,
+};
+
+const char *rtaudio_version() { return RTAUDIO_VERSION; }
+
+const rtaudio_api_t *rtaudio_compiled_api() { return compiled_api; }
+
+const char *rtaudio_error(rtaudio_t audio) {
+  if (audio->has_error) {
+    return audio->errmsg;
+  }
+  return NULL;
+}
+
+rtaudio_t rtaudio_create(rtaudio_api_t api) {
+  rtaudio_t audio = new struct rtaudio();
+  try {
+    audio->audio = new RtAudio((RtAudio::Api)api);
+  } catch (RtAudioError &err) {
+    audio->has_error = 1;
+    strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
+  }
+  return audio;
+}
+
+void rtaudio_destroy(rtaudio_t audio) { delete audio->audio; }
+
+rtaudio_api_t rtaudio_current_api(rtaudio_t audio) {
+  return (rtaudio_api_t)audio->audio->getCurrentApi();
+}
+
+int rtaudio_device_count(rtaudio_t audio) {
+  return audio->audio->getDeviceCount();
+}
+
+rtaudio_device_info_t rtaudio_get_device_info(rtaudio_t audio, int i) {
+  rtaudio_device_info_t result = {};
+  try {
+    audio->has_error = 0;
+    RtAudio::DeviceInfo info = audio->audio->getDeviceInfo(i);
+    result.probed = info.probed;
+    result.output_channels = info.outputChannels;
+    result.input_channels = info.inputChannels;
+    result.duplex_channels = info.duplexChannels;
+    result.is_default_output = info.isDefaultOutput;
+    result.is_default_input = info.isDefaultInput;
+    result.native_formats = info.nativeFormats;
+    result.preferred_sample_rate = info.preferredSampleRate;
+    strncpy(result.name, info.name.c_str(), sizeof(result.name) - 1);
+    for (unsigned int j = 0; j < info.sampleRates.size(); j++) {
+      if (j < sizeof(result.sample_rates) / sizeof(result.sample_rates[0])) {
+        result.sample_rates[j] = info.sampleRates[j];
+      }
+    }
+  } catch (RtAudioError &err) {
+    audio->has_error = 1;
+    strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
+  }
+  return result;
+}
+
+unsigned int rtaudio_get_default_output_device(rtaudio_t audio) {
+  return audio->audio->getDefaultOutputDevice();
+}
+
+unsigned int rtaudio_get_default_input_device(rtaudio_t audio) {
+  return audio->audio->getDefaultInputDevice();
+}
+
+static int proxy_cb_func(void *out, void *in, unsigned int nframes, double time,
+                         RtAudioStreamStatus status, void *userdata) {
+  rtaudio_t audio = (rtaudio_t)userdata;
+  return audio->cb(out, in, nframes, time, (rtaudio_stream_status_t)status,
+                   audio->userdata);
+}
+
+int rtaudio_open_stream(rtaudio_t audio,
+                        rtaudio_stream_parameters_t *output_params,
+                        rtaudio_stream_parameters_t *input_params,
+                        rtaudio_format_t format, unsigned int sample_rate,
+                        unsigned int *buffer_frames, rtaudio_cb_t cb,
+                        void *userdata, rtaudio_stream_options_t *options,
+                        rtaudio_error_cb_t /*errcb*/) {
+  try {
+    audio->has_error = 0;
+    RtAudio::StreamParameters *in = NULL;
+    RtAudio::StreamParameters *out = NULL;
+    RtAudio::StreamOptions *opts = NULL;
+
+    RtAudio::StreamParameters inparams;
+    RtAudio::StreamParameters outparams;
+    RtAudio::StreamOptions stream_opts;
+
+    if (input_params != NULL) {
+      inparams.deviceId = input_params->device_id;
+      inparams.nChannels = input_params->num_channels;
+      inparams.firstChannel = input_params->first_channel;
+      in = &inparams;
+    }
+    if (output_params != NULL) {
+      outparams.deviceId = output_params->device_id;
+      outparams.nChannels = output_params->num_channels;
+      outparams.firstChannel = output_params->first_channel;
+      out = &outparams;
+    }
+
+    if (options != NULL) {
+      stream_opts.flags = (RtAudioStreamFlags)options->flags;
+      stream_opts.numberOfBuffers = options->num_buffers;
+      stream_opts.priority = options->priority;
+      if (strlen(options->name) > 0) {
+        stream_opts.streamName = std::string(options->name);
+      }
+      opts = &stream_opts;
+    }
+    audio->cb = cb;
+    audio->userdata = userdata;
+    audio->audio->openStream(out, in, (RtAudioFormat)format, sample_rate,
+                             buffer_frames, proxy_cb_func, (void *)audio, opts,
+                             NULL);
+    return 0;
+  } catch (RtAudioError &err) {
+    audio->has_error = 1;
+    strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
+    return -1;
+  }
+}
+
+void rtaudio_close_stream(rtaudio_t audio) { audio->audio->closeStream(); }
+
+int rtaudio_start_stream(rtaudio_t audio) {
+  try {
+    audio->has_error = 0;
+    audio->audio->startStream();
+  } catch (RtAudioError &err) {
+    audio->has_error = 1;
+    strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
+  }
+  return 0;
+}
+
+int rtaudio_stop_stream(rtaudio_t audio) {
+  try {
+    audio->has_error = 0;
+    audio->audio->stopStream();
+  } catch (RtAudioError &err) {
+    audio->has_error = 1;
+    strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
+  }
+  return 0;
+}
+
+int rtaudio_abort_stream(rtaudio_t audio) {
+  try {
+    audio->has_error = 0;
+    audio->audio->abortStream();
+  } catch (RtAudioError &err) {
+    audio->has_error = 1;
+    strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
+  }
+  return 0;
+}
+
+int rtaudio_is_stream_open(rtaudio_t audio) {
+  return !!audio->audio->isStreamOpen();
+}
+
+int rtaudio_is_stream_running(rtaudio_t audio) {
+  return !!audio->audio->isStreamRunning();
+}
+
+double rtaudio_get_stream_time(rtaudio_t audio) {
+  try {
+    audio->has_error = 0;
+    return audio->audio->getStreamTime();
+  } catch (RtAudioError &err) {
+    audio->has_error = 1;
+    strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
+    return 0;
+  }
+}
+
+void rtaudio_set_stream_time(rtaudio_t audio, double time) {
+  try {
+    audio->has_error = 0;
+    audio->audio->setStreamTime(time);
+  } catch (RtAudioError &err) {
+    audio->has_error = 1;
+    strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
+  }
+}
+
+int rtaudio_get_stream_latency(rtaudio_t audio) {
+  try {
+    audio->has_error = 0;
+    return audio->audio->getStreamLatency();
+  } catch (RtAudioError &err) {
+    audio->has_error = 1;
+    strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
+    return -1;
+  }
+}
+
+unsigned int rtaudio_get_stream_sample_rate(rtaudio_t audio) {
+  try {
+    return audio->audio->getStreamSampleRate();
+  } catch (RtAudioError &err) {
+    audio->has_error = 1;
+    strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
+    return -1;
+  }
+}
+
+void rtaudio_show_warnings(rtaudio_t audio, int show) {
+  audio->audio->showWarnings(!!show);
+}
diff --git a/rtaudio_c.h b/rtaudio_c.h
new file mode 100644 (file)
index 0000000..d92107e
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef RTAUDIO_C_H
+#define RTAUDIO_C_H
+
+#if defined(RTAUDIO_EXPORT)
+#define RTAUDIOAPI __declspec(dllexport)
+#else
+#define RTAUDIOAPI //__declspec(dllimport)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned long rtaudio_format_t;
+
+#define RTAUDIO_FORMAT_SINT8 0x01
+#define RTAUDIO_FORMAT_SINT16 0x02
+#define RTAUDIO_FORMAT_SINT24 0x04
+#define RTAUDIO_FORMAT_SINT32 0x08
+#define RTAUDIO_FORMAT_FLOAT32 0x10
+#define RTAUDIO_FORMAT_FLOAT64 0x20
+
+typedef unsigned int rtaudio_stream_flags_t;
+
+#define RTAUDIO_FLAGS_NONINTERLEAVED 0x1
+#define RTAUDIO_FLAGS_MINIMIZE_LATENCY 0x2
+#define RTAUDIO_FLAGS_HOG_DEVICE 0x4
+#define RTAUDIO_FLAGS_SCHEDULE_REALTIME 0x8
+#define RTAUDIO_FLAGS_ALSA_USE_DEFAULT 0x10
+
+typedef unsigned int rtaudio_stream_status_t;
+
+#define RTAUDIO_STATUS_INPUT_OVERFLOW 0x1
+#define RTAUDIO_STATUS_OUTPUT_UNDERFLOW 0x2
+
+typedef int (*rtaudio_cb_t)(void *out, void *in, unsigned int nFrames,
+                            double stream_time, rtaudio_stream_status_t status,
+                            void *userdata);
+
+typedef enum rtaudio_error {
+  RTAUDIO_ERROR_WARNING,
+  RTAUDIO_ERROR_DEBUG_WARNING,
+  RTAUDIO_ERROR_UNSPECIFIED,
+  RTAUDIO_ERROR_NO_DEVICES_FOUND,
+  RTAUDIO_ERROR_INVALID_DEVICE,
+  RTAUDIO_ERROR_MEMORY_ERROR,
+  RTAUDIO_ERROR_INVALID_PARAMETER,
+  RTAUDIO_ERROR_INVALID_USE,
+  RTAUDIO_ERROR_DRIVER_ERROR,
+  RTAUDIO_ERROR_SYSTEM_ERROR,
+  RTAUDIO_ERROR_THREAD_ERROR,
+} rtaudio_error_t;
+
+typedef void (*rtaudio_error_cb_t)(rtaudio_error_t err, const char *msg);
+
+typedef enum rtaudio_api {
+  RTAUDIO_API_UNSPECIFIED,
+  RTAUDIO_API_LINUX_ALSA,
+  RTAUDIO_API_LINUX_PULSE,
+  RTAUDIO_API_LINUX_OSS,
+  RTAUDIO_API_UNIX_JACK,
+  RTAUDIO_API_MACOSX_CORE,
+  RTAUDIO_API_WINDOWS_WASAPI,
+  RTAUDIO_API_WINDOWS_ASIO,
+  RTAUDIO_API_WINDOWS_DS,
+  RTAUDIO_API_DUMMY,
+} rtaudio_api_t;
+
+#define NUM_SAMPLE_RATES 16
+#define MAX_NAME_LENGTH 512
+typedef struct rtaudio_device_info {
+  int probed;
+  unsigned int output_channels;
+  unsigned int input_channels;
+  unsigned int duplex_channels;
+
+  int is_default_output;
+  int is_default_input;
+
+  rtaudio_format_t native_formats;
+
+  unsigned int preferred_sample_rate;
+  int sample_rates[NUM_SAMPLE_RATES];
+
+  char name[MAX_NAME_LENGTH];
+} rtaudio_device_info_t;
+
+typedef struct rtaudio_stream_parameters {
+  unsigned int device_id;
+  unsigned int num_channels;
+  unsigned int first_channel;
+} rtaudio_stream_parameters_t;
+
+typedef struct rtaudio_stream_options {
+  rtaudio_stream_flags_t flags;
+  unsigned int num_buffers;
+  int priority;
+  char name[MAX_NAME_LENGTH];
+} rtaudio_stream_options_t;
+
+typedef struct rtaudio *rtaudio_t;
+
+RTAUDIOAPI const char *rtaudio_version();
+RTAUDIOAPI const rtaudio_api_t *rtaudio_compiled_api();
+
+RTAUDIOAPI const char *rtaudio_error(rtaudio_t audio);
+
+RTAUDIOAPI rtaudio_t rtaudio_create(rtaudio_api_t api);
+RTAUDIOAPI void rtaudio_destroy(rtaudio_t audio);
+
+RTAUDIOAPI rtaudio_api_t rtaudio_current_api(rtaudio_t audio);
+
+RTAUDIOAPI int rtaudio_device_count(rtaudio_t audio);
+RTAUDIOAPI rtaudio_device_info_t rtaudio_get_device_info(rtaudio_t audio,
+                                                         int i);
+RTAUDIOAPI unsigned int rtaudio_get_default_output_device(rtaudio_t audio);
+RTAUDIOAPI unsigned int rtaudio_get_default_input_device(rtaudio_t audio);
+
+RTAUDIOAPI int
+rtaudio_open_stream(rtaudio_t audio, rtaudio_stream_parameters_t *output_params,
+                    rtaudio_stream_parameters_t *input_params,
+                    rtaudio_format_t format, unsigned int sample_rate,
+                    unsigned int *buffer_frames, rtaudio_cb_t cb,
+                    void *userdata, rtaudio_stream_options_t *options,
+                    rtaudio_error_cb_t errcb);
+RTAUDIOAPI void rtaudio_close_stream(rtaudio_t audio);
+RTAUDIOAPI int rtaudio_start_stream(rtaudio_t audio);
+RTAUDIOAPI int rtaudio_stop_stream(rtaudio_t audio);
+RTAUDIOAPI int rtaudio_abort_stream(rtaudio_t audio);
+
+RTAUDIOAPI int rtaudio_is_stream_open(rtaudio_t audio);
+RTAUDIOAPI int rtaudio_is_stream_running(rtaudio_t audio);
+
+RTAUDIOAPI double rtaudio_get_stream_time(rtaudio_t audio);
+RTAUDIOAPI void rtaudio_set_stream_time(rtaudio_t audio, double time);
+RTAUDIOAPI int rtaudio_get_stream_latency(rtaudio_t audio);
+RTAUDIOAPI unsigned int rtaudio_get_stream_sample_rate(rtaudio_t audio);
+
+RTAUDIOAPI void rtaudio_show_warnings(rtaudio_t audio, int show);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* RTAUDIO_C_H */