AAudioAudio.cpp revision f53e613b3dedab3ecada2c93d8846233c442d129
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/AAudioDefinitions.h>
25#include <aaudio/AAudio.h>
26
27#include "AudioStreamBuilder.h"
28#include "AudioStream.h"
29#include "AudioClock.h"
30#include "client/AudioStreamInternal.h"
31#include "HandleTracker.h"
32
33using namespace aaudio;
34
35// This is not the maximum theoretic possible number of handles that the HandlerTracker
36// class could support; instead it is the maximum number of handles that we are configuring
37// for our HandleTracker instance (sHandleTracker).
38#define AAUDIO_MAX_HANDLES  64
39
40// Macros for common code that includes a return.
41// TODO Consider using do{}while(0) construct. I tried but it hung AndroidStudio
42#define CONVERT_BUILDER_HANDLE_OR_RETURN() \
43    convertAAudioBuilderToStreamBuilder(builder); \
44    if (streamBuilder == nullptr) { \
45        return AAUDIO_ERROR_INVALID_HANDLE; \
46    }
47
48#define COMMON_GET_FROM_BUILDER_OR_RETURN(resultPtr) \
49    CONVERT_BUILDER_HANDLE_OR_RETURN() \
50    if ((resultPtr) == nullptr) { \
51        return AAUDIO_ERROR_NULL; \
52    }
53
54#define CONVERT_STREAM_HANDLE_OR_RETURN() \
55    convertAAudioStreamToAudioStream(stream); \
56    if (audioStream == nullptr) { \
57        return AAUDIO_ERROR_INVALID_HANDLE; \
58    }
59
60#define COMMON_GET_FROM_STREAM_OR_RETURN(resultPtr) \
61    CONVERT_STREAM_HANDLE_OR_RETURN(); \
62    if ((resultPtr) == nullptr) { \
63        return AAUDIO_ERROR_NULL; \
64    }
65
66// Static data.
67// TODO static constructors are discouraged, alternatives?
68static HandleTracker sHandleTracker(AAUDIO_MAX_HANDLES);
69
70typedef enum
71{
72    AAUDIO_HANDLE_TYPE_STREAM,
73    AAUDIO_HANDLE_TYPE_STREAM_BUILDER,
74    AAUDIO_HANDLE_TYPE_COUNT
75} aaudio_handle_type_t;
76static_assert(AAUDIO_HANDLE_TYPE_COUNT <= HANDLE_TRACKER_MAX_TYPES, "Too many handle types.");
77
78
79#define AAUDIO_CASE_ENUM(name) case name: return #name
80
81AAUDIO_API const char * AAudio_convertResultToText(aaudio_result_t returnCode) {
82    switch (returnCode) {
83        AAUDIO_CASE_ENUM(AAUDIO_OK);
84        AAUDIO_CASE_ENUM(AAUDIO_ERROR_ILLEGAL_ARGUMENT);
85        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INCOMPATIBLE);
86        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INTERNAL);
87        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_STATE);
88        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_HANDLE);
89        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_QUERY);
90        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNIMPLEMENTED);
91        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNAVAILABLE);
92        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_FREE_HANDLES);
93        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_MEMORY);
94        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NULL);
95        AAUDIO_CASE_ENUM(AAUDIO_ERROR_TIMEOUT);
96        AAUDIO_CASE_ENUM(AAUDIO_ERROR_WOULD_BLOCK);
97        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_ORDER);
98        AAUDIO_CASE_ENUM(AAUDIO_ERROR_OUT_OF_RANGE);
99        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_SERVICE);
100    }
101    return "Unrecognized AAudio error.";
102}
103
104AAUDIO_API const char * AAudio_convertStreamStateToText(aaudio_stream_state_t state) {
105    switch (state) {
106        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNINITIALIZED);
107        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_OPEN);
108        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTING);
109        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTED);
110        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSING);
111        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSED);
112        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHING);
113        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHED);
114        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPING);
115        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPED);
116        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSING);
117        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSED);
118    }
119    return "Unrecognized AAudio state.";
120}
121
122#undef AAUDIO_CASE_ENUM
123
124static AudioStream *convertAAudioStreamToAudioStream(AAudioStream stream)
125{
126    return (AudioStream *) sHandleTracker.get(AAUDIO_HANDLE_TYPE_STREAM,
127                                              (aaudio_handle_t) stream);
128}
129
130static AudioStreamBuilder *convertAAudioBuilderToStreamBuilder(AAudioStreamBuilder builder)
131{
132    return (AudioStreamBuilder *) sHandleTracker.get(AAUDIO_HANDLE_TYPE_STREAM_BUILDER,
133                                                     (aaudio_handle_t) builder);
134}
135
136AAUDIO_API aaudio_result_t AAudio_createStreamBuilder(AAudioStreamBuilder *builder)
137{
138    ALOGD("AAudio_createStreamBuilder(): check sHandleTracker.isInitialized ()");
139    if (!sHandleTracker.isInitialized()) {
140        return AAUDIO_ERROR_NO_MEMORY;
141    }
142    AudioStreamBuilder *audioStreamBuilder =  new AudioStreamBuilder();
143    if (audioStreamBuilder == nullptr) {
144        return AAUDIO_ERROR_NO_MEMORY;
145    }
146    ALOGD("AAudio_createStreamBuilder(): created AudioStreamBuilder = %p", audioStreamBuilder);
147    // TODO protect the put() with a Mutex
148    AAudioStreamBuilder handle = sHandleTracker.put(AAUDIO_HANDLE_TYPE_STREAM_BUILDER,
149            audioStreamBuilder);
150    if (handle < 0) {
151        delete audioStreamBuilder;
152        return static_cast<aaudio_result_t>(handle);
153    } else {
154        *builder = handle;
155    }
156    return AAUDIO_OK;
157}
158
159AAUDIO_API aaudio_result_t AAudioStreamBuilder_setDeviceId(AAudioStreamBuilder builder,
160                                                     aaudio_device_id_t deviceId)
161{
162    AudioStreamBuilder *streamBuilder = CONVERT_BUILDER_HANDLE_OR_RETURN();
163    streamBuilder->setDeviceId(deviceId);
164    return AAUDIO_OK;
165}
166
167AAUDIO_API aaudio_result_t AAudioStreamBuilder_getDeviceId(AAudioStreamBuilder builder,
168                                              aaudio_device_id_t *deviceId)
169{
170    AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(deviceId);
171    *deviceId = streamBuilder->getDeviceId();
172    return AAUDIO_OK;
173}
174
175AAUDIO_API aaudio_result_t AAudioStreamBuilder_setSampleRate(AAudioStreamBuilder builder,
176                                              aaudio_sample_rate_t sampleRate)
177{
178    AudioStreamBuilder *streamBuilder = CONVERT_BUILDER_HANDLE_OR_RETURN();
179    streamBuilder->setSampleRate(sampleRate);
180    return AAUDIO_OK;
181}
182
183AAUDIO_API aaudio_result_t AAudioStreamBuilder_getSampleRate(AAudioStreamBuilder builder,
184                                              aaudio_sample_rate_t *sampleRate)
185{
186    AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(sampleRate);
187    *sampleRate = streamBuilder->getSampleRate();
188    return AAUDIO_OK;
189}
190
191AAUDIO_API aaudio_result_t AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder builder,
192                                                   int32_t samplesPerFrame)
193{
194    AudioStreamBuilder *streamBuilder = CONVERT_BUILDER_HANDLE_OR_RETURN();
195    streamBuilder->setSamplesPerFrame(samplesPerFrame);
196    return AAUDIO_OK;
197}
198
199AAUDIO_API aaudio_result_t AAudioStreamBuilder_getSamplesPerFrame(AAudioStreamBuilder builder,
200                                                   int32_t *samplesPerFrame)
201{
202    AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(samplesPerFrame);
203    *samplesPerFrame = streamBuilder->getSamplesPerFrame();
204    return AAUDIO_OK;
205}
206
207AAUDIO_API aaudio_result_t AAudioStreamBuilder_setDirection(AAudioStreamBuilder builder,
208                                             aaudio_direction_t direction)
209{
210    AudioStreamBuilder *streamBuilder = CONVERT_BUILDER_HANDLE_OR_RETURN();
211    streamBuilder->setDirection(direction);
212    return AAUDIO_OK;
213}
214
215AAUDIO_API aaudio_result_t AAudioStreamBuilder_getDirection(AAudioStreamBuilder builder,
216                                             aaudio_direction_t *direction)
217{
218    AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(direction);
219    *direction = streamBuilder->getDirection();
220    return AAUDIO_OK;
221}
222
223AAUDIO_API aaudio_result_t AAudioStreamBuilder_setFormat(AAudioStreamBuilder builder,
224                                                   aaudio_audio_format_t format)
225{
226    AudioStreamBuilder *streamBuilder = CONVERT_BUILDER_HANDLE_OR_RETURN();
227    streamBuilder->setFormat(format);
228    return AAUDIO_OK;
229}
230
231AAUDIO_API aaudio_result_t AAudioStreamBuilder_getFormat(AAudioStreamBuilder builder,
232                                                   aaudio_audio_format_t *format)
233{
234    AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(format);
235    *format = streamBuilder->getFormat();
236    return AAUDIO_OK;
237}
238
239AAUDIO_API aaudio_result_t AAudioStreamBuilder_setSharingMode(AAudioStreamBuilder builder,
240                                                        aaudio_sharing_mode_t sharingMode)
241{
242    AudioStreamBuilder *streamBuilder = CONVERT_BUILDER_HANDLE_OR_RETURN();
243    if ((sharingMode < 0) || (sharingMode >= AAUDIO_SHARING_MODE_COUNT)) {
244        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
245    } else {
246        streamBuilder->setSharingMode(sharingMode);
247        return AAUDIO_OK;
248    }
249}
250
251AAUDIO_API aaudio_result_t AAudioStreamBuilder_getSharingMode(AAudioStreamBuilder builder,
252                                                        aaudio_sharing_mode_t *sharingMode)
253{
254    AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(sharingMode);
255    *sharingMode = streamBuilder->getSharingMode();
256    return AAUDIO_OK;
257}
258
259AAUDIO_API aaudio_result_t AAudioStreamBuilder_setBufferCapacity(AAudioStreamBuilder builder,
260                                                        aaudio_size_frames_t frames)
261{
262    AudioStreamBuilder *streamBuilder = CONVERT_BUILDER_HANDLE_OR_RETURN();
263    if (frames < 0) {
264        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
265    } else {
266        streamBuilder->setBufferCapacity(frames);
267        return AAUDIO_OK;
268    }
269}
270
271AAUDIO_API aaudio_result_t AAudioStreamBuilder_getBufferCapacity(AAudioStreamBuilder builder,
272                                                        aaudio_size_frames_t *frames)
273{
274    AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(frames);
275    *frames = streamBuilder->getBufferCapacity();
276    return AAUDIO_OK;
277}
278
279static aaudio_result_t  AAudioInternal_openStream(AudioStreamBuilder *streamBuilder,
280                                              AAudioStream *streamPtr)
281{
282    AudioStream *audioStream = nullptr;
283    aaudio_result_t result = streamBuilder->build(&audioStream);
284    if (result != AAUDIO_OK) {
285        return result;
286    } else {
287        // Create a handle for referencing the object.
288        // TODO protect the put() with a Mutex
289        AAudioStream handle = sHandleTracker.put(AAUDIO_HANDLE_TYPE_STREAM, audioStream);
290        if (handle < 0) {
291            delete audioStream;
292            return static_cast<aaudio_result_t>(handle);
293        }
294        *streamPtr = handle;
295        return AAUDIO_OK;
296    }
297}
298
299AAUDIO_API aaudio_result_t  AAudioStreamBuilder_openStream(AAudioStreamBuilder builder,
300                                                     AAudioStream *streamPtr)
301{
302    ALOGD("AAudioStreamBuilder_openStream(): builder = 0x%08X", builder);
303    AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr);
304    return AAudioInternal_openStream(streamBuilder, streamPtr);
305}
306
307AAUDIO_API aaudio_result_t  AAudioStreamBuilder_delete(AAudioStreamBuilder builder)
308{
309    AudioStreamBuilder *streamBuilder = (AudioStreamBuilder *)
310            sHandleTracker.remove(AAUDIO_HANDLE_TYPE_STREAM_BUILDER, builder);
311    if (streamBuilder != nullptr) {
312        delete streamBuilder;
313        return AAUDIO_OK;
314    }
315    return AAUDIO_ERROR_INVALID_HANDLE;
316}
317
318AAUDIO_API aaudio_result_t  AAudioStream_close(AAudioStream stream)
319{
320    AudioStream *audioStream = (AudioStream *)
321            sHandleTracker.remove(AAUDIO_HANDLE_TYPE_STREAM, (aaudio_handle_t)stream);
322    ALOGD("AAudioStream_close(0x%08X), audioStream = %p", stream, audioStream);
323    if (audioStream != nullptr) {
324        audioStream->close();
325        delete audioStream;
326        return AAUDIO_OK;
327    }
328    return AAUDIO_ERROR_INVALID_HANDLE;
329}
330
331AAUDIO_API aaudio_result_t  AAudioStream_requestStart(AAudioStream stream)
332{
333    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
334    ALOGD("AAudioStream_requestStart(0x%08X), audioStream = %p", stream, audioStream);
335    return audioStream->requestStart();
336}
337
338AAUDIO_API aaudio_result_t  AAudioStream_requestPause(AAudioStream stream)
339{
340    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
341    ALOGD("AAudioStream_requestPause(0x%08X), audioStream = %p", stream, audioStream);
342    return audioStream->requestPause();
343}
344
345AAUDIO_API aaudio_result_t  AAudioStream_requestFlush(AAudioStream stream)
346{
347    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
348    ALOGD("AAudioStream_requestFlush(0x%08X), audioStream = %p", stream, audioStream);
349    return audioStream->requestFlush();
350}
351
352AAUDIO_API aaudio_result_t  AAudioStream_requestStop(AAudioStream stream)
353{
354    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
355    ALOGD("AAudioStream_requestStop(0x%08X), audioStream = %p", stream, audioStream);
356    return audioStream->requestStop();
357}
358
359AAUDIO_API aaudio_result_t AAudioStream_waitForStateChange(AAudioStream stream,
360                                            aaudio_stream_state_t inputState,
361                                            aaudio_stream_state_t *nextState,
362                                            aaudio_nanoseconds_t timeoutNanoseconds)
363{
364
365    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
366    return audioStream->waitForStateChange(inputState, nextState, timeoutNanoseconds);
367}
368
369// ============================================================
370// Stream - non-blocking I/O
371// ============================================================
372
373AAUDIO_API aaudio_result_t AAudioStream_read(AAudioStream stream,
374                               void *buffer,
375                               aaudio_size_frames_t numFrames,
376                               aaudio_nanoseconds_t timeoutNanoseconds)
377{
378    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
379    if (buffer == nullptr) {
380        return AAUDIO_ERROR_NULL;
381    }
382    if (numFrames < 0) {
383        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
384    } else if (numFrames == 0) {
385        return 0;
386    }
387
388    aaudio_result_t result = audioStream->read(buffer, numFrames, timeoutNanoseconds);
389    // ALOGD("AAudioStream_read(): read returns %d", result);
390
391    return result;
392}
393
394AAUDIO_API aaudio_result_t AAudioStream_write(AAudioStream stream,
395                               const void *buffer,
396                               aaudio_size_frames_t numFrames,
397                               aaudio_nanoseconds_t timeoutNanoseconds)
398{
399    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
400    if (buffer == nullptr) {
401        return AAUDIO_ERROR_NULL;
402    }
403    if (numFrames < 0) {
404        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
405    } else if (numFrames == 0) {
406        return 0;
407    }
408
409    aaudio_result_t result = audioStream->write(buffer, numFrames, timeoutNanoseconds);
410    // ALOGD("AAudioStream_write(): write returns %d", result);
411
412    return result;
413}
414
415// ============================================================
416// Miscellaneous
417// ============================================================
418
419AAUDIO_API aaudio_result_t AAudioStream_createThread(AAudioStream stream,
420                                     aaudio_nanoseconds_t periodNanoseconds,
421                                     aaudio_audio_thread_proc_t *threadProc, void *arg)
422{
423    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
424    return audioStream->createThread(periodNanoseconds, threadProc, arg);
425}
426
427AAUDIO_API aaudio_result_t AAudioStream_joinThread(AAudioStream stream,
428                                   void **returnArg,
429                                   aaudio_nanoseconds_t timeoutNanoseconds)
430{
431    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
432    return audioStream->joinThread(returnArg, timeoutNanoseconds);
433}
434
435// ============================================================
436// Stream - queries
437// ============================================================
438
439// TODO Use aaudio_clockid_t all the way down through the C++ streams.
440static clockid_t AAudioConvert_fromAAudioClockId(aaudio_clockid_t clockid)
441{
442    clockid_t hostClockId;
443    switch (clockid) {
444        case AAUDIO_CLOCK_MONOTONIC:
445            hostClockId = CLOCK_MONOTONIC;
446            break;
447        case AAUDIO_CLOCK_BOOTTIME:
448            hostClockId = CLOCK_BOOTTIME;
449            break;
450        default:
451            hostClockId = 0; // TODO review
452    }
453    return hostClockId;
454}
455
456aaudio_nanoseconds_t AAudio_getNanoseconds(aaudio_clockid_t clockid)
457{
458    clockid_t hostClockId = AAudioConvert_fromAAudioClockId(clockid);
459   return AudioClock::getNanoseconds(hostClockId);
460}
461
462AAUDIO_API aaudio_result_t AAudioStream_getSampleRate(AAudioStream stream, aaudio_sample_rate_t *sampleRate)
463{
464    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(sampleRate);
465    *sampleRate = audioStream->getSampleRate();
466    return AAUDIO_OK;
467}
468
469AAUDIO_API aaudio_result_t AAudioStream_getSamplesPerFrame(AAudioStream stream, int32_t *samplesPerFrame)
470{
471    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(samplesPerFrame);
472    *samplesPerFrame = audioStream->getSamplesPerFrame();
473    return AAUDIO_OK;
474}
475
476AAUDIO_API aaudio_result_t AAudioStream_getState(AAudioStream stream, aaudio_stream_state_t *state)
477{
478    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(state);
479    *state = audioStream->getState();
480    return AAUDIO_OK;
481}
482
483AAUDIO_API aaudio_result_t AAudioStream_getFormat(AAudioStream stream, aaudio_audio_format_t *format)
484{
485    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(format);
486    *format = audioStream->getFormat();
487    return AAUDIO_OK;
488}
489
490AAUDIO_API aaudio_result_t AAudioStream_setBufferSize(AAudioStream stream,
491                                                aaudio_size_frames_t requestedFrames,
492                                                aaudio_size_frames_t *actualFrames)
493{
494    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
495    return audioStream->setBufferSize(requestedFrames, actualFrames);
496}
497
498AAUDIO_API aaudio_result_t AAudioStream_getBufferSize(AAudioStream stream, aaudio_size_frames_t *frames)
499{
500    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(frames);
501    *frames = audioStream->getBufferSize();
502    return AAUDIO_OK;
503}
504
505AAUDIO_API aaudio_result_t AAudioStream_getDirection(AAudioStream stream, int32_t *direction)
506{
507    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(direction);
508    *direction = audioStream->getDirection();
509    return AAUDIO_OK;
510}
511
512AAUDIO_API aaudio_result_t AAudioStream_getFramesPerBurst(AAudioStream stream,
513                                                    aaudio_size_frames_t *framesPerBurst)
514{
515    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(framesPerBurst);
516    *framesPerBurst = audioStream->getFramesPerBurst();
517    return AAUDIO_OK;
518}
519
520AAUDIO_API aaudio_result_t AAudioStream_getBufferCapacity(AAudioStream stream,
521                                           aaudio_size_frames_t *capacity)
522{
523    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(capacity);
524    *capacity = audioStream->getBufferCapacity();
525    return AAUDIO_OK;
526}
527
528AAUDIO_API aaudio_result_t AAudioStream_getXRunCount(AAudioStream stream, int32_t *xRunCount)
529{
530    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(xRunCount);
531    *xRunCount = audioStream->getXRunCount();
532    return AAUDIO_OK;
533}
534
535AAUDIO_API aaudio_result_t AAudioStream_getDeviceId(AAudioStream stream,
536                                                 aaudio_device_id_t *deviceId)
537{
538    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(deviceId);
539    *deviceId = audioStream->getDeviceId();
540    return AAUDIO_OK;
541}
542
543AAUDIO_API aaudio_result_t AAudioStream_getSharingMode(AAudioStream stream,
544                                                 aaudio_sharing_mode_t *sharingMode)
545{
546    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(sharingMode);
547    *sharingMode = audioStream->getSharingMode();
548    return AAUDIO_OK;
549}
550
551AAUDIO_API aaudio_result_t AAudioStream_getFramesWritten(AAudioStream stream,
552                                                   aaudio_position_frames_t *frames)
553{
554    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(frames);
555    *frames = audioStream->getFramesWritten();
556    return AAUDIO_OK;
557}
558
559AAUDIO_API aaudio_result_t AAudioStream_getFramesRead(AAudioStream stream, aaudio_position_frames_t *frames)
560{
561    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(frames);
562    *frames = audioStream->getFramesRead();
563    return AAUDIO_OK;
564}
565
566AAUDIO_API aaudio_result_t AAudioStream_getTimestamp(AAudioStream stream,
567                                      aaudio_clockid_t clockid,
568                                      aaudio_position_frames_t *framePosition,
569                                      aaudio_nanoseconds_t *timeNanoseconds)
570{
571    AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
572    if (framePosition == nullptr) {
573        return AAUDIO_ERROR_NULL;
574    } else if (timeNanoseconds == nullptr) {
575        return AAUDIO_ERROR_NULL;
576    } else if (clockid != AAUDIO_CLOCK_MONOTONIC && clockid != AAUDIO_CLOCK_BOOTTIME) {
577        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
578    }
579
580    clockid_t hostClockId = AAudioConvert_fromAAudioClockId(clockid);
581    return audioStream->getTimestamp(hostClockId, framePosition, timeNanoseconds);
582}
583