Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/host/alsa/duplex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,12 +349,15 @@ fn process_duplex(
) -> Result<(), Error> {
let mut frames_read = 0;
while frames_read < stream.period_size {
match stream
// Bind the result first: an IO in a match scrutinee lives across the arms, and
// alsa allows only one IO per PCM, so recover_duplex() -> begin_duplex_playback()
// would panic creating a second IO on the playback PCM.
let result = stream
.capture
.handle
.io_bytes()
.readi(&mut capture_buffer[frames_read * stream.capture.frame_size..])
{
.readi(&mut capture_buffer[frames_read * stream.capture.frame_size..]);
match result {
Ok(n) => frames_read += n,
Err(err) if err.errno() == libc::EAGAIN && frames_read == 0 => return Ok(()),
Err(_) if matches!(stream.capture.handle.state(), alsa::pcm::State::Suspended) => {
Expand Down Expand Up @@ -431,12 +434,14 @@ fn process_duplex(

let mut frames_written = 0;
while frames_written < stream.period_size {
match stream
// Bind the result first, as for capture above: recover_duplex() must not run
// while this PCM's IO is still alive.
let result = stream
.playback
.handle
.io_bytes()
.writei(&playback_buffer[frames_written * stream.playback.frame_size..])
{
.writei(&playback_buffer[frames_written * stream.playback.frame_size..]);
match result {
Ok(n) => frames_written += n,
Err(err) if err.errno() == libc::EAGAIN && frames_written == 0 => return Ok(()),
Err(_) if matches!(stream.playback.handle.state(), alsa::pcm::State::Suspended) => {
Expand Down
16 changes: 10 additions & 6 deletions src/host/alsa/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,11 +334,13 @@ fn process_input(
) -> Result<(), Error> {
let mut frames_read = 0;
while frames_read < stream.period_size {
match stream
// Bind the result first: an IO in a match scrutinee lives across the arms, and
// alsa allows only one IO per PCM, so recovery must not run while it is alive.
let result = stream
.handle
.io_bytes()
.readi(&mut buffer[frames_read * stream.frame_size..])
{
.readi(&mut buffer[frames_read * stream.frame_size..]);
match result {
Ok(n) => frames_read += n,
// EAGAIN = no frames available: skip this cycle if no progress was made,
// otherwise treat as an underrun (partial period cannot be delivered safely).
Expand Down Expand Up @@ -419,11 +421,13 @@ fn process_output(

let mut frames_written = 0;
while frames_written < stream.period_size {
match stream
// Bind the result first, as for input above: recovery must not run while
// this PCM's IO is still alive.
let result = stream
.handle
.io_bytes()
.writei(&buffer[frames_written * stream.frame_size..])
{
.writei(&buffer[frames_written * stream.frame_size..]);
match result {
Ok(n) => frames_written += n,
// EAGAIN = device cannot currently accept more frames: skip this cycle if no
// progress was made, otherwise treat as an underrun (partial period cannot be
Expand Down
Loading