AAudioAudio.cpp revision a4eb0d86a29be2763be5fac51727858d5095794b
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AAudio"
18//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include <time.h>
22#include <pthread.h>
23
24#include <aaudio/AAudio.h>
25
26#include "AudioStreamBuilder.h"
27#include "AudioStream.h"
28#include "AudioClock.h"
29#include "client/AudioStreamInternal.h"
30#include "HandleTracker.h"
31
32using namespace aaudio;
33
34
35// Macros for common code that includes a return.
36// TODO Consider using do{}while(0) construct. I tried but it hung AndroidStudio
37#define CONVERT_BUILDER_HANDLE_OR_RETURN() \
38    convertAAudioBuilderToStreamBuilder(builder);
39
40#define COMMON_GET_FROM_BUILDER_OR_RETURN(resultPtr) \
41    CONVERT_BUILDER_HANDLE_OR_RETURN() \
42    if ((resultPtr) == nullptr) { \
43        return AAUDIO_ERROR_NULL; \
44    }
45
46#define AAUDIO_CASE_ENUM(name) case name: return #name
47
48AAUDIO_API const char * AAudio_convertResultToText(aaudio_result_t returnCode) {
49    switch (returnCode) {
50        AAUDIO_CASE_ENUM(AAUDIO_OK);
51        AAUDIO_CASE_ENUM(AAUDIO_ERROR_DISCONNECTED);
52        AAUDIO_CASE_ENUM(AAUDIO_ERROR_ILLEGAL_ARGUMENT);
53        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INCOMPATIBLE);
54        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INTERNAL);
55        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_STATE);
56        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNEXPECTED_STATE);
57        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNEXPECTED_VALUE);
58        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_HANDLE);
59        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_QUERY);
60        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNIMPLEMENTED);
61        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNAVAILABLE);
62        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_FREE_HANDLES);
63        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_MEMORY);
64        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NULL);
65        AAUDIO_CASE_ENUM(AAUDIO_ERROR_TIMEOUT);
66        AAUDIO_CASE_ENUM(AAUDIO_ERROR_WOULD_BLOCK);
67        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_FORMAT);
68        AAUDIO_CASE_ENUM(AAUDIO_ERROR_OUT_OF_RANGE);
69        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_SERVICE);
70        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_RATE);
71    }
72    return "Unrecognized AAudio error.";
73}
74
75AAUDIO_API const char * AAudio_convertStreamStateToText(aaudio_stream_state_t state) {
76    switch (state) {
77        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNINITIALIZED);
78        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNKNOWN);
79        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_OPEN);
80        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTING);
81        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTED);
82        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSING);
83        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSED);
84        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHING);
85        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHED);
86        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPING);
87        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPED);
88        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_DISCONNECTED);
89        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSING);
90        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSED);
91    }
92    return "Unrecognized AAudio state.";
93}
94
95#undef AAUDIO_CASE_ENUM
96
97static AudioStream *convertAAudioStreamToAudioStream(AAudioStream* stream)
98{
99    return (AudioStream*) stream;
100}
101
102static AudioStreamBuilder *convertAAudioBuilderToStreamBuilder(AAudioStreamBuilder* builder)
103{
104    return (AudioStreamBuilder*) builder;
105}
106
107AAUDIO_API aaudio_result_t AAudio_createStreamBuilder(AAudioStreamBuilder** builder)
108{
109    AudioStreamBuilder *audioStreamBuilder =  new AudioStreamBuilder();
110    if (audioStreamBuilder == nullptr) {
111        return AAUDIO_ERROR_NO_MEMORY;
112    }
113    *builder = (AAudioStreamBuilder*) audioStreamBuilder;
114    return AAUDIO_OK;
115}
116
117AAUDIO_API void AAudioStreamBuilder_setDeviceId(AAudioStreamBuilder* builder,
118                                                     int32_t deviceId)
119{
120    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
121    streamBuilder->setDeviceId(deviceId);
122}
123
124AAUDIO_API void AAudioStreamBuilder_setSampleRate(AAudioStreamBuilder* builder,
125                                              int32_t sampleRate)
126{
127    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
128    streamBuilder->setSampleRate(sampleRate);
129}
130
131AAUDIO_API void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder,
132                                                   int32_t samplesPerFrame)
133{
134    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
135    streamBuilder->setSamplesPerFrame(samplesPerFrame);
136}
137
138AAUDIO_API void AAudioStreamBuilder_setDirection(AAudioStreamBuilder* builder,
139                                             aaudio_direction_t direction)
140{
141    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
142    streamBuilder->setDirection(direction);
143}
144
145AAUDIO_API void AAudioStreamBuilder_setFormat(AAudioStreamBuilder* builder,
146                                                   aaudio_audio_format_t format)
147{
148    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
149    streamBuilder->setFormat(format);
150}
151
152AAUDIO_API void AAudioStreamBuilder_setSharingMode(AAudioStreamBuilder* builder,
153                                                        aaudio_sharing_mode_t sharingMode)
154{
155    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
156    streamBuilder->setSharingMode(sharingMode);
157}
158
159AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder,
160                                                        int32_t frames)
161{
162    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
163    streamBuilder->setBufferCapacity(frames);
164}
165
166AAUDIO_API void AAudioStreamBuilder_setDataCallback(AAudioStreamBuilder* builder,
167                                                    AAudioStream_dataCallback callback,
168                                                    void *userData)
169{
170    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
171    ALOGD("AAudioStreamBuilder_setCallback(): userData = %p", userData);
172    streamBuilder->setDataCallbackProc(callback);
173    streamBuilder->setDataCallbackUserData(userData);
174}
175AAUDIO_API void AAudioStreamBuilder_setErrorCallback(AAudioStreamBuilder* builder,
176                                                 AAudioStream_errorCallback callback,
177                                                 void *userData)
178{
179    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
180    ALOGD("AAudioStreamBuilder_setCallback(): userData = %p", userData);
181    streamBuilder->setErrorCallbackProc(callback);
182    streamBuilder->setErrorCallbackUserData(userData);
183}
184
185AAUDIO_API void AAudioStreamBuilder_setFramesPerDataCallback(AAudioStreamBuilder* builder,
186                                                int32_t frames)
187{
188    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
189    ALOGD("%s: frames = %d", __func__, frames);
190    streamBuilder->setFramesPerDataCallback(frames);
191}
192
193static aaudio_result_t  AAudioInternal_openStream(AudioStreamBuilder *streamBuilder,
194                                              AAudioStream** streamPtr)
195{
196    AudioStream *audioStream = nullptr;
197    aaudio_result_t result = streamBuilder->build(&audioStream);
198    if (result != AAUDIO_OK) {
199        return result;
200    } else {
201        *streamPtr = (AAudioStream*) audioStream;
202        return AAUDIO_OK;
203    }
204}
205
206AAUDIO_API aaudio_result_t  AAudioStreamBuilder_openStream(AAudioStreamBuilder* builder,
207                                                     AAudioStream** streamPtr)
208{
209    ALOGD("AAudioStreamBuilder_openStream(): builder = %p", builder);
210    AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr);
211    return AAudioInternal_openStream(streamBuilder, streamPtr);
212}
213
214AAUDIO_API aaudio_result_t  AAudioStreamBuilder_delete(AAudioStreamBuilder* builder)
215{
216    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
217    if (streamBuilder != nullptr) {
218        delete streamBuilder;
219        return AAUDIO_OK;
220    }
221    return AAUDIO_ERROR_INVALID_HANDLE;
222}
223
224AAUDIO_API aaudio_result_t  AAudioStream_close(AAudioStream* stream)
225{
226    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
227    ALOGD("AAudioStream_close(%p)", stream);
228    if (audioStream != nullptr) {
229        audioStream->close();
230        delete audioStream;
231        return AAUDIO_OK;
232    }
233    return AAUDIO_ERROR_INVALID_HANDLE;
234}
235
236AAUDIO_API aaudio_result_t  AAudioStream_requestStart(AAudioStream* stream)
237{
238    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
239    ALOGD("AAudioStream_requestStart(%p)", stream);
240    return audioStream->requestStart();
241}
242
243AAUDIO_API aaudio_result_t  AAudioStream_requestPause(AAudioStream* stream)
244{
245    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
246    ALOGD("AAudioStream_requestPause(%p)", stream);
247    return audioStream->requestPause();
248}
249
250AAUDIO_API aaudio_result_t  AAudioStream_requestFlush(AAudioStream* stream)
251{
252    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
253    ALOGD("AAudioStream_requestFlush(%p)", stream);
254    return audioStream->requestFlush();
255}
256
257AAUDIO_API aaudio_result_t  AAudioStream_requestStop(AAudioStream* stream)
258{
259    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
260    ALOGD("AAudioStream_requestStop(%p)", stream);
261    return audioStream->requestStop();
262}
263
264AAUDIO_API aaudio_result_t AAudioStream_waitForStateChange(AAudioStream* stream,
265                                            aaudio_stream_state_t inputState,
266                                            aaudio_stream_state_t *nextState,
267                                            int64_t timeoutNanoseconds)
268{
269
270    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
271    return audioStream->waitForStateChange(inputState, nextState, timeoutNanoseconds);
272}
273
274// ============================================================
275// Stream - non-blocking I/O
276// ============================================================
277
278AAUDIO_API aaudio_result_t AAudioStream_read(AAudioStream* stream,
279                               void *buffer,
280                               int32_t numFrames,
281                               int64_t timeoutNanoseconds)
282{
283    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
284    if (buffer == nullptr) {
285        return AAUDIO_ERROR_NULL;
286    }
287    if (numFrames < 0) {
288        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
289    } else if (numFrames == 0) {
290        return 0;
291    }
292
293    aaudio_result_t result = audioStream->read(buffer, numFrames, timeoutNanoseconds);
294    // ALOGD("AAudioStream_read(): read returns %d", result);
295
296    return result;
297}
298
299AAUDIO_API aaudio_result_t AAudioStream_write(AAudioStream* stream,
300                               const void *buffer,
301                               int32_t numFrames,
302                               int64_t timeoutNanoseconds)
303{
304    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
305    if (buffer == nullptr) {
306        return AAUDIO_ERROR_NULL;
307    }
308
309    // Don't allow writes when playing with a callback.
310    if (audioStream->getDataCallbackProc() != nullptr && audioStream->isPlaying()) {
311        ALOGE("Cannot write to a callback stream when running.");
312        return AAUDIO_ERROR_INVALID_STATE;
313    }
314
315    if (numFrames < 0) {
316        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
317    } else if (numFrames == 0) {
318        return 0;
319    }
320
321    aaudio_result_t result = audioStream->write(buffer, numFrames, timeoutNanoseconds);
322    // ALOGD("AAudioStream_write(): write returns %d", result);
323
324    return result;
325}
326
327// ============================================================
328// Miscellaneous
329// ============================================================
330
331AAUDIO_API aaudio_result_t AAudioStream_createThread(AAudioStream* stream,
332                                     int64_t periodNanoseconds,
333                                     aaudio_audio_thread_proc_t threadProc, void *arg)
334{
335    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
336    if (audioStream->getDataCallbackProc() != nullptr) {
337        return AAUDIO_ERROR_INCOMPATIBLE;
338    }
339    return audioStream->createThread(periodNanoseconds, threadProc, arg);
340}
341
342AAUDIO_API aaudio_result_t AAudioStream_joinThread(AAudioStream* stream,
343                                   void **returnArg,
344                                   int64_t timeoutNanoseconds)
345{
346    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
347    return audioStream->joinThread(returnArg, timeoutNanoseconds);
348}
349
350// ============================================================
351// Stream - queries
352// ============================================================
353
354AAUDIO_API int32_t AAudioStream_getSampleRate(AAudioStream* stream)
355{
356    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
357    return audioStream->getSampleRate();
358}
359
360AAUDIO_API int32_t AAudioStream_getSamplesPerFrame(AAudioStream* stream)
361{
362    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
363    return audioStream->getSamplesPerFrame();
364}
365
366AAUDIO_API aaudio_stream_state_t AAudioStream_getState(AAudioStream* stream)
367{
368    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
369    return audioStream->getState();
370}
371
372AAUDIO_API aaudio_audio_format_t AAudioStream_getFormat(AAudioStream* stream)
373{
374    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
375    return audioStream->getFormat();
376}
377
378AAUDIO_API aaudio_result_t AAudioStream_setBufferSizeInFrames(AAudioStream* stream,
379                                                int32_t requestedFrames)
380{
381    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
382    return audioStream->setBufferSize(requestedFrames);
383}
384
385AAUDIO_API int32_t AAudioStream_getBufferSizeInFrames(AAudioStream* stream)
386{
387    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
388    return audioStream->getBufferSize();
389}
390
391AAUDIO_API aaudio_direction_t AAudioStream_getDirection(AAudioStream* stream)
392{
393    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
394    return audioStream->getDirection();
395}
396
397AAUDIO_API int32_t AAudioStream_getFramesPerBurst(AAudioStream* stream)
398{
399    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
400    return audioStream->getFramesPerBurst();
401}
402
403AAUDIO_API int32_t AAudioStream_getFramesPerDataCallback(AAudioStream* stream)
404{
405    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
406    return audioStream->getFramesPerDataCallback();
407}
408
409AAUDIO_API int32_t AAudioStream_getBufferCapacityInFrames(AAudioStream* stream)
410{
411    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
412    return audioStream->getBufferCapacity();
413}
414
415AAUDIO_API int32_t AAudioStream_getXRunCount(AAudioStream* stream)
416{
417    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
418    return audioStream->getXRunCount();
419}
420
421AAUDIO_API int32_t AAudioStream_getDeviceId(AAudioStream* stream)
422{
423    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
424    return audioStream->getDeviceId();
425}
426
427AAUDIO_API aaudio_sharing_mode_t AAudioStream_getSharingMode(AAudioStream* stream)
428{
429    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
430    return audioStream->getSharingMode();
431}
432
433AAUDIO_API int64_t AAudioStream_getFramesWritten(AAudioStream* stream)
434{
435    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
436    return audioStream->getFramesWritten();
437}
438
439AAUDIO_API int64_t AAudioStream_getFramesRead(AAudioStream* stream)
440{
441    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
442    return audioStream->getFramesRead();
443}
444
445AAUDIO_API aaudio_result_t AAudioStream_getTimestamp(AAudioStream* stream,
446                                      clockid_t clockid,
447                                      int64_t *framePosition,
448                                      int64_t *timeNanoseconds)
449{
450    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
451    if (framePosition == nullptr) {
452        return AAUDIO_ERROR_NULL;
453    } else if (timeNanoseconds == nullptr) {
454        return AAUDIO_ERROR_NULL;
455    } else if (clockid != CLOCK_MONOTONIC && clockid != CLOCK_BOOTTIME) {
456        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
457    }
458
459    return audioStream->getTimestamp(clockid, framePosition, timeNanoseconds);
460}
461