Граф коммитов

1057 Коммитов

Автор SHA1 Сообщение Дата
Chun-Min Chang 1607f2f0d3 Only ignore DeviceIsAlive event if no other events
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.
2022-03-14 09:35:44 -07:00
Chun-Min Chang a616bf062f Simplify the event logs 2022-03-14 09:35:44 -07:00
Chun-Min Chang 720c797d12 Make PropertySelector enum 2022-03-14 09:35:44 -07:00
Chun-Min Chang cde02a7627 Assert we won't get unexpected events 2022-03-14 09:35:44 -07:00
Chun-Min Chang 63a1b2d562 Avoid busy waiting 2022-03-14 09:35:44 -07:00
Chun-Min Chang 3dad5e11c4 Add more debugging logs to show the test status 2022-03-14 09:35:44 -07:00
Chun-Min Chang 73c26d107b Replace FIXIT by FIXME 2022-03-14 09:35:44 -07:00
Chun-Min Chang a7999fb0c7 Add more comments for device tests 2022-03-14 09:35:44 -07:00
Chun-Min Chang b44c0f2c1c Fix typo 2022-03-14 09:35:44 -07:00
Chun-Min Chang 059ddf37be Add device selection for stream tester
It would be much easier to test the stream with different devices if we
can set the device for the stream in test_stream_tester
2022-02-28 12:35:02 -08:00
Chun-Min Chang 0a35299b99
Merge pull request #147 from ChunMinChang/fix-device-changed-test
Fix device-changed test for duplex stream when we have only one input and multiple output
2022-02-25 08:26:12 -08:00
Chun-Min Chang 28b89399e7 Correct the test logic for device_changed_callback
`test_register_device_changed_callback_to_check_default_device_changed_duplex`
fails when we have a single input device and many output devices.

In the test code, we try to switch the input device but we don't have
any available device at all so the test hangs.

We should not switch the input device for the duplex stream if we only
have one input device.
2022-02-24 20:17:48 -08:00
Chun-Min Chang 4ad80d98da Exclude CubebAggregateDevice when getting device list
We might create a custom cubeb-private aggregate device as our
input-output device when creating a duplex stream. The lifetime of this
aggregate device follows the lifetime of the created duplex stream.

We should not expose it in our test-only device-list getter API.
Otherwise, if we set it to another stream's input or output device, that
aggregate device may die before we finish the test for another stream.

