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