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#include <aaudio/AAudioTesting.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 36// Macros for common code that includes a return. 37// TODO Consider using do{}while(0) construct. I tried but it hung AndroidStudio 38#define CONVERT_BUILDER_HANDLE_OR_RETURN() \ 39 convertAAudioBuilderToStreamBuilder(builder); 40 41#define COMMON_GET_FROM_BUILDER_OR_RETURN(resultPtr) \ 42 CONVERT_BUILDER_HANDLE_OR_RETURN() \ 43 if ((resultPtr) == nullptr) { \ 44 return AAUDIO_ERROR_NULL; \ 45 } 46 47#define AAUDIO_CASE_ENUM(name) case name: return #name 48 49AAUDIO_API const char * AAudio_convertResultToText(aaudio_result_t returnCode) { 50 switch (returnCode) { 51 AAUDIO_CASE_ENUM(AAUDIO_OK); 52 AAUDIO_CASE_ENUM(AAUDIO_ERROR_DISCONNECTED); 53 AAUDIO_CASE_ENUM(AAUDIO_ERROR_ILLEGAL_ARGUMENT); 54 // reserved 55 AAUDIO_CASE_ENUM(AAUDIO_ERROR_INTERNAL); 56 AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_STATE); 57 // reserved 58 // reserved 59 AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_HANDLE); 60 // reserved 61 AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNIMPLEMENTED); 62 AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNAVAILABLE); 63 AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_FREE_HANDLES); 64 AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_MEMORY); 65 AAUDIO_CASE_ENUM(AAUDIO_ERROR_NULL); 66 AAUDIO_CASE_ENUM(AAUDIO_ERROR_TIMEOUT); 67 AAUDIO_CASE_ENUM(AAUDIO_ERROR_WOULD_BLOCK); 68 AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_FORMAT); 69 AAUDIO_CASE_ENUM(AAUDIO_ERROR_OUT_OF_RANGE); 70 AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_SERVICE); 71 AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_RATE); 72 } 73 return "Unrecognized AAudio error."; 74} 75 76AAUDIO_API const char * AAudio_convertStreamStateToText(aaudio_stream_state_t state) { 77 switch (state) { 78 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNINITIALIZED); 79 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNKNOWN); 80 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_OPEN); 81 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTING); 82 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTED); 83 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSING); 84 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSED); 85 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHING); 86 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHED); 87 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPING); 88 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPED); 89 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_DISCONNECTED); 90 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSING); 91 AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSED); 92 } 93 return "Unrecognized AAudio state."; 94} 95 96#undef AAUDIO_CASE_ENUM 97 98 99/****************************************** 100 * Static globals. 101 */ 102static aaudio_policy_t s_MMapPolicy = AAUDIO_UNSPECIFIED; 103 104 105static AudioStream *convertAAudioStreamToAudioStream(AAudioStream* stream) 106{ 107 return (AudioStream*) stream; 108} 109 110static AudioStreamBuilder *convertAAudioBuilderToStreamBuilder(AAudioStreamBuilder* builder) 111{ 112 return (AudioStreamBuilder*) builder; 113} 114 115AAUDIO_API aaudio_result_t AAudio_createStreamBuilder(AAudioStreamBuilder** builder) 116{ 117 AudioStreamBuilder *audioStreamBuilder = new(std::nothrow) AudioStreamBuilder(); 118 if (audioStreamBuilder == nullptr) { 119 return AAUDIO_ERROR_NO_MEMORY; 120 } 121 *builder = (AAudioStreamBuilder*) audioStreamBuilder; 122 return AAUDIO_OK; 123} 124 125AAUDIO_API void AAudioStreamBuilder_setPerformanceMode(AAudioStreamBuilder* builder, 126 aaudio_performance_mode_t mode) 127{ 128 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 129 streamBuilder->setPerformanceMode(mode); 130} 131 132AAUDIO_API void AAudioStreamBuilder_setDeviceId(AAudioStreamBuilder* builder, 133 int32_t deviceId) 134{ 135 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 136 streamBuilder->setDeviceId(deviceId); 137} 138 139AAUDIO_API void AAudioStreamBuilder_setSampleRate(AAudioStreamBuilder* builder, 140 int32_t sampleRate) 141{ 142 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 143 streamBuilder->setSampleRate(sampleRate); 144} 145 146AAUDIO_API void AAudioStreamBuilder_setChannelCount(AAudioStreamBuilder* builder, 147 int32_t channelCount) 148{ 149 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 150 streamBuilder->setSamplesPerFrame(channelCount); 151} 152 153AAUDIO_API void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder, 154 int32_t samplesPerFrame) 155{ 156 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 157 streamBuilder->setSamplesPerFrame(samplesPerFrame); 158} 159 160AAUDIO_API void AAudioStreamBuilder_setDirection(AAudioStreamBuilder* builder, 161 aaudio_direction_t direction) 162{ 163 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 164 streamBuilder->setDirection(direction); 165} 166 167AAUDIO_API void AAudioStreamBuilder_setFormat(AAudioStreamBuilder* builder, 168 aaudio_format_t format) 169{ 170 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 171 streamBuilder->setFormat(format); 172} 173 174AAUDIO_API void AAudioStreamBuilder_setSharingMode(AAudioStreamBuilder* builder, 175 aaudio_sharing_mode_t sharingMode) 176{ 177 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 178 streamBuilder->setSharingMode(sharingMode); 179} 180 181AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder, 182 int32_t frames) 183{ 184 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 185 streamBuilder->setBufferCapacity(frames); 186} 187 188AAUDIO_API void AAudioStreamBuilder_setDataCallback(AAudioStreamBuilder* builder, 189 AAudioStream_dataCallback callback, 190 void *userData) 191{ 192 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 193 streamBuilder->setDataCallbackProc(callback); 194 streamBuilder->setDataCallbackUserData(userData); 195} 196 197AAUDIO_API void AAudioStreamBuilder_setErrorCallback(AAudioStreamBuilder* builder, 198 AAudioStream_errorCallback callback, 199 void *userData) 200{ 201 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 202 streamBuilder->setErrorCallbackProc(callback); 203 streamBuilder->setErrorCallbackUserData(userData); 204} 205 206AAUDIO_API void AAudioStreamBuilder_setFramesPerDataCallback(AAudioStreamBuilder* builder, 207 int32_t frames) 208{ 209 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 210 streamBuilder->setFramesPerDataCallback(frames); 211} 212 213AAUDIO_API aaudio_result_t AAudioStreamBuilder_openStream(AAudioStreamBuilder* builder, 214 AAudioStream** streamPtr) 215{ 216 AudioStream *audioStream = nullptr; 217 // Please leave these logs because they are very helpful when debugging. 218 ALOGD("AAudioStreamBuilder_openStream() called ----------------------------------------"); 219 AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr); 220 aaudio_result_t result = streamBuilder->build(&audioStream); 221 ALOGD("AAudioStreamBuilder_openStream() returns %d = %s for (%p) ----------------", 222 result, AAudio_convertResultToText(result), audioStream); 223 if (result == AAUDIO_OK) { 224 *streamPtr = (AAudioStream*) audioStream; 225 } else { 226 *streamPtr = nullptr; 227 } 228 return result; 229} 230 231AAUDIO_API aaudio_result_t AAudioStreamBuilder_delete(AAudioStreamBuilder* builder) 232{ 233 AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder); 234 if (streamBuilder != nullptr) { 235 delete streamBuilder; 236 return AAUDIO_OK; 237 } 238 return AAUDIO_ERROR_NULL; 239} 240 241AAUDIO_API aaudio_result_t AAudioStream_close(AAudioStream* stream) 242{ 243 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 244 ALOGD("AAudioStream_close(%p)", stream); 245 if (audioStream != nullptr) { 246 audioStream->close(); 247 delete audioStream; 248 return AAUDIO_OK; 249 } 250 return AAUDIO_ERROR_NULL; 251} 252 253AAUDIO_API aaudio_result_t AAudioStream_requestStart(AAudioStream* stream) 254{ 255 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 256 ALOGD("AAudioStream_requestStart(%p)", stream); 257 return audioStream->requestStart(); 258} 259 260AAUDIO_API aaudio_result_t AAudioStream_requestPause(AAudioStream* stream) 261{ 262 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 263 ALOGD("AAudioStream_requestPause(%p)", stream); 264 return audioStream->requestPause(); 265} 266 267AAUDIO_API aaudio_result_t AAudioStream_requestFlush(AAudioStream* stream) 268{ 269 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 270 ALOGD("AAudioStream_requestFlush(%p)", stream); 271 return audioStream->requestFlush(); 272} 273 274AAUDIO_API aaudio_result_t AAudioStream_requestStop(AAudioStream* stream) 275{ 276 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 277 ALOGD("AAudioStream_requestStop(%p)", stream); 278 return audioStream->requestStop(); 279} 280 281AAUDIO_API aaudio_result_t AAudioStream_waitForStateChange(AAudioStream* stream, 282 aaudio_stream_state_t inputState, 283 aaudio_stream_state_t *nextState, 284 int64_t timeoutNanoseconds) 285{ 286 287 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 288 return audioStream->waitForStateChange(inputState, nextState, timeoutNanoseconds); 289} 290 291// ============================================================ 292// Stream - non-blocking I/O 293// ============================================================ 294 295AAUDIO_API aaudio_result_t AAudioStream_read(AAudioStream* stream, 296 void *buffer, 297 int32_t numFrames, 298 int64_t timeoutNanoseconds) 299{ 300 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 301 if (buffer == nullptr) { 302 return AAUDIO_ERROR_NULL; 303 } 304 if (numFrames < 0) { 305 return AAUDIO_ERROR_ILLEGAL_ARGUMENT; 306 } else if (numFrames == 0) { 307 return 0; 308 } 309 310 aaudio_result_t result = audioStream->read(buffer, numFrames, timeoutNanoseconds); 311 312 return result; 313} 314 315AAUDIO_API aaudio_result_t AAudioStream_write(AAudioStream* stream, 316 const void *buffer, 317 int32_t numFrames, 318 int64_t timeoutNanoseconds) 319{ 320 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 321 if (buffer == nullptr) { 322 return AAUDIO_ERROR_NULL; 323 } 324 325 // Don't allow writes when playing with a callback. 326 if (audioStream->getDataCallbackProc() != nullptr && audioStream->isActive()) { 327 ALOGE("Cannot write to a callback stream when running."); 328 return AAUDIO_ERROR_INVALID_STATE; 329 } 330 331 if (numFrames < 0) { 332 return AAUDIO_ERROR_ILLEGAL_ARGUMENT; 333 } else if (numFrames == 0) { 334 return 0; 335 } 336 337 aaudio_result_t result = audioStream->write(buffer, numFrames, timeoutNanoseconds); 338 339 return result; 340} 341 342// ============================================================ 343// Stream - queries 344// ============================================================ 345 346AAUDIO_API int32_t AAudioStream_getSampleRate(AAudioStream* stream) 347{ 348 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 349 return audioStream->getSampleRate(); 350} 351 352AAUDIO_API int32_t AAudioStream_getChannelCount(AAudioStream* stream) 353{ 354 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 355 return audioStream->getSamplesPerFrame(); 356} 357 358AAUDIO_API int32_t AAudioStream_getSamplesPerFrame(AAudioStream* stream) 359{ 360 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 361 return audioStream->getSamplesPerFrame(); 362} 363 364AAUDIO_API aaudio_stream_state_t AAudioStream_getState(AAudioStream* stream) 365{ 366 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 367 return audioStream->getState(); 368} 369 370AAUDIO_API aaudio_format_t AAudioStream_getFormat(AAudioStream* stream) 371{ 372 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 373 return audioStream->getFormat(); 374} 375 376AAUDIO_API aaudio_result_t AAudioStream_setBufferSizeInFrames(AAudioStream* stream, 377 int32_t requestedFrames) 378{ 379 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 380 return audioStream->setBufferSize(requestedFrames); 381} 382 383AAUDIO_API int32_t AAudioStream_getBufferSizeInFrames(AAudioStream* stream) 384{ 385 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 386 return audioStream->getBufferSize(); 387} 388 389AAUDIO_API aaudio_direction_t AAudioStream_getDirection(AAudioStream* stream) 390{ 391 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 392 return audioStream->getDirection(); 393} 394 395AAUDIO_API int32_t AAudioStream_getFramesPerBurst(AAudioStream* stream) 396{ 397 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 398 return audioStream->getFramesPerBurst(); 399} 400 401AAUDIO_API int32_t AAudioStream_getFramesPerDataCallback(AAudioStream* stream) 402{ 403 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 404 return audioStream->getFramesPerDataCallback(); 405} 406 407AAUDIO_API int32_t AAudioStream_getBufferCapacityInFrames(AAudioStream* stream) 408{ 409 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 410 return audioStream->getBufferCapacity(); 411} 412 413AAUDIO_API int32_t AAudioStream_getXRunCount(AAudioStream* stream) 414{ 415 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 416 return audioStream->getXRunCount(); 417} 418 419AAUDIO_API aaudio_performance_mode_t AAudioStream_getPerformanceMode(AAudioStream* stream) 420{ 421 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 422 return audioStream->getPerformanceMode(); 423} 424 425AAUDIO_API int32_t AAudioStream_getDeviceId(AAudioStream* stream) 426{ 427 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 428 return audioStream->getDeviceId(); 429} 430 431AAUDIO_API aaudio_sharing_mode_t AAudioStream_getSharingMode(AAudioStream* stream) 432{ 433 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 434 return audioStream->getSharingMode(); 435} 436 437AAUDIO_API int64_t AAudioStream_getFramesWritten(AAudioStream* stream) 438{ 439 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 440 return audioStream->getFramesWritten(); 441} 442 443AAUDIO_API int64_t AAudioStream_getFramesRead(AAudioStream* stream) 444{ 445 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 446 return audioStream->getFramesRead(); 447} 448 449AAUDIO_API aaudio_result_t AAudioStream_getTimestamp(AAudioStream* stream, 450 clockid_t clockid, 451 int64_t *framePosition, 452 int64_t *timeNanoseconds) 453{ 454 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 455 if (framePosition == nullptr) { 456 return AAUDIO_ERROR_NULL; 457 } else if (timeNanoseconds == nullptr) { 458 return AAUDIO_ERROR_NULL; 459 } else if (clockid != CLOCK_MONOTONIC && clockid != CLOCK_BOOTTIME) { 460 return AAUDIO_ERROR_ILLEGAL_ARGUMENT; 461 } 462 463 return audioStream->getTimestamp(clockid, framePosition, timeNanoseconds); 464} 465 466AAUDIO_API aaudio_policy_t AAudio_getMMapPolicy() { 467 return s_MMapPolicy; 468} 469 470AAUDIO_API aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy) { 471 aaudio_result_t result = AAUDIO_OK; 472 switch(policy) { 473 case AAUDIO_UNSPECIFIED: 474 case AAUDIO_POLICY_NEVER: 475 case AAUDIO_POLICY_AUTO: 476 case AAUDIO_POLICY_ALWAYS: 477 s_MMapPolicy = policy; 478 break; 479 default: 480 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT; 481 break; 482 } 483 return result; 484} 485 486AAUDIO_API bool AAudioStream_isMMapUsed(AAudioStream* stream) 487{ 488 AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); 489 return audioStream->isMMap(); 490} 491