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