| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2017 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 | #ifndef AAUDIO_EXAMPLE_ARGS_PARSER_H | 
 | 18 | #define AAUDIO_EXAMPLE_ARGS_PARSER_H | 
 | 19 |  | 
| Phil Burk | 67ed9da | 2017-09-06 16:26:52 -0700 | [diff] [blame] | 20 | #define MAX_CHANNELS                     8 | 
 | 21 |  | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 22 | //#include <cctype> | 
 | 23 | #include <dlfcn.h> | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 24 | #include <unistd.h> | 
 | 25 | #include <stdio.h> | 
 | 26 | #include <stdlib.h> | 
 | 27 |  | 
 | 28 | #include <aaudio/AAudio.h> | 
 | 29 | #include <aaudio/AAudioTesting.h> | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 30 |  | 
 | 31 | #include "AAudioExampleUtils.h" | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 32 |  | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 33 |  | 
 | 34 | static void (*s_setUsage)(AAudioStreamBuilder* builder, aaudio_usage_t usage) = nullptr; | 
 | 35 | static void (*s_setContentType)(AAudioStreamBuilder* builder, | 
 | 36 |                                 aaudio_content_type_t contentType) = nullptr; | 
 | 37 | static void (*s_setInputPreset)(AAudioStreamBuilder* builder, | 
 | 38 |                                 aaudio_input_preset_t inputPreset) = nullptr; | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 39 | static void (*s_setAllowedCapturePolicy)(AAudioStreamBuilder* builder, | 
 | 40 |                                           aaudio_allowed_capture_policy_t usage) = nullptr; | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 41 | static void (*s_setPrivacySensitive)(AAudioStreamBuilder* builder, | 
 | 42 |                                           bool privacySensitive) = nullptr; | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 43 |  | 
 | 44 | static bool s_loadAttempted = false; | 
 | 45 | static aaudio_usage_t (*s_getUsage)(AAudioStream *stream) = nullptr; | 
 | 46 | static aaudio_content_type_t (*s_getContentType)(AAudioStream *stream) = nullptr; | 
 | 47 | static aaudio_input_preset_t (*s_getInputPreset)(AAudioStream *stream) = nullptr; | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 48 | static aaudio_allowed_capture_policy_t (*s_getAllowedCapturePolicy)(AAudioStream *stream) = nullptr; | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 49 | static bool (*s_isPrivacySensitive)(AAudioStream *stream) = nullptr; | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 50 |  | 
 | 51 | // Link to test functions in shared library. | 
 | 52 | static void loadFutureFunctions() { | 
 | 53 |     if (s_loadAttempted)  return; // only try once | 
 | 54 |     s_loadAttempted = true; | 
 | 55 |  | 
 | 56 |     void *handle = dlopen("libaaudio.so", RTLD_NOW); | 
 | 57 |     if (handle != nullptr) { | 
 | 58 |         s_setUsage = (void (*)(AAudioStreamBuilder *, aaudio_usage_t)) | 
 | 59 |                 dlsym(handle, "AAudioStreamBuilder_setUsage"); | 
 | 60 |         if (s_setUsage == nullptr) goto error; | 
 | 61 |  | 
 | 62 |         s_setContentType = (void (*)(AAudioStreamBuilder *, aaudio_content_type_t)) | 
 | 63 |                 dlsym(handle, "AAudioStreamBuilder_setContentType"); | 
 | 64 |         if (s_setContentType == nullptr) goto error; | 
 | 65 |  | 
 | 66 |         s_setInputPreset = (void (*)(AAudioStreamBuilder *, aaudio_input_preset_t)) | 
 | 67 |                 dlsym(handle, "AAudioStreamBuilder_setInputPreset"); | 
 | 68 |         if (s_setInputPreset == nullptr) goto error; | 
 | 69 |  | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 70 |         s_setAllowedCapturePolicy = (void (*)(AAudioStreamBuilder *, aaudio_input_preset_t)) | 
 | 71 |                 dlsym(handle, "AAudioStreamBuilder_setAllowedCapturePolicy"); | 
 | 72 |         if (s_setAllowedCapturePolicy == nullptr) goto error; | 
 | 73 |  | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 74 |         s_setPrivacySensitive = (void (*)(AAudioStreamBuilder *, bool)) | 
 | 75 |                 dlsym(handle, "AAudioStreamBuilder_setPrivacySensitive"); | 
 | 76 |         if (s_setPrivacySensitive == nullptr) goto error; | 
 | 77 |  | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 78 |         s_getUsage = (aaudio_usage_t (*)(AAudioStream *)) | 
 | 79 |                 dlsym(handle, "AAudioStream_getUsage"); | 
 | 80 |         if (s_getUsage == nullptr) goto error; | 
 | 81 |  | 
 | 82 |         s_getContentType = (aaudio_content_type_t (*)(AAudioStream *)) | 
 | 83 |                 dlsym(handle, "AAudioStream_getContentType"); | 
 | 84 |         if (s_getContentType == nullptr) goto error; | 
 | 85 |  | 
 | 86 |         s_getInputPreset = (aaudio_input_preset_t (*)(AAudioStream *)) | 
 | 87 |                 dlsym(handle, "AAudioStream_getInputPreset"); | 
 | 88 |         if (s_getInputPreset == nullptr) goto error; | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 89 |  | 
 | 90 |         s_getAllowedCapturePolicy = (aaudio_input_preset_t (*)(AAudioStream *)) | 
 | 91 |                 dlsym(handle, "AAudioStream_getAllowedCapturePolicy"); | 
 | 92 |         if (s_getAllowedCapturePolicy == nullptr) goto error; | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 93 |  | 
 | 94 |         s_isPrivacySensitive = (bool (*)(AAudioStream *)) | 
 | 95 |                 dlsym(handle, "AAudioStream_isPrivacySensitive"); | 
 | 96 |         if (s_isPrivacySensitive == nullptr) goto error; | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 97 |     } | 
 | 98 |     return; | 
 | 99 |  | 
 | 100 | error: | 
 | 101 |     // prevent any calls to these functions | 
 | 102 |     s_setUsage = nullptr; | 
 | 103 |     s_setContentType = nullptr; | 
 | 104 |     s_setInputPreset = nullptr; | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 105 |     s_setPrivacySensitive = nullptr; | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 106 |     s_getUsage = nullptr; | 
 | 107 |     s_getContentType = nullptr; | 
 | 108 |     s_getInputPreset = nullptr; | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 109 |     s_isPrivacySensitive = nullptr; | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 110 |     dlclose(handle); | 
 | 111 |     return; | 
 | 112 | } | 
 | 113 |  | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 114 | class AAudioParameters { | 
 | 115 | public: | 
 | 116 |  | 
 | 117 |     /** | 
 | 118 |      * This is also known as samplesPerFrame. | 
 | 119 |      */ | 
 | 120 |     int32_t getChannelCount() const { | 
 | 121 |         return mChannelCount; | 
 | 122 |     } | 
 | 123 |  | 
 | 124 |     void setChannelCount(int32_t channelCount) { | 
| Phil Burk | 67ed9da | 2017-09-06 16:26:52 -0700 | [diff] [blame] | 125 |         if (channelCount > MAX_CHANNELS) { | 
 | 126 |             printf("Sorry, MAX of %d channels!\n", MAX_CHANNELS); | 
 | 127 |             channelCount = MAX_CHANNELS; | 
 | 128 |         } | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 129 |         mChannelCount = channelCount; | 
 | 130 |     } | 
 | 131 |  | 
 | 132 |     int32_t getSampleRate() const { | 
 | 133 |         return mSampleRate; | 
 | 134 |     } | 
 | 135 |  | 
 | 136 |     void setSampleRate(int32_t sampleRate) { | 
 | 137 |         mSampleRate = sampleRate; | 
 | 138 |     } | 
 | 139 |  | 
 | 140 |     aaudio_format_t getFormat() const { | 
 | 141 |         return mFormat; | 
 | 142 |     } | 
 | 143 |  | 
 | 144 |     void setFormat(aaudio_format_t format) { | 
 | 145 |         mFormat = format; | 
 | 146 |     } | 
 | 147 |  | 
 | 148 |     aaudio_sharing_mode_t getSharingMode() const { | 
 | 149 |         return mSharingMode; | 
 | 150 |     } | 
 | 151 |  | 
 | 152 |     void setSharingMode(aaudio_sharing_mode_t sharingMode) { | 
 | 153 |         mSharingMode = sharingMode; | 
 | 154 |     } | 
 | 155 |  | 
 | 156 |     int32_t getBufferCapacity() const { | 
 | 157 |         return mBufferCapacity; | 
 | 158 |     } | 
 | 159 |  | 
 | 160 |     void setBufferCapacity(int32_t frames) { | 
 | 161 |         mBufferCapacity = frames; | 
 | 162 |     } | 
 | 163 |  | 
 | 164 |     int32_t getPerformanceMode() const { | 
 | 165 |         return mPerformanceMode; | 
 | 166 |     } | 
 | 167 |  | 
 | 168 |     void setPerformanceMode(aaudio_performance_mode_t performanceMode) { | 
 | 169 |         mPerformanceMode = performanceMode; | 
 | 170 |     } | 
 | 171 |  | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 172 |     aaudio_usage_t getUsage() const { | 
 | 173 |         return mUsage; | 
 | 174 |     } | 
 | 175 |  | 
 | 176 |     void setUsage(aaudio_usage_t usage) { | 
 | 177 |         mUsage = usage; | 
 | 178 |     } | 
 | 179 |  | 
 | 180 |     aaudio_content_type_t getContentType() const { | 
 | 181 |         return mContentType; | 
 | 182 |     } | 
 | 183 |  | 
 | 184 |     void setContentType(aaudio_content_type_t contentType) { | 
 | 185 |         mContentType = contentType; | 
 | 186 |     } | 
 | 187 |  | 
 | 188 |     aaudio_input_preset_t getInputPreset() const { | 
 | 189 |         return mInputPreset; | 
 | 190 |     } | 
 | 191 |  | 
 | 192 |     void setInputPreset(aaudio_input_preset_t inputPreset) { | 
 | 193 |         mInputPreset = inputPreset; | 
 | 194 |     } | 
 | 195 |  | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 196 |     aaudio_allowed_capture_policy_t getAllowedCapturePolicy() const { | 
 | 197 |         return mAllowedCapturePolicy; | 
 | 198 |     } | 
 | 199 |  | 
 | 200 |     void setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy) { | 
 | 201 |         mAllowedCapturePolicy = policy; | 
 | 202 |     } | 
 | 203 |  | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 204 |     int32_t getDeviceId() const { | 
 | 205 |         return mDeviceId; | 
 | 206 |     } | 
 | 207 |  | 
 | 208 |     void setDeviceId(int32_t deviceId) { | 
 | 209 |         mDeviceId = deviceId; | 
 | 210 |     } | 
 | 211 |  | 
 | 212 |     int32_t getNumberOfBursts() const { | 
 | 213 |         return mNumberOfBursts; | 
 | 214 |     } | 
 | 215 |  | 
 | 216 |     void setNumberOfBursts(int32_t numBursts) { | 
 | 217 |         mNumberOfBursts = numBursts; | 
 | 218 |     } | 
 | 219 |  | 
