This uses an spsc ring buffer to proxy the audio input callback
parameters to the output thread, for logging purposes.
Without this, multiple threads can attempt writing in the spsc ring
buffer that's used for logging, which make an assertion blow up.
* Revert 8c1c57a, keeping the changes in 8b7d464
* Really attempt to create a device_info when reiniting to ensure a valid device is availble.
* Let the OS error out and propagate the error instead of asserting
* Revert "Let the OS error out and propagate the error instead of asserting"
This reverts commit a5fe4208cc.
* Revert "Really attempt to create a device_info when reiniting to ensure a valid device is availble."
This reverts commit 38896988d7.
* Revert "Revert 8c1c57a, keeping the changes in 8b7d464"
This reverts commit 0a82ab619f.
* Fix device reinit when no input/output device are present
Co-authored-by: Chun-Min Chang <chun.m.chang@gmail.com>
* Use get_channel_count for max_channel_count
We use `get_channel_count` for the max channel count in
`enumerate_devices` but we use `get_device_stream_format`'s channel info
for `max_channel_count`. We should use `get_channel_count` instead.
* Return OSStatus as error in get_channel_count
No need to return cubeb-error in non top-level API.
* Shorten the function name
Rename `audiounit_get_default_device_id` to `get_default_device_id`.
* Return error for default device if it's kAudioObjectUnknown
The default output device on CircleCI server is `kAudioObjectUnknown`.
We should return error if we get this kind of device since all its
operations will be invalid.
* Add todo
Remove input_channels_to_ignore from CoreStreamData, and pass it
directly to the BufferManager.
Refactor input_desc so that it's always what we set the input audiounit
to, and subsequently remove input_hw_rate, because it's redundant with
input_desc.mSamplerate.
We don't want to use the regular mixer here, we can do everything in
place, always, and make it very efficient. Also it's specialized and
only handles very few cases.
When using an aggregate device, it can be that the output device has
input channels. Those input channels are delivered in the input callback
as usual, in the same buffer as the input channels of the input device
we care about. The channels for the output device are _always_ first in
the buffer, followed by the channels for the inpuut device, because of
the way the aggregate device is setup (see aggregate_device.rs).
This patch allows remixing the data, dropping the channels we don't want
and putting the frames for the channels the user wants at the right
location in the buffer.
We always monitor the default input changed event even if we don't use
the default input device. As a result, one audio stream has an input can
be re-initialized even if its device has no change at all (e.g., When
default input device is X and the input stream S uses device Y as its
input device, the S will be re-initialized if the system default device
is changed from X to Z, where X, Y, Z are all different devices.).
To avoid the above problem, and not to reinitialize the stream, when it
has input, we should monitor the default-input change only when the user
requests to follow the system default input.
In the current code, theoretically we can fire multiple
device_changed_callbacks at one event handler, but we will at most
re-initialize stream once. There is no need to fire multiple callbacks
if we only reinitialize stream once.
By the comments [1,2] in the BMO 1735201, we should not switch the input
device behind the scenes when users specify what devices they want. That
is, we should not automatically re-initialize the input or duplex stream
when the input device is gone. We will get a device-collection changed
event as well when this happen and Gecko/Firefox will stop the paired
MediaStreamTrack soon in this case.
[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1735201#c0
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=1735201#c11
From the callback API pattern, theoretically it's possible to get
multiple events at the same time. We used to ignore
`kAudioDevicePropertyDeviceIsAlive` event and do nothing when the device
is system input without checking if we have other events at that moment
or not. If we do have other events, we should run other event handler
rather than do nothing in this case.