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