| Phil Burk | 10ffb19 | 2018-09-26 12:09:00 -0700 | [diff] [blame] | 220 |     int32_t getFramesPerCallback() const { | 
 | 221 |         return mFramesPerCallback; | 
 | 222 |     } | 
 | 223 |     void setFramesPerCallback(int32_t size) { | 
 | 224 |         mFramesPerCallback = size; | 
 | 225 |     } | 
 | 226 |  | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 227 |     int32_t isPrivacySensitive() const { | 
 | 228 |         return mPrivacySensitive; | 
 | 229 |     } | 
 | 230 |  | 
 | 231 |     void setPrivacySensitive(int32_t privacySensitive) { | 
 | 232 |         mPrivacySensitive = privacySensitive; | 
 | 233 |     } | 
 | 234 |  | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 235 |     /** | 
 | 236 |      * Apply these parameters to a stream builder. | 
 | 237 |      * @param builder | 
 | 238 |      */ | 
 | 239 |     void applyParameters(AAudioStreamBuilder *builder) const { | 
| Phil Burk | e0a4d2a | 2018-11-05 11:40:36 -0800 | [diff] [blame] | 240 |         AAudioStreamBuilder_setBufferCapacityInFrames(builder, getBufferCapacity()); | 
| Phil Burk | 10ffb19 | 2018-09-26 12:09:00 -0700 | [diff] [blame] | 241 |         AAudioStreamBuilder_setChannelCount(builder, mChannelCount); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 242 |         AAudioStreamBuilder_setDeviceId(builder, mDeviceId); | 
| Phil Burk | 10ffb19 | 2018-09-26 12:09:00 -0700 | [diff] [blame] | 243 |         AAudioStreamBuilder_setFormat(builder, mFormat); | 
 | 244 |         AAudioStreamBuilder_setFramesPerDataCallback(builder, mFramesPerCallback); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 245 |         AAudioStreamBuilder_setPerformanceMode(builder, mPerformanceMode); | 
| Phil Burk | 10ffb19 | 2018-09-26 12:09:00 -0700 | [diff] [blame] | 246 |         AAudioStreamBuilder_setSampleRate(builder, mSampleRate); | 
 | 247 |         AAudioStreamBuilder_setSharingMode(builder, mSharingMode); | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 248 |  | 
 | 249 |         // Call P functions if supported. | 
 | 250 |         loadFutureFunctions(); | 
 | 251 |         if (s_setUsage != nullptr) { | 
 | 252 |             s_setUsage(builder, mUsage); | 
 | 253 |         } else if (mUsage != AAUDIO_UNSPECIFIED){ | 
 | 254 |             printf("WARNING: setUsage not supported"); | 
 | 255 |         } | 
 | 256 |         if (s_setContentType != nullptr) { | 
 | 257 |             s_setContentType(builder, mContentType); | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 258 |         } else if (mContentType != AAUDIO_UNSPECIFIED){ | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 259 |             printf("WARNING: setContentType not supported"); | 
 | 260 |         } | 
 | 261 |         if (s_setInputPreset != nullptr) { | 
 | 262 |             s_setInputPreset(builder, mInputPreset); | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 263 |         } else if (mInputPreset != AAUDIO_UNSPECIFIED){ | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 264 |             printf("WARNING: setInputPreset not supported"); | 
 | 265 |         } | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 266 |  | 
 | 267 |         // Call Q functions if supported. | 
 | 268 |         if (s_setAllowedCapturePolicy != nullptr) { | 
 | 269 |             s_setAllowedCapturePolicy(builder, mAllowedCapturePolicy); | 
 | 270 |         } else if (mAllowedCapturePolicy != AAUDIO_UNSPECIFIED){ | 
 | 271 |             printf("WARNING: setAllowedCapturePolicy not supported"); | 
 | 272 |         } | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 273 |  | 
 | 274 |         if (mPrivacySensitive != PRIVACY_SENSITIVE_DEFAULT) { | 
 | 275 |             if (s_setPrivacySensitive != nullptr) { | 
 | 276 |                 s_setPrivacySensitive(builder, | 
 | 277 |                     mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED); | 
 | 278 |             } else { | 
 | 279 |                 printf("WARNING: setPrivacySensitive not supported"); | 
 | 280 |             } | 
 | 281 |         } | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 282 |     } | 
 | 283 |  | 
