aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorPhil Burk <philburk@mobileer.com>2020-11-11 07:30:52 -0800
committerPhil Burk <philburk@mobileer.com>2020-11-18 10:29:42 -0800
commit7b814ba2fcf8badf65b1565c62bafc6561a2cac5 (patch)
tree5546da0bff3d3136e89f4b6bc7e8d41d5eff617e /include
parentf9bc95d1b89ab6d73d7275a091c3eef34661fb79 (diff)
downloadoboe-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.h32
-rw-r--r--include/oboe/AudioStreamBase.h41
-rw-r--r--include/oboe/AudioStreamBuilder.h40
-rw-r--r--include/oboe/AudioStreamCallback.h90
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