diff options
author | Phil Burk <philburk@mobileer.com> | 2020-11-11 07:30:52 -0800 |
---|---|---|
committer | Phil Burk <philburk@mobileer.com> | 2020-11-18 10:29:42 -0800 |
commit | 7b814ba2fcf8badf65b1565c62bafc6561a2cac5 (patch) | |
tree | 5546da0bff3d3136e89f4b6bc7e8d41d5eff617e /include | |
parent | f9bc95d1b89ab6d73d7275a091c3eef34661fb79 (diff) | |
download | oboe-7b814ba2fcf8badf65b1565c62bafc6561a2cac5.tar.gz |
oboe: add AudioStreamDataCallback and AudioStreamErrorCallback
This allows an app to use different callbacks for data processing
and error processing. The AudioStreamCallback inherits
from both interfaces.
There is also a new method: bool onError()
that allows an app to completely override the default
error handling.
This change is backwards compatible with older versions.
Fixes #917
Diffstat (limited to 'include')
-rw-r--r-- | include/oboe/AudioStream.h | 32 | ||||
-rw-r--r-- | include/oboe/AudioStreamBase.h | 41 | ||||
-rw-r--r-- | include/oboe/AudioStreamBuilder.h | 40 | ||||
-rw-r--r-- | include/oboe/AudioStreamCallback.h | 90 |
4 files changed, 176 insertions, 27 deletions
diff --git a/include/oboe/AudioStream.h b/include/oboe/AudioStream.h index a158aafc..c862de6d 100644 --- a/include/oboe/AudioStream.h +++ b/include/oboe/AudioStream.h @@ -393,12 +393,25 @@ public: * Swap old callback for new callback. * This not atomic. * This should only be used internally. - * @param streamCallback - * @return previous streamCallback + * @param dataCallback + * @return previous dataCallback */ - AudioStreamCallback *swapCallback(AudioStreamCallback *streamCallback) { - AudioStreamCallback *previousCallback = mStreamCallback; - mStreamCallback = streamCallback; + AudioStreamDataCallback *swapDataCallback(AudioStreamDataCallback *dataCallback) { + AudioStreamDataCallback *previousCallback = mDataCallback; + mDataCallback = dataCallback; + return previousCallback; + } + + /* + * Swap old callback for new callback. + * This not atomic. + * This should only be used internally. + * @param errorCallback + * @return previous errorCallback + */ + AudioStreamErrorCallback *swapErrorCallback(AudioStreamErrorCallback *errorCallback) { + AudioStreamErrorCallback *previousCallback = mErrorCallback; + mErrorCallback = errorCallback; return previousCallback; } @@ -419,6 +432,13 @@ public: ResultWithValue<int32_t> waitForAvailableFrames(int32_t numFrames, int64_t timeoutNanoseconds); + /** + * @return last result passed from an error callback + */ + virtual oboe::Result getLastErrorCallbackResult() const { + return mErrorCallbackResult; + } + protected: /** @@ -515,8 +535,10 @@ protected: std::mutex mLock; // for synchronizing start/stop/close + oboe::Result mErrorCallbackResult = oboe::Result::OK; private: + // Log the scheduler if it changes. void checkScheduler(); int mPreviousScheduler = -1; diff --git a/include/oboe/AudioStreamBase.h b/include/oboe/AudioStreamBase.h index 787ff20e..73c27dfd 100644 --- a/include/oboe/AudioStreamBase.h +++ b/include/oboe/AudioStreamBase.h @@ -100,10 +100,35 @@ public: int32_t getDeviceId() const { return mDeviceId; } /** - * @return the callback object for this stream, if set. + * For internal use only. + * @return the data callback object for this stream, if set. */ - AudioStreamCallback* getCallback() const { - return mStreamCallback; + AudioStreamDataCallback *getDataCallback() const { + return mDataCallback; + } + + /** + * For internal use only. + * @return the error callback object for this stream, if set. + */ + AudioStreamErrorCallback *getErrorCallback() const { + return mErrorCallback; + } + + /** + * @return true if a data callback was set for this stream + */ + bool isDataCallbackSpecified() const { + return mDataCallback != nullptr; + } + + /** + * Note that if the app does not set an error callback then a + * default one may be provided. + * @return true if an error callback was set for this stream + */ + bool isErrorCallbackSpecified() const { + return mErrorCallback != nullptr; } /** @@ -148,9 +173,15 @@ public: } protected: + /** The callback which will be fired when new data is ready to be read/written. **/ + AudioStreamDataCallback *mDataCallback = nullptr; + + /** The callback which will be fired when an error or a disconnect occurs. **/ + AudioStreamErrorCallback *mErrorCallback = nullptr; + + /** The callback that combines data and error callback. **/ + // AudioStreamCallback *mStreamCallback = nullptr; - /** The callback which will be fired when new data is ready to be read/written **/ - AudioStreamCallback *mStreamCallback = nullptr; /** Number of audio frames which will be requested in each callback */ int32_t mFramesPerCallback = kUnspecified; /** Stream channel count */ diff --git a/include/oboe/AudioStreamBuilder.h b/include/oboe/AudioStreamBuilder.h index 80c5da42..d63578c3 100644 --- a/include/oboe/AudioStreamBuilder.h +++ b/include/oboe/AudioStreamBuilder.h @@ -306,8 +306,44 @@ public: } /** + * Specifies an object to handle data related callbacks from the underlying API. + * + * <strong>Important: See AudioStreamCallback for restrictions on what may be called + * from the callback methods.</strong> + * + * @param dataCallback + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setDataCallback(oboe::AudioStreamDataCallback *dataCallback) { + mDataCallback = dataCallback; + return this; + } + + /** + * Specifies an object to handle error related callbacks from the underlying API. + * This can occur when a stream is disconnected because a headset is plugged in or unplugged. + * It can also occur if the audio service fails or if an exclusive stream is stolen by + * another stream. + * + * <strong>Important: See AudioStreamCallback for restrictions on what may be called + * from the callback methods.</strong> + * + * <strong>When an error callback occurs, the associated stream must be stopped and closed + * in a separate thread.</strong> + * + * @param errorCallback + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setErrorCallback(oboe::AudioStreamErrorCallback *errorCallback) { + mErrorCallback = errorCallback; + return this; + } + + /** * Specifies an object to handle data or error related callbacks from the underlying API. * + * This is the equivalent of calling both setDataCallback() and setErrorCallback(). + * * <strong>Important: See AudioStreamCallback for restrictions on what may be called * from the callback methods.</strong> * @@ -327,7 +363,9 @@ public: * @return pointer to the builder so calls can be chained */ AudioStreamBuilder *setCallback(AudioStreamCallback *streamCallback) { - mStreamCallback = streamCallback; + // Use the same callback object for both, dual inheritance. + mDataCallback = streamCallback; + mErrorCallback = streamCallback; return this; } diff --git a/include/oboe/AudioStreamCallback.h b/include/oboe/AudioStreamCallback.h index f427693e..0018623d 100644 --- a/include/oboe/AudioStreamCallback.h +++ b/include/oboe/AudioStreamCallback.h @@ -24,15 +24,16 @@ namespace oboe { class AudioStream; /** - * AudioStreamCallback defines a callback interface for: - * - * 1) moving data to/from an audio stream using `onAudioReady` + * AudioStreamDataCallback defines a callback interface for + * moving data to/from an audio stream using `onAudioReady` * 2) being alerted when a stream has an error using `onError*` methods * + * It is used with AudioStreamBuilder::setDataCallback(). */ -class AudioStreamCallback { + +class AudioStreamDataCallback { public: - virtual ~AudioStreamCallback() = default; + virtual ~AudioStreamDataCallback() = default; /** * A buffer is ready for processing. @@ -75,21 +76,60 @@ public: * If you need to move data, eg. MIDI commands, in or out of the callback function then * we recommend the use of non-blocking techniques such as an atomic FIFO. * - * @param oboeStream pointer to the associated stream + * @param audioStream pointer to the associated stream * @param audioData buffer containing input data or a place to put output data * @param numFrames number of frames to be processed * @return DataCallbackResult::Continue or DataCallbackResult::Stop */ virtual DataCallbackResult onAudioReady( - AudioStream *oboeStream, + AudioStream *audioStream, void *audioData, int32_t numFrames) = 0; +}; + +/** + * AudioStreamDataCallback defines a callback interface for + * being alerted when a stream has an error or is disconnected + * using `onError*` methods. + * + * It is used with AudioStreamBuilder::setErrorCallback(). + */ +class AudioStreamErrorCallback { +public: + virtual ~AudioStreamErrorCallback() = default; /** - * This will be called when an error occurs on a stream or when the stream is disconnected. + * This will be called first when an error occurs on a stream or when the stream is disconnected. + * + * It can be used to override and customize the normal error processing. + * Use of this method is considered an advanced technique. + * It might, for example, be used if an app want to use a high level lock when + * closing and reopening a stream. + * Or it might be used when an app want to signal a management thread that handles + * all of the stream state. + * + * If this method returns false then + * the stream will be stopped, and onErrorBeforeClose() will be called, + * then the stream will be closed and onErrorAfterClose() will be closed. * - * Note that this will be called on a different thread than the onAudioReady() thread. - * This thread will be created by Oboe. + * If this method returns true then the normal error processing will not occur. + * In that case, the app MUST stop() and close() the stream! + * + * Note that this will be called on a thread created by Oboe. + * + * @param audioStream pointer to the associated stream + * @param error + */ + virtual bool onError(AudioStream* /* audioStream */, Result /* error */) { + return false; // false means the stream will be stopped and closed by Oboe + // return true; // true means the stream will be stopped and closed by the app + } + + /** + * This will be called when an error occurs on a stream or when the stream is disconnected + * and if onError() returns false. + * + * Note that this will be called on a thread created by Oboe. * * The underlying stream will already be stopped by Oboe but not yet closed. * So the stream can be queried. @@ -97,27 +137,45 @@ public: * Do not close or delete the stream in this method because it will be * closed after this method returns. * - * @param oboeStream pointer to the associated stream + * @param audioStream pointer to the associated stream * @param error */ - virtual void onErrorBeforeClose(AudioStream* /* oboeStream */, Result /* error */) {} + virtual void onErrorBeforeClose(AudioStream* /* audioStream */, Result /* error */) {} /** - * This will be called when an error occurs on a stream or when the stream is disconnected. + * This will be called when an error occurs on a stream or when the stream is disconnected + * and if onError() returns false. + * * The underlying AAudio or OpenSL ES stream will already be stopped AND closed by Oboe. * So the underlying stream cannot be referenced. * But you can still query most parameters. * * This callback could be used to reopen a new stream on another device. - * You can safely delete the old AudioStream in this method. * - * @param oboeStream pointer to the associated stream + * @param audioStream pointer to the associated stream * @param error */ - virtual void onErrorAfterClose(AudioStream* /* oboeStream */, Result /* error */) {} + virtual void onErrorAfterClose(AudioStream* /* audioStream */, Result /* error */) {} }; +/** + * AudioStreamCallback defines a callback interface for: + * + * 1) moving data to/from an audio stream using `onAudioReady` + * 2) being alerted when a stream has an error using `onError*` methods + * + * It is used with AudioStreamBuilder::setCallback(). + * + * It combines the interfaces defined by AudioStreamDataCallback and AudioStreamErrorCallback. + * This was the original callback object. We now recommend using the individual interfaces. + */ +class AudioStreamCallback : public AudioStreamDataCallback, + public AudioStreamErrorCallback { +public: + virtual ~AudioStreamCallback() = default; +}; + } // namespace oboe #endif //OBOE_STREAM_CALLBACK_H |