| Phil Burk | bad0f57 | 2019-03-29 11:03:13 -0700 | [diff] [blame] | 284 |     static constexpr int32_t   kDefaultNumberOfBursts = 2; | 
 | 285 |  | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 286 | private: | 
 | 287 |     int32_t                    mChannelCount    = AAUDIO_UNSPECIFIED; | 
 | 288 |     aaudio_format_t            mFormat          = AAUDIO_FORMAT_UNSPECIFIED; | 
 | 289 |     int32_t                    mSampleRate      = AAUDIO_UNSPECIFIED; | 
 | 290 |  | 
 | 291 |     int32_t                    mBufferCapacity  = AAUDIO_UNSPECIFIED; | 
 | 292 |     int32_t                    mDeviceId        = AAUDIO_UNSPECIFIED; | 
 | 293 |     aaudio_sharing_mode_t      mSharingMode     = AAUDIO_SHARING_MODE_SHARED; | 
 | 294 |     aaudio_performance_mode_t  mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE; | 
 | 295 |  | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 296 |     aaudio_usage_t             mUsage           = AAUDIO_UNSPECIFIED; | 
 | 297 |     aaudio_content_type_t      mContentType     = AAUDIO_UNSPECIFIED; | 
 | 298 |     aaudio_input_preset_t      mInputPreset     = AAUDIO_UNSPECIFIED; | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 299 |     aaudio_allowed_capture_policy_t mAllowedCapturePolicy     = AAUDIO_UNSPECIFIED; | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 300 |  | 
