You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
7.9KB

  1. #include "rtaudio_c.h"
  2. #include "RtAudio.h"
  3. #include <cstring>
  4. #define MAX_ERROR_MESSAGE_LENGTH 512
  5. struct rtaudio {
  6. RtAudio *audio;
  7. rtaudio_cb_t cb;
  8. void *userdata;
  9. int has_error;
  10. char errmsg[MAX_ERROR_MESSAGE_LENGTH];
  11. };
  12. static const rtaudio_api_t compiled_api[] = {
  13. #if defined(__UNIX_JACK__)
  14. RTAUDIO_API_UNIX_JACK,
  15. #endif
  16. #if defined(__LINUX_ALSA__)
  17. RTAUDIO_API_LINUX_ALSA,
  18. #endif
  19. #if defined(__LINUX_PULSE__)
  20. RTAUDIO_API_LINUX_PULSE,
  21. #endif
  22. #if defined(__LINUX_OSS__)
  23. RTAUDIO_API_LINUX_OSS,
  24. #endif
  25. #if defined(__WINDOWS_ASIO__)
  26. RTAUDIO_API_WINDOWS_ASIO,
  27. #endif
  28. #if defined(__WINDOWS_WASAPI__)
  29. RTAUDIO_API_WINDOWS_WASAPI,
  30. #endif
  31. #if defined(__WINDOWS_DS__)
  32. RTAUDIO_API_WINDOWS_DS,
  33. #endif
  34. #if defined(__MACOSX_CORE__)
  35. RTAUDIO_API_MACOSX_CORE,
  36. #endif
  37. #if defined(__RTAUDIO_DUMMY__)
  38. RTAUDIO_API_DUMMY,
  39. #endif
  40. RTAUDIO_API_UNSPECIFIED,
  41. };
  42. const char *rtaudio_version() { return RTAUDIO_VERSION; }
  43. const rtaudio_api_t *rtaudio_compiled_api() { return compiled_api; }
  44. const char *rtaudio_compiled_api_name(rtaudio_api_t api) {
  45. const std::string &name = RtAudio::getCompiledApiName((RtAudio::Api)api);
  46. return name.empty() ? NULL : name.c_str();
  47. }
  48. const char *rtaudio_compiled_api_display_name(rtaudio_api_t api)
  49. {
  50. const std::string &name = RtAudio::getCompiledApiDisplayName((RtAudio::Api)api);
  51. return name.empty() ? NULL : name.c_str();
  52. }
  53. rtaudio_api_t rtaudio_compiled_api_by_name(const char *name) {
  54. RtAudio::Api api = RtAudio::UNSPECIFIED;
  55. if (name) {
  56. api = RtAudio::getCompiledApiByName(name);
  57. }
  58. return (rtaudio_api_t)api;
  59. }
  60. const char *rtaudio_error(rtaudio_t audio) {
  61. if (audio->has_error) {
  62. return audio->errmsg;
  63. }
  64. return NULL;
  65. }
  66. rtaudio_t rtaudio_create(rtaudio_api_t api) {
  67. rtaudio_t audio = new struct rtaudio();
  68. try {
  69. audio->audio = new RtAudio((RtAudio::Api)api);
  70. } catch (RtAudioError &err) {
  71. audio->has_error = 1;
  72. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  73. }
  74. return audio;
  75. }
  76. void rtaudio_destroy(rtaudio_t audio) { delete audio->audio; }
  77. rtaudio_api_t rtaudio_current_api(rtaudio_t audio) {
  78. return (rtaudio_api_t)audio->audio->getCurrentApi();
  79. }
  80. int rtaudio_device_count(rtaudio_t audio) {
  81. return audio->audio->getDeviceCount();
  82. }
  83. rtaudio_device_info_t rtaudio_get_device_info(rtaudio_t audio, int i) {
  84. rtaudio_device_info_t result;
  85. std::memset(&result, 0, sizeof(result));
  86. try {
  87. audio->has_error = 0;
  88. RtAudio::DeviceInfo info = audio->audio->getDeviceInfo(i);
  89. result.probed = info.probed;
  90. result.output_channels = info.outputChannels;
  91. result.input_channels = info.inputChannels;
  92. result.duplex_channels = info.duplexChannels;
  93. result.is_default_output = info.isDefaultOutput;
  94. result.is_default_input = info.isDefaultInput;
  95. result.native_formats = info.nativeFormats;
  96. result.preferred_sample_rate = info.preferredSampleRate;
  97. strncpy(result.name, info.name.c_str(), sizeof(result.name) - 1);
  98. for (unsigned int j = 0; j < info.sampleRates.size(); j++) {
  99. if (j < sizeof(result.sample_rates) / sizeof(result.sample_rates[0])) {
  100. result.sample_rates[j] = info.sampleRates[j];
  101. }
  102. }
  103. } catch (RtAudioError &err) {
  104. audio->has_error = 1;
  105. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  106. }
  107. return result;
  108. }
  109. unsigned int rtaudio_get_default_output_device(rtaudio_t audio) {
  110. return audio->audio->getDefaultOutputDevice();
  111. }
  112. unsigned int rtaudio_get_default_input_device(rtaudio_t audio) {
  113. return audio->audio->getDefaultInputDevice();
  114. }
  115. static int proxy_cb_func(void *out, void *in, unsigned int nframes, double time,
  116. RtAudioStreamStatus status, void *userdata) {
  117. rtaudio_t audio = (rtaudio_t)userdata;
  118. return audio->cb(out, in, nframes, time, (rtaudio_stream_status_t)status,
  119. audio->userdata);
  120. }
  121. int rtaudio_open_stream(rtaudio_t audio,
  122. rtaudio_stream_parameters_t *output_params,
  123. rtaudio_stream_parameters_t *input_params,
  124. rtaudio_format_t format, unsigned int sample_rate,
  125. unsigned int *buffer_frames, rtaudio_cb_t cb,
  126. void *userdata, rtaudio_stream_options_t *options,
  127. rtaudio_error_cb_t /*errcb*/) {
  128. try {
  129. audio->has_error = 0;
  130. RtAudio::StreamParameters *in = NULL;
  131. RtAudio::StreamParameters *out = NULL;
  132. RtAudio::StreamOptions *opts = NULL;
  133. RtAudio::StreamParameters inparams;
  134. RtAudio::StreamParameters outparams;
  135. RtAudio::StreamOptions stream_opts;
  136. if (input_params != NULL) {
  137. inparams.deviceId = input_params->device_id;
  138. inparams.nChannels = input_params->num_channels;
  139. inparams.firstChannel = input_params->first_channel;
  140. in = &inparams;
  141. }
  142. if (output_params != NULL) {
  143. outparams.deviceId = output_params->device_id;
  144. outparams.nChannels = output_params->num_channels;
  145. outparams.firstChannel = output_params->first_channel;
  146. out = &outparams;
  147. }
  148. if (options != NULL) {
  149. stream_opts.flags = (RtAudioStreamFlags)options->flags;
  150. stream_opts.numberOfBuffers = options->num_buffers;
  151. stream_opts.priority = options->priority;
  152. if (strlen(options->name) > 0) {
  153. stream_opts.streamName = std::string(options->name);
  154. }
  155. opts = &stream_opts;
  156. }
  157. audio->cb = cb;
  158. audio->userdata = userdata;
  159. audio->audio->openStream(out, in, (RtAudioFormat)format, sample_rate,
  160. buffer_frames, proxy_cb_func, (void *)audio, opts,
  161. NULL);
  162. return 0;
  163. } catch (RtAudioError &err) {
  164. audio->has_error = 1;
  165. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  166. return -1;
  167. }
  168. }
  169. void rtaudio_close_stream(rtaudio_t audio) { audio->audio->closeStream(); }
  170. int rtaudio_start_stream(rtaudio_t audio) {
  171. try {
  172. audio->has_error = 0;
  173. audio->audio->startStream();
  174. } catch (RtAudioError &err) {
  175. audio->has_error = 1;
  176. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  177. }
  178. return 0;
  179. }
  180. int rtaudio_stop_stream(rtaudio_t audio) {
  181. try {
  182. audio->has_error = 0;
  183. audio->audio->stopStream();
  184. } catch (RtAudioError &err) {
  185. audio->has_error = 1;
  186. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  187. }
  188. return 0;
  189. }
  190. int rtaudio_abort_stream(rtaudio_t audio) {
  191. try {
  192. audio->has_error = 0;
  193. audio->audio->abortStream();
  194. } catch (RtAudioError &err) {
  195. audio->has_error = 1;
  196. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  197. }
  198. return 0;
  199. }
  200. int rtaudio_is_stream_open(rtaudio_t audio) {
  201. return !!audio->audio->isStreamOpen();
  202. }
  203. int rtaudio_is_stream_running(rtaudio_t audio) {
  204. return !!audio->audio->isStreamRunning();
  205. }
  206. double rtaudio_get_stream_time(rtaudio_t audio) {
  207. try {
  208. audio->has_error = 0;
  209. return audio->audio->getStreamTime();
  210. } catch (RtAudioError &err) {
  211. audio->has_error = 1;
  212. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  213. return 0;
  214. }
  215. }
  216. void rtaudio_set_stream_time(rtaudio_t audio, double time) {
  217. try {
  218. audio->has_error = 0;
  219. audio->audio->setStreamTime(time);
  220. } catch (RtAudioError &err) {
  221. audio->has_error = 1;
  222. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  223. }
  224. }
  225. int rtaudio_get_stream_latency(rtaudio_t audio) {
  226. try {
  227. audio->has_error = 0;
  228. return audio->audio->getStreamLatency();
  229. } catch (RtAudioError &err) {
  230. audio->has_error = 1;
  231. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  232. return -1;
  233. }
  234. }
  235. unsigned int rtaudio_get_stream_sample_rate(rtaudio_t audio) {
  236. try {
  237. return audio->audio->getStreamSampleRate();
  238. } catch (RtAudioError &err) {
  239. audio->has_error = 1;
  240. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  241. return -1;
  242. }
  243. }
  244. void rtaudio_show_warnings(rtaudio_t audio, int show) {
  245. audio->audio->showWarnings(!!show);
  246. }