1/*
2 * Copyright 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#ifndef AAUDIO_AUDIOSTREAM_H
18#define AAUDIO_AUDIOSTREAM_H
19
20#include <atomic>
21#include <mutex>
22#include <stdint.h>
23#include <aaudio/AAudio.h>
24
25#include "utility/AAudioUtilities.h"
26#include "utility/MonotonicCounter.h"
27
28namespace aaudio {
29
30typedef void *(*aaudio_audio_thread_proc_t)(void *);
31
32class AudioStreamBuilder;
33
34/**
35 * AAudio audio stream.
36 */
37class AudioStream {
38public:
39
40    AudioStream();
41
42    virtual ~AudioStream();
43
44
45    // =========== Begin ABSTRACT methods ===========================
46
47    /* Asynchronous requests.
48     * Use waitForStateChange() to wait for completion.
49     */
50    virtual aaudio_result_t requestStart() = 0;
51    virtual aaudio_result_t requestPause() = 0;
52    virtual aaudio_result_t requestFlush() = 0;
53    virtual aaudio_result_t requestStop() = 0;
54
55    virtual aaudio_result_t getTimestamp(clockid_t clockId,
56                                       int64_t *framePosition,
57                                       int64_t *timeNanoseconds) = 0;
58
59
60    /**
61     * Update state while in the middle of waitForStateChange()
62     * @return
63     */
64    virtual aaudio_result_t updateStateWhileWaiting() = 0;
65
66
67    // =========== End ABSTRACT methods ===========================
68
69    virtual aaudio_result_t waitForStateChange(aaudio_stream_state_t currentState,
70                                               aaudio_stream_state_t *nextState,
71                                               int64_t timeoutNanoseconds);
72
73    /**
74     * Open the stream using the parameters in the builder.
75     * Allocate the necessary resources.
76     */
77    virtual aaudio_result_t open(const AudioStreamBuilder& builder);
78
79    /**
80     * Close the stream and deallocate any resources from the open() call.
81     * It is safe to call close() multiple times.
82     */
83    virtual aaudio_result_t close() {
84        return AAUDIO_OK;
85    }
86
87    virtual aaudio_result_t setBufferSize(int32_t requestedFrames) {
88        return AAUDIO_ERROR_UNIMPLEMENTED;
89    }
90
91    virtual aaudio_result_t createThread(int64_t periodNanoseconds,
92                                       aaudio_audio_thread_proc_t threadProc,
93                                       void *threadArg);
94
95    aaudio_result_t joinThread(void **returnArg, int64_t timeoutNanoseconds);
96
97    virtual aaudio_result_t registerThread() {
98        return AAUDIO_OK;
99    }
100
101    virtual aaudio_result_t unregisterThread() {
102        return AAUDIO_OK;
103    }
104
105    /**
106     * Internal function used to call the audio thread passed by the user.
107     * It is unfortunately public because it needs to be called by a static 'C' function.
108     */
109    void* wrapUserThread();
110
111    // ============== Queries ===========================
112
113    aaudio_stream_state_t getState() const {
114        return mState;
115    }
116
117    virtual int32_t getBufferSize() const {
118        return AAUDIO_ERROR_UNIMPLEMENTED;
119    }
120
121    virtual int32_t getBufferCapacity() const {
122        return AAUDIO_ERROR_UNIMPLEMENTED;
123    }
124
125    virtual int32_t getFramesPerBurst() const {
126        return AAUDIO_ERROR_UNIMPLEMENTED;
127    }
128
129    virtual int32_t getXRunCount() const {
130        return AAUDIO_ERROR_UNIMPLEMENTED;
131    }
132
133    bool isActive() const {
134        return mState == AAUDIO_STREAM_STATE_STARTING || mState == AAUDIO_STREAM_STATE_STARTED;
135    }
136
137    virtual bool isMMap() {
138        return false;
139    }
140
141    aaudio_result_t getSampleRate() const {
142        return mSampleRate;
143    }
144
145    aaudio_format_t getFormat()  const {
146        return mFormat;
147    }
148
149    aaudio_result_t getSamplesPerFrame() const {
150        return mSamplesPerFrame;
151    }
152
153    virtual int32_t getPerformanceMode() const {
154        return mPerformanceMode;
155    }
156
157    void setPerformanceMode(aaudio_performance_mode_t performanceMode) {
158        mPerformanceMode = performanceMode;
159    }
160
161    int32_t getDeviceId() const {
162        return mDeviceId;
163    }
164
165    aaudio_sharing_mode_t getSharingMode() const {
166        return mSharingMode;
167    }
168
169    bool isSharingModeMatchRequired() const {
170        return mSharingModeMatchRequired;
171    }
172
173    virtual aaudio_direction_t getDirection() const = 0;
174
175    /**
176     * This is only valid after setSamplesPerFrame() and setFormat() have been called.
177     */
178    int32_t getBytesPerFrame() const {
179        return mSamplesPerFrame * getBytesPerSample();
180    }
181
182    /**
183     * This is only valid after setFormat() has been called.
184     */
185    int32_t getBytesPerSample() const {
186        return AAudioConvert_formatToSizeInBytes(mFormat);
187    }
188
189    virtual int64_t getFramesWritten() {
190        return mFramesWritten.get();
191    }
192
193    virtual int64_t getFramesRead() {
194        return mFramesRead.get();
195    }
196
197    AAudioStream_dataCallback getDataCallbackProc() const {
198        return mDataCallbackProc;
199    }
200    AAudioStream_errorCallback getErrorCallbackProc() const {
201        return mErrorCallbackProc;
202    }
203
204    void *getDataCallbackUserData() const {
205        return mDataCallbackUserData;
206    }
207    void *getErrorCallbackUserData() const {
208        return mErrorCallbackUserData;
209    }
210
211    int32_t getFramesPerDataCallback() const {
212        return mFramesPerDataCallback;
213    }
214
215    bool isDataCallbackActive() {
216        return (mDataCallbackProc != nullptr) && isActive();
217    }
218
219    // ============== I/O ===========================
220    // A Stream will only implement read() or write() depending on its direction.
221    virtual aaudio_result_t write(const void *buffer,
222                             int32_t numFrames,
223                             int64_t timeoutNanoseconds) {
224        return AAUDIO_ERROR_UNIMPLEMENTED;
225    }
226
227    virtual aaudio_result_t read(void *buffer,
228                            int32_t numFrames,
229                            int64_t timeoutNanoseconds) {
230        return AAUDIO_ERROR_UNIMPLEMENTED;
231    }
232
233protected:
234
235    virtual int64_t incrementFramesWritten(int32_t frames) {
236        return mFramesWritten.increment(frames);
237    }
238
239    virtual int64_t incrementFramesRead(int32_t frames) {
240        return mFramesRead.increment(frames);
241    }
242
243    /**
244     * This should not be called after the open() call.
245     */
246    void setSampleRate(int32_t sampleRate) {
247        mSampleRate = sampleRate;
248    }
249
250    /**
251     * This should not be called after the open() call.
252     */
253    void setSamplesPerFrame(int32_t samplesPerFrame) {
254        mSamplesPerFrame = samplesPerFrame;
255    }
256
257    /**
258     * This should not be called after the open() call.
259     */
260    void setSharingMode(aaudio_sharing_mode_t sharingMode) {
261        mSharingMode = sharingMode;
262    }
263
264    /**
265     * This should not be called after the open() call.
266     */
267    void setFormat(aaudio_format_t format) {
268        mFormat = format;
269    }
270
271    void setState(aaudio_stream_state_t state) {
272        mState = state;
273    }
274
275    void setDeviceId(int32_t deviceId) {
276        mDeviceId = deviceId;
277    }
278
279    std::mutex           mStreamMutex;
280
281    std::atomic<bool>    mCallbackEnabled;
282
283protected:
284    MonotonicCounter     mFramesWritten;
285    MonotonicCounter     mFramesRead;
286
287    void setPeriodNanoseconds(int64_t periodNanoseconds) {
288        mPeriodNanoseconds.store(periodNanoseconds, std::memory_order_release);
289    }
290
291    int64_t getPeriodNanoseconds() {
292        return mPeriodNanoseconds.load(std::memory_order_acquire);
293    }
294
295private:
296    // These do not change after open().
297    int32_t                mSamplesPerFrame = AAUDIO_UNSPECIFIED;
298    int32_t                mSampleRate = AAUDIO_UNSPECIFIED;
299    int32_t                mDeviceId = AAUDIO_UNSPECIFIED;
300    aaudio_sharing_mode_t  mSharingMode = AAUDIO_SHARING_MODE_SHARED;
301    bool                   mSharingModeMatchRequired = false; // must match sharing mode requested
302    aaudio_format_t        mFormat = AAUDIO_FORMAT_UNSPECIFIED;
303    aaudio_stream_state_t  mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
304
305    aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
306
307    // callback ----------------------------------
308
309    AAudioStream_dataCallback   mDataCallbackProc = nullptr;  // external callback functions
310    void                       *mDataCallbackUserData = nullptr;
311    int32_t                     mFramesPerDataCallback = AAUDIO_UNSPECIFIED; // frames
312
313    AAudioStream_errorCallback  mErrorCallbackProc = nullptr;
314    void                       *mErrorCallbackUserData = nullptr;
315
316    // background thread ----------------------------------
317    bool                   mHasThread = false;
318    pthread_t              mThread; // initialized in constructor
319
320    // These are set by the application thread and then read by the audio pthread.
321    std::atomic<int64_t>   mPeriodNanoseconds; // for tuning SCHED_FIFO threads
322    // TODO make atomic?
323    aaudio_audio_thread_proc_t mThreadProc = nullptr;
324    void*                  mThreadArg = nullptr;
325    aaudio_result_t        mThreadRegistrationResult = AAUDIO_OK;
326
327
328};
329
330} /* namespace aaudio */
331
332#endif /* AAUDIO_AUDIOSTREAM_H */
333