| Phil Burk | bad0f57 | 2019-03-29 11:03:13 -0700 | [diff] [blame] | 301 |     int32_t                    mNumberOfBursts  = kDefaultNumberOfBursts; | 
| Phil Burk | 10ffb19 | 2018-09-26 12:09:00 -0700 | [diff] [blame] | 302 |     int32_t                    mFramesPerCallback = AAUDIO_UNSPECIFIED; | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 303 |  | 
 | 304 |     enum { | 
 | 305 |         PRIVACY_SENSITIVE_DEFAULT = -1, | 
 | 306 |         PRIVACY_SENSITIVE_DISABLED = 0, | 
 | 307 |         PRIVACY_SENSITIVE_ENABLED = 1, | 
 | 308 |     }; | 
 | 309 |     int32_t                    mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT; | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 310 | }; | 
 | 311 |  | 
 | 312 | class AAudioArgsParser : public AAudioParameters { | 
 | 313 | public: | 
 | 314 |     AAudioArgsParser() = default; | 
 | 315 |     ~AAudioArgsParser() = default; | 
 | 316 |  | 
 | 317 |     enum { | 
 | 318 |         DEFAULT_DURATION_SECONDS = 5 | 
 | 319 |     }; | 
 | 320 |  | 
 | 321 |     /** | 
 | 322 |      * @param arg | 
 | 323 |      * @return true if the argument was not handled | 
 | 324 |      */ | 
 | 325 |     bool parseArg(const char *arg) { | 
 | 326 |         bool unrecognized = false; | 
 | 327 |         if (arg[0] == '-') { | 
 | 328 |             char option = arg[1]; | 
 | 329 |             switch (option) { | 
 | 330 |                 case 'b': | 
 | 331 |                     setBufferCapacity(atoi(&arg[2])); | 
 | 332 |                     break; | 
 | 333 |                 case 'c': | 
 | 334 |                     setChannelCount(atoi(&arg[2])); | 
 | 335 |                     break; | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 336 |                 case 'C': | 
 | 337 |                     setAllowedCapturePolicy(parseAllowedCapturePolicy(arg[2])); | 
 | 338 |                     break; | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 339 |                 case 'd': | 
| Phil Burk | e008d02 | 2017-08-23 12:56:15 -0700 | [diff] [blame] | 340 |                     setDeviceId(atoi(&arg[2])); | 
 | 341 |                     break; | 
| Phil Burk | dd574ca | 2018-04-04 14:41:28 -0700 | [diff] [blame] | 342 |                 case 'f': | 
 | 343 |                     setFormat(atoi(&arg[2])); | 
 | 344 |                     break; | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 345 |                 case 'i': | 
 | 346 |                     setInputPreset(atoi(&arg[2])); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 347 |                     break; | 
| Phil Burk | fcf9efd | 2017-07-14 08:25:08 -0700 | [diff] [blame] | 348 |                 case 'm': { | 
 | 349 |                     aaudio_policy_t policy = AAUDIO_POLICY_AUTO; | 
 | 350 |                     if (strlen(arg) > 2) { | 
 | 351 |                         policy = atoi(&arg[2]); | 
 | 352 |                     } | 
| Phil Burk | e0a4d2a | 2018-11-05 11:40:36 -0800 | [diff] [blame] | 353 |                     if (AAudio_setMMapPolicy(policy) != AAUDIO_OK) { | 
| Kevin Rocard | 9dcd34f | 2018-06-13 16:19:36 -0700 | [diff] [blame] | 354 |                         printf("ERROR: invalid MMAP policy mode %i\n", policy); | 
 | 355 |                     } | 
| Phil Burk | fcf9efd | 2017-07-14 08:25:08 -0700 | [diff] [blame] | 356 |                 } break; | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 357 |                 case 'n': | 
 | 358 |                     setNumberOfBursts(atoi(&arg[2])); | 
 | 359 |                     break; | 
 | 360 |                 case 'p': | 
 | 361 |                     setPerformanceMode(parsePerformanceMode(arg[2])); | 
 | 362 |                     break; | 
 | 363 |                 case 'r': | 
 | 364 |                     setSampleRate(atoi(&arg[2])); | 
 | 365 |                     break; | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 366 |                 case 's': | 
 | 367 |                     mDurationSeconds = atoi(&arg[2]); | 
 | 368 |                     break; | 
 | 369 |                 case 'u': | 
 | 370 |                     setUsage(atoi(&arg[2])); | 
 | 371 |                     break; | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 372 |                 case 'x': | 
 | 373 |                     setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE); | 
 | 374 |                     break; | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 375 |                 case 'y': | 
 | 376 |                     setContentType(atoi(&arg[2])); | 
 | 377 |                     break; | 
| Phil Burk | 10ffb19 | 2018-09-26 12:09:00 -0700 | [diff] [blame] | 378 |                 case 'z': | 
 | 379 |                     setFramesPerCallback(atoi(&arg[2])); | 
 | 380 |                     break; | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 381 |                 case 'S': | 
 | 382 |                     setPrivacySensitive(atoi(&arg[2])); | 
 | 383 |                     break; | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 384 |                 default: | 
 | 385 |                     unrecognized = true; | 
 | 386 |                     break; | 
 | 387 |             } | 
 | 388 |         } | 
 | 389 |         return unrecognized; | 
 | 390 |     } | 
 | 391 |  | 
 | 392 |     /** | 
 | 393 |      * | 
 | 394 |      * @param argc | 
 | 395 |      * @param argv | 
 | 396 |      * @return true if an unrecognized argument was passed | 
 | 397 |      */ | 
 | 398 |     bool parseArgs(int argc, const char **argv) { | 
 | 399 |         for (int i = 1; i < argc; i++) { | 
 | 400 |             const char *arg = argv[i]; | 
 | 401 |             if (parseArg(arg)) { | 
 | 402 |                 usage(); | 
 | 403 |                 return true; | 
 | 404 |             } | 
 | 405 |  | 
 | 406 |         } | 
 | 407 |         return false; | 
 | 408 |     } | 
 | 409 |  | 
 | 410 |     static void usage() { | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 411 |         printf("-c{channels} -d{deviceId} -m{mmapPolicy} -n{burstsPerBuffer} -p{perfMode}"); | 
 | 412 |         printf(" -r{rate} -s{seconds} -x\n"); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 413 |         printf("      Default values are UNSPECIFIED unless otherwise stated.\n"); | 
 | 414 |         printf("      -b{bufferCapacity} frames\n"); | 
 | 415 |         printf("      -c{channels} for example 2 for stereo\n"); | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 416 |         printf("      -C{a|s|n} set playback capture policy\n"); | 
 | 417 |         printf("          a = _ALL (default)\n"); | 
 | 418 |         printf("          s = _SYSTEM\n"); | 
 | 419 |         printf("          n = _NONE\n"); | 
| Phil Burk | e008d02 | 2017-08-23 12:56:15 -0700 | [diff] [blame] | 420 |         printf("      -d{deviceId} default is %d\n", AAUDIO_UNSPECIFIED); | 
| Phil Burk | dd574ca | 2018-04-04 14:41:28 -0700 | [diff] [blame] | 421 |         printf("      -f{0|1|2} set format\n"); | 
 | 422 |         printf("          0 = UNSPECIFIED\n"); | 
 | 423 |         printf("          1 = PCM_I16\n"); | 
| Phil Burk | b658630 | 2020-11-12 20:18:00 +0000 | [diff] [blame] | 424 |         printf("          2 = PCM_FLOAT\n"); | 
 | 425 |         printf("          3 = PCM_I24_PACKED\n"); | 
 | 426 |         printf("          4 = PCM_I32\n"); | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 427 |         printf("      -i{inputPreset} eg. 5 for AAUDIO_INPUT_PRESET_CAMCORDER\n"); | 
| Phil Burk | fcf9efd | 2017-07-14 08:25:08 -0700 | [diff] [blame] | 428 |         printf("      -m{0|1|2|3} set MMAP policy\n"); | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 429 |         printf("          0 = _UNSPECIFIED, use aaudio.mmap_policy system property, default\n"); | 
 | 430 |         printf("          1 = _NEVER, never use MMAP\n"); | 
 | 431 |         printf("          2 = _AUTO, use MMAP if available, default for -m with no number\n"); | 
 | 432 |         printf("          3 = _ALWAYS, use MMAP or fail\n"); | 
| Phil Burk | bad0f57 | 2019-03-29 11:03:13 -0700 | [diff] [blame] | 433 |         printf("      -n{numberOfBursts} for setBufferSize, default %d\n", kDefaultNumberOfBursts); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 434 |         printf("      -p{performanceMode} set output AAUDIO_PERFORMANCE_MODE*, default NONE\n"); | 
 | 435 |         printf("          n for _NONE\n"); | 
 | 436 |         printf("          l for _LATENCY\n"); | 
 | 437 |         printf("          p for _POWER_SAVING;\n"); | 
 | 438 |         printf("      -r{sampleRate} for example 44100\n"); | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 439 |         printf("      -s{duration} in seconds, default is %d\n", DEFAULT_DURATION_SECONDS); | 
 | 440 |         printf("      -u{usage} eg. 14 for AAUDIO_USAGE_GAME\n"); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 441 |         printf("      -x to use EXCLUSIVE mode\n"); | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 442 |         printf("      -y{contentType} eg. 1 for AAUDIO_CONTENT_TYPE_SPEECH\n"); | 
| Phil Burk | 10ffb19 | 2018-09-26 12:09:00 -0700 | [diff] [blame] | 443 |         printf("      -z{callbackSize} or block size, in frames, default = 0\n"); | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 444 |         printf("      -S{0|1} set privacy Sensitive enabled or disabled\n"); | 
 | 445 |         printf("          0 = disabled\n"); | 
 | 446 |         printf("          1 = enabled\n"); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 447 |     } | 
 | 448 |  | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 449 |     static aaudio_performance_mode_t parseAllowedCapturePolicy(char c) { | 
 | 450 |         aaudio_allowed_capture_policy_t policy = AAUDIO_ALLOW_CAPTURE_BY_ALL; | 
 | 451 |         switch (c) { | 
 | 452 |             case 'a': | 
 | 453 |                 policy = AAUDIO_ALLOW_CAPTURE_BY_ALL; | 
 | 454 |                 break; | 
 | 455 |             case 's': | 
 | 456 |                 policy = AAUDIO_ALLOW_CAPTURE_BY_SYSTEM; | 
 | 457 |                 break; | 
 | 458 |             case 'n': | 
 | 459 |                 policy = AAUDIO_ALLOW_CAPTURE_BY_NONE; | 
 | 460 |                 break; | 
 | 461 |             default: | 
 | 462 |                 printf("ERROR: invalid playback capture policy %c\n", c); | 
 | 463 |                 break; | 
 | 464 |         } | 
 | 465 |         return policy; | 
 | 466 |     } | 
 | 467 |  | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 468 |     static aaudio_performance_mode_t parsePerformanceMode(char c) { | 
 | 469 |         aaudio_performance_mode_t mode = AAUDIO_PERFORMANCE_MODE_NONE; | 
 | 470 |         switch (c) { | 
 | 471 |             case 'n': | 
 | 472 |                 mode = AAUDIO_PERFORMANCE_MODE_NONE; | 
 | 473 |                 break; | 
 | 474 |             case 'l': | 
 | 475 |                 mode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY; | 
 | 476 |                 break; | 
 | 477 |             case 'p': | 
 | 478 |                 mode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING; | 
 | 479 |                 break; | 
 | 480 |             default: | 
| Kevin Rocard | 9dcd34f | 2018-06-13 16:19:36 -0700 | [diff] [blame] | 481 |                 printf("ERROR: invalid performance mode %c\n", c); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 482 |                 break; | 
 | 483 |         } | 
 | 484 |         return mode; | 
 | 485 |     } | 
 | 486 |  | 
 | 487 |     /** | 
 | 488 |      * Print stream parameters in comparison with requested values. | 
 | 489 |      * @param stream | 
 | 490 |      */ | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 491 |     void compareWithStream(AAudioStream *stream) const { | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 492 |  | 
 | 493 |         printf("  DeviceId:     requested = %d, actual = %d\n", | 
 | 494 |                getDeviceId(), AAudioStream_getDeviceId(stream)); | 
 | 495 |  | 
 | 496 |         aaudio_stream_state_t state = AAudioStream_getState(stream); | 
 | 497 |         printf("  State:        %s\n", AAudio_convertStreamStateToText(state)); | 
 | 498 |  | 
 | 499 |         // Check to see what kind of stream we actually got. | 
 | 500 |         printf("  SampleRate:   requested = %d, actual = %d\n", | 
 | 501 |                getSampleRate(), AAudioStream_getSampleRate(stream)); | 
 | 502 |  | 
 | 503 |         printf("  ChannelCount: requested = %d, actual = %d\n", | 
 | 504 |                getChannelCount(), AAudioStream_getChannelCount(stream)); | 
 | 505 |  | 
 | 506 |         printf("  DataFormat:   requested = %d, actual = %d\n", | 
 | 507 |                getFormat(), AAudioStream_getFormat(stream)); | 
 | 508 |  | 
 | 509 |         int32_t framesPerBurst = AAudioStream_getFramesPerBurst(stream); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 510 |         printf("  Buffer:       burst     = %d\n", framesPerBurst); | 
| Phil Burk | bad0f57 | 2019-03-29 11:03:13 -0700 | [diff] [blame] | 511 |  | 
 | 512 |         int32_t sizeFrames = AAudioStream_getBufferSizeInFrames(stream); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 513 |         if (framesPerBurst > 0) { | 
| Phil Burk | bad0f57 | 2019-03-29 11:03:13 -0700 | [diff] [blame] | 514 |             int32_t requestedSize = getNumberOfBursts() * framesPerBurst; | 
 | 515 |             printf("  BufferSize:   requested = %4d, actual = %4d = (%d * %d) + %d\n", | 
 | 516 |                    requestedSize, | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 517 |                    sizeFrames, | 
 | 518 |                    (sizeFrames / framesPerBurst), | 
 | 519 |                    framesPerBurst, | 
 | 520 |                    (sizeFrames % framesPerBurst)); | 
| Phil Burk | bad0f57 | 2019-03-29 11:03:13 -0700 | [diff] [blame] | 521 |         } else { | 
 | 522 |              printf("  BufferSize:    %d\n", sizeFrames); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 523 |         } | 
| Phil Burk | bad0f57 | 2019-03-29 11:03:13 -0700 | [diff] [blame] | 524 |  | 
 | 525 |         int32_t capacityFrames = AAudioStream_getBufferCapacityInFrames(stream); | 
 | 526 |         printf("  Capacity:     requested = %4d, actual = %4d = (%d * %d) + %d\n", | 
 | 527 |                getBufferCapacity(), | 
 | 528 |                capacityFrames, | 
 | 529 |                (capacityFrames / framesPerBurst), | 
 | 530 |                framesPerBurst, | 
 | 531 |                (capacityFrames % framesPerBurst)); | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 532 |  | 
| Phil Burk | 10ffb19 | 2018-09-26 12:09:00 -0700 | [diff] [blame] | 533 |         printf("  CallbackSize: requested = %d, actual = %d\n", getFramesPerCallback(), | 
 | 534 |                AAudioStream_getFramesPerDataCallback(stream)); | 
 | 535 |  | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 536 |         printf("  SharingMode:  requested = %s, actual = %s\n", | 
 | 537 |                getSharingModeText(getSharingMode()), | 
 | 538 |                getSharingModeText(AAudioStream_getSharingMode(stream))); | 
 | 539 |  | 
 | 540 |         printf("  PerformanceMode: requested = %d, actual = %d\n", | 
 | 541 |                getPerformanceMode(), AAudioStream_getPerformanceMode(stream)); | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 542 |  | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 543 |         loadFutureFunctions(); | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 544 |  | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 545 |         if (s_setUsage != nullptr) { | 
 | 546 |             printf("  Usage:        requested = %d, actual = %d\n", | 
 | 547 |                    getUsage(), s_getUsage(stream)); | 
 | 548 |         } | 
 | 549 |         if (s_getContentType != nullptr) { | 
 | 550 |             printf("  ContentType:  requested = %d, actual = %d\n", | 
 | 551 |                    getContentType(), s_getContentType(stream)); | 
 | 552 |         } | 
 | 553 |  | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 554 |         if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT) { | 
 | 555 |             if (s_getInputPreset != nullptr) { | 
| Phil Burk | 4e98efa | 2018-02-05 18:41:55 -0800 | [diff] [blame] | 556 |                 printf("  InputPreset:  requested = %d, actual = %d\n", | 
 | 557 |                        getInputPreset(), s_getInputPreset(stream)); | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 558 |             } | 
 | 559 |             if (s_isPrivacySensitive != nullptr) { | 
 | 560 |                 printf("  Privacy Sensitive:  requested = %d, actual = %d\n", | 
 | 561 |                        isPrivacySensitive(), s_isPrivacySensitive(stream)); | 
 | 562 |             } | 
| Phil Burk | 6d6f3f6 | 2018-01-12 17:27:54 -0800 | [diff] [blame] | 563 |         } | 
 | 564 |  | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 565 |         printf("  Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream) | 
 | 566 |                ? "yes" : "no"); | 
 | 567 |  | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 568 |         if (s_getAllowedCapturePolicy != nullptr) { | 
 | 569 |             printf("  ContentType:  requested = %d, actual = %d\n", | 
 | 570 |                    getAllowedCapturePolicy(), s_getAllowedCapturePolicy(stream)); | 
 | 571 |         } | 
 | 572 |  | 
| Phil Burk | 4479523 | 2017-06-30 16:27:38 -0700 | [diff] [blame] | 573 |     } | 
 | 574 |  | 
 | 575 |     int32_t getDurationSeconds() const { | 
 | 576 |         return mDurationSeconds; | 
 | 577 |     } | 
 | 578 |  | 
 | 579 |     void setDurationSeconds(int32_t seconds) { | 
 | 580 |         mDurationSeconds = seconds; | 
 | 581 |     } | 
 | 582 |  | 
 | 583 | private: | 
 | 584 |     int32_t      mDurationSeconds = DEFAULT_DURATION_SECONDS; | 
 | 585 | }; | 
 | 586 |  | 
 | 587 | #endif // AAUDIO_EXAMPLE_ARGS_PARSER_H |