We've done the same thing in our cubeb API. We should do the same for
the test-only API as well.
2022-02-24 20:17:40 -08:00
Chun-Min Chang 87b351b035
Update xcode version on circle ci (#146) 2021-12-29 09:50:30 -08:00
Chun-Min Chang c11f994035
Fix: clippy::needless-late-init (#145) 2021-12-29 09:25:25 -08:00
Chun-Min Chang dea28d0c7d
Fix clippy warnings (#143)
* Allow clippy::non_send_fields_in_send_ty for now

Allow clippy::non_send_fields_in_send_ty for now.
https://github.com/mozilla/cubeb-coreaudio-rs/issues/142 is opened to
track this.

* Fix clippy::question_mark

See https://rust-lang.github.io/rust-clippy/master/#question_mark
2021-12-06 10:36:28 -08:00
Chun-Min Chang 41de71f88c
BMO 1737833 - Return error when reinit fails if input is not defined (#141)
If the stream is output-only, or its input device is system-default, its
reinit failure can lead to hitting an assertion in set_volume since the
program keeps running as the error doesn't occur. We should return an
error instead.
2021-11-10 08:06:16 -08:00
Chun-Min Chang 5ada876e8b
`close` the CoreStreamData if it fails to `setup` (#140)
This should solve the crash on [BMO
1708718](https://bugzilla.mozilla.org/show_bug.cgi?id=1708718).
2021-10-07 08:18:09 -07:00
Chun-Min Chang 5a5bc63d7e
Revise custom group id test (#139)
* Add comments explaining the purpose of the test

* Revise test for the custom group

This solves https://github.com/mozilla/cubeb-coreaudio-rs/issues/138.
When the Blackhole device is installed, both its input and output data
source are the same. As a result, the hash-map whose key is data source
value has collision when the hash-map is used to store both input and
output device's group ids.

To avoid the collision, we should use different hash-map for input
device and output device to store the group id values.
2021-10-05 09:59:34 -07:00
Paul Adenot afe2077961 Always use SAFE_MAX_LATENCY_FRAMES * 2 frames per channel for the ring buffer 2021-10-04 19:39:52 +02:00
Paul Adenot dff88aaf33 Choose the size the input ring buffer based on the stream parameter 2021-10-04 19:39:52 +02:00
Paul Adenot 763be27f3b Update ringbuf to 0.2.6 2021-10-04 19:39:52 +02:00
Chun-Min Chang 6eaf5f2559 Fix dead-code
Fix
https://github.com/mozilla/cubeb-coreaudio-rs/pull/136/checks?check_run_id=3756279581#step:6:49
and https://github.com/mozilla/cubeb-coreaudio-rs/pull/136/checks?check_run_id=3756279581#step:6:57
2021-10-04 12:42:10 +02:00
Chun-Min Chang 79d70fd31d Fix clippy::needless-borrow
Fix
https://github.com/mozilla/cubeb-coreaudio-rs/pull/136/checks?check_run_id=3756279581#step:6:63
and https://github.com/mozilla/cubeb-coreaudio-rs/pull/136/checks?check_run_id=3756279581#step:6:69

See more: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
2021-10-04 12:42:10 +02:00
Chun-Min Chang 1d280186a2 Fix clippy::derivable-impls
Fix https://github.com/mozilla/cubeb-coreaudio-rs/pull/136/checks?check_run_id=3756279581#step:6:80 and https://github.com/mozilla/cubeb-coreaudio-rs/pull/136/checks?check_run_id=3756279581#step:6:96

See more: https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls
2021-10-04 12:42:10 +02:00
Paul Adenot 4ee3b28318 Don't check for `reinit_pending` after entering the branch, since it's updated on another thread. 2021-08-30 14:48:06 +02:00
Chun-Min Chang 17e4e9be3b Revert "Remove unnecessary checks"
This reverts commit 246b787376.
2021-08-30 14:48:06 +02:00
Chun-Min Chang e33d2d39c3
Update links (#134)
Update outdated links. All the cubeb repos are hosted by mozilla now.
2021-07-29 09:23:35 -07:00
Chun-Min Chang 8ae48c16b6
BMO 1721496 - Append silence frames to when switching from A2DP to HFP/HSP (#132)
* BMO 1721496 - Append silence frames to when switching from A2DP to HFP/HSP

No silence frame is fed to resampler when the duplex stream runs on a
bluetooth when the device is switchiing from A2DP to HFP/HSP profile,
which leads to hit an assertion [1] within cubeb resampler.

When the duplex cubeb stream runs on a bluetooth device and the device
is switching from A2DP to HFP/HSP profile, the `input_buffer_manager`
has no input data to be appended [2] in `audiounit_input_callback`. And
then when `audiounit_input_callback` runs, the `buffered_input_frames`
is `0` but `input_frames_needed` is a positive integer greater than `0`.
However, the `input_frames` in this case is equal to
`buffered_input_frames` since neither `switching_device` nor
`frames_read > 0` is `true`.

When the above case happens in the first `audiounit_output_callback`
call, it makes the cubeb resampler hit the assertion in [1]. The `data_`
[3] in the `internal_input_buffer` [4] is `nullptr` when the resampler
is created (`passthrough_resampler` in my case). If the `length` in the
first `push*` [5] is `0`, then the `reserve` won't be called so `data_`
remains `nullptr`, which makes the resampler hit the assertion in [1]

We should append the silence frames to the resampler in this case not
only to avoid hitting the assertion but also to append the silence
frames correctly when we need.

[1] b608f59024/src/cubeb_utils.h (L31)
[2] 8c9bb1e745/src/backend/mod.rs (L409)
[3] b608f59024/src/cubeb_utils.h (L115)
[4] b608f59024/src/cubeb_resampler_internal.h (L112)
[5] b608f59024/src/cubeb_utils.h (L196)
[6] b608f59024/src/cubeb_utils.h (L172)

* Remove unnecessary checks

* Correct frames_read

`frames_read` is added in `audiounit_input_callback` with K frames but
it can be added by K+N frames again when `input_frame_needed` in
`audiounit_output_callback is K+N, where K is non-negative integer and N
is positive integer. The N is the number of the silence frames we add in
the input buffer when input_buffer_manager doesn't have enough frames
resampler needs. The `frames_read` should be added by N, which is
silence frames only, rather than K+N in this case.

* Make `frames_read` always follow input_buffer_manager

We always use `input_buffer_manager.get_linear_data(...)` to get the
input buffer with required frames, so `frames_read` should be the sum of
the required frames.
2021-07-28 10:34:50 -07:00
Chun-Min Chang a9d837c8a1
Correct the input buffer for input-only stream (#133)
The parameter for `get_linear_data` should be *samples* rather than
*frames*.
2021-07-28 10:19:38 -07:00
Chun-Min Chang 0e83b233a5
Fix clippy warnings (#131)
* Fix clippy::needless-borrow

Fix error here: https://github.com/ChunMinChang/cubeb-coreaudio-rs/runs/3126257229#step:6:55

* Fix clippy::strlen-on-c-strings

Fix error here: https://github.com/ChunMinChang/cubeb-coreaudio-rs/runs/3126257229#step:6:72
2021-07-26 10:09:07 -07:00
Chun-Min Chang 8c9bb1e745
Add a GitHub Actions badge (#130) 2021-03-09 21:11:38 -08:00
Chun-Min Chang e74f8e4bbe
Add GitHub Action workflows (#128)
* Set github-action running tests with Rust stable

* Set github-action running tests with Rust nightly

* Skip some sanitizers

* Setup github-action

Add a Github-action setting to run tests with Rust stable and nightly. This setting installs the Rust manually instead of using actions-rs since external actions are generally not available inside the Mozilla GitHub org for security reasons.

* Remove nightly.yml and stable.yml

stable.yml and stable.yml can be replaced by test.yml

* Remove MATRIX_RUST
2021-03-09 17:43:32 -08:00
Chun-Min Chang 8da8f640f9 Add workflows to circle-ci setting 2021-03-09 17:30:21 -08:00
Chun-Min Chang bb524bcabc
Rework test_unplug_a_device_on_an_active_stream (#127)
When we create/add/plug a new device to Mac OS, the newly added device
is possible to be the new default device (depends on system setting?).
In `test_unplug_a_device_on_an_active_stream`, we didn't check if the
default device is the expected one. The created device in that function
could be the default device in some tests, and it could be non-default
device in some tests. We need to check if the created device is default
or non-default before running the tests. Otherwise we may use the wrong
device to run the tests.
2021-03-09 13:55:58 -08:00
Chun-Min Chang 8475507b9e
Replace Travis CI badge by Circle CI badge (#126) 2021-03-07 23:11:27 -08:00
Chun-Min Chang 9366db300b
Add circle-ci setting (#124) 2021-03-07 22:26:03 -08:00
Chun-Min Chang 238f423ce5
Fix a couple of clippy warnings (#123)
* Remove unnecessary trailing semicolon

* clippy fix: unnecessary cast

* clippy fix: from_over_into

See: https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into

* clippy fix: field-reassign-with-default

See https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default
2021-03-05 15:35:46 -08:00
Chun-Min Chang ad56ea14ac
BMO 1692910: Avoid the race between `set_volume` and stream-reinitialization (#122)
* Manual test: Add a command to set stream volume

* Test case - `assertion failed: !unit.is_null()` in `set_volume`

The following commit message demonstrating a possible cause of
the assertion-failed issue in [BMO 1692910](https://bugzilla.mozilla.org/show_bug.cgi?id=1692910)

This is a data-racing issue.  The assertion will be hit when the
1. `set_volume` is called on thread A at the same time when the stream is
   being reinitialized at thread B
2. `set_volume` is called on thread A just after the
   `self.core_stream_data.close()` is called on the thread B, which will
   uninitialize and dispose the AudioUnit called in `set_volume` on
   thread A

This commit adds some delay to give us a room to call the
`AudioUnitStream.set_volume` in the manual test, `test_stream_tester`,
after the `AudioUnitStream.stream.core_stream_data.close()` is called
when the `AudioUnitStream` is being reinitialized

The following log illustrates the steps to hit that assertion in
`AudioUnitStream.set_volume` on purpose:
```
% cargo test test_stream_tester -- --ignored --nocapture
   Compiling cubeb-coreaudio v0.1.0 (/Users/cchang/Work/cubeb-coreaudio-rs)
    Finished test [unoptimized + debuginfo] target(s) in 3.24s
     Running target/debug/deps/cubeb_coreaudio-29d6ac8d8020965d

running 1 test
commands:
	'q': quit
	'c': create a stream
	'd': destroy a stream
	's': start the created stream
	't': stop the created stream
	'r': register a device changed callback
	'v': set volume
c
Select stream type:
1) Input 2) Output 3) In-Out Duplex 4) Back
2
Stream 0x7f86967160f0 created.
commands:
	'q': quit
	'c': create a stream
	'd': destroy a stream
	's': start the created stream
	't': stop the created stream
	'r': register a device changed callback
	'v': set volume
s
state: Started
Stream 0x7f86967160f0 started.
commands:
	'q': quit
	'c': create a stream
	'd': destroy a stream
	's': start the created stream
	't': stop the created stream
	'r': register a device changed callback
	'v': set volume

*******************************************************************
* Switch the audio device here to trigger stream reinitializatoin *
*******************************************************************

1 Reinit > Sleep for 5s
v
thread 'backend::tests::manual::test_stream_tester' panicked at 'assertion failed: !unit.is_null()', src/backend/mod.rs:268:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test backend::tests::manual::test_stream_tester ... FAILED

failures:

failures:
    backend::tests::manual::test_stream_tester

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 182 filtered out
```

* Move `set_volume` to the task-queue running stream reinitialization

One simple way to avoid the data-racing issue mentioned in the previous
commit is to dispatch the `set_volume` task to the same task-queue that
runs the stream reinitialization tasks (it executes the stream
destroying task as well). That is, if `set_volume` task is executed
before stream reinitialization, the volume will be set before the stream
is reinitialized. If the `set_volume` task is executed after stream
reinitialization, the volume will be set after the stream finishes its
reinitialization task.

* Revert "Test case - `assertion failed: !unit.is_null()` in `set_volume`"

This reverts commit 8c1e3f91bd.

* Update README
2021-02-23 11:26:28 -08:00
Matthew Gregan 3d071d733d Remove cubeb_stream_reset_default_device API. 2021-02-17 22:43:06 +13:00
Chun-Min Chang 1e1222d621 Update todo 2020-11-18 11:16:58 -08:00
Chun-Min Chang 58d5056812
Bail out in `activate_clock_drift_compensation` if no enough sub devices (#118)
* Create a custom Error enum for AggregateDevice

* Rename variables whose type is OSStatus

* Bail out if the aggregate device contains less than 2 sub devices

This works around the crash in [BMO 1677766](https://bugzilla.mozilla.org/show_bug.cgi?id=1677766).

It's not clear why the number of the owning sub-devices in the created
aggregate device is less than 2, after setting sub devices from input
and output sides via `AggregateDevice::set_sub_devices_sync`. The
sub-devices should be set synchronously when the above function is
called. Maybe `kAudioObjectPropertyOwnedObjects` is not synchronous or
symmetric to `kAudioAggregateDevicePropertyFullSubDeviceList`, which is
the property set in `AggregateDevice::set_sub_devices_sync`.

If the sub devices are less than 2 (we should have at least one input
and one output) in `AggregateDevice::activate_clock_drift_compensation`,
the `AggregateDevice::new` should bail out with an error returned. Then
the cubeb stream can follow the fallback mechanism to create a duplex
stream without using an aggregate-device.

* Correct LessDevicesThan2 to LessThan2Devices
2020-11-18 11:15:02 -08:00
Chun-Min Chang 87667052a5
Use default channel layout if layout have non silent duplicate channels (#117)
* Use default channel layout if layout have non silent duplicate channels

This solves the [BMO 1675719](https://bugzilla.mozilla.org/show_bug.cgi?id=1675719).

The channel layout set in the output device might have non silent
duplicate channels (e.g., having two Front-Right in the channels), which
is not a valid case of our audio mixer usages. It will lead to a panic in
our code. The Audio MIDI Setup on MacOS disallows setting duplicate
channels within a channel layout. It will throw a "Overlapping Channels"
error in that case. It implies that the "overlapping channels" setting
is not defined by the user. It's likely to be defined in the firmware
instead. Since the user doesn't ask it explicitly, it's not necessary to
accept this kind of layout that is forbidden on Mac OS by default.

When there are duplicate non-silent channel in the output channel
layout, we can ignore this invalid channel layout and apply a standard
SMPTE layout instead.

* Rename
2020-11-10 10:55:51 -08:00
Chun-Min Chang fa166ec97b Update README 2020-10-29 17:45:19 -07:00
Chun-Min Chang 4e4089d513 Add a script to install cubeb-coreaudio within cubeb 2020-10-29 17:33:07 -07:00
Markus Stange d5af7ad763 Respect mach timebase when computing latencies.
This fixes a bug where incorrect position information would be returned
when compiling for Apple Silicon, where mach time values do not map 1:1
to nanoseconds.
See https://developer.apple.com/documentation/apple_silicon/addressing_architectural_differences_in_your_macos_code#3616875
2020-10-21 18:21:39 +01:00
Chun-Min Chang f8abfdba75 Remove docs for `test_add_then_remove_listeners`
`test_add_then_remove_listeners` has been removed for a while
2020-10-15 11:15:27 -07:00
Chun-Min Chang 8cf441870b
Check the listeners are none before registering them (#115)
* Check listener is none before registering it

* Move the comments
2020-10-15 10:52:02 -07:00
Chun-Min Chang faa9c58506
Skip listener-removed assertion if aggregate device is dead (#114)
This patch works around a crash we get in BMO 1658982 [1].

When creating the aggregate device, somehow we will get
`kAudioHardwareBadObjectError` error during `set_sub_devices_sync` step.
This error occurs when removing the device-changed listeners for the
newly created aggregate device. This error implies the aggregate device
is somehow dead. In this case, it's ok to not remove the listener
manually since the listener should receive nothing from a dead device.
We can just return error to indicate the aggregate device isn't
initialized successfully.

We should return the error if sub devices cannot be set. However, this
patch only return the error when timeout of setting the sub devices. The
reason to do so is to investigate when `kAudioHardwareBadObjectError` is
thrown.

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1658982
2020-10-14 16:55:56 -07:00
Matthew Gregan b4f45e18a4 Bump cubeb-backend to 0.8 and add stubbed `StreamOps::set_name` implementation. 2020-10-13 15:54:23 +01:00