Backed out 2 changesets (bug 1687070) for causing failures on cubeb.drain, cubeb.tone. CLOSED TREE

Backed out changeset 65dd5e6a60fe (bug 1687070)
Backed out changeset fd7fa895cdef (bug 1687070)
This commit is contained in:
Marian-Vasile Laza 2021-07-16 15:16:05 +03:00
parent 999d851597
commit 408a169597
11 changed files with 200 additions and 157 deletions

View File

@ -25,7 +25,7 @@ rev = "1bb484e96ae724309e3346968e8ffd4c25e61616"
[source."https://github.com/mozilla/cubeb-pulse-rs"]
git = "https://github.com/mozilla/cubeb-pulse-rs"
replace-with = "vendored-sources"
rev = "c3a51357f9674756311848bf1e5966a0b7c3eef9"
rev = "c87b50aebfa088c1ad30c74819d4e9829f88b2e3"
[source."https://github.com/mozilla/cubeb-coreaudio-rs"]
git = "https://github.com/mozilla/cubeb-coreaudio-rs"

6
Cargo.lock generated
View File

@ -1014,7 +1014,7 @@ dependencies = [
[[package]]
name = "cubeb-pulse"
version = "0.3.0"
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=c3a51357f9674756311848bf1e5966a0b7c3eef9#c3a51357f9674756311848bf1e5966a0b7c3eef9"
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=c87b50aebfa088c1ad30c74819d4e9829f88b2e3#c87b50aebfa088c1ad30c74819d4e9829f88b2e3"
dependencies = [
"cubeb-backend",
"pulse",
@ -3858,7 +3858,7 @@ dependencies = [
[[package]]
name = "pulse"
version = "0.3.0"
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=c3a51357f9674756311848bf1e5966a0b7c3eef9#c3a51357f9674756311848bf1e5966a0b7c3eef9"
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=c87b50aebfa088c1ad30c74819d4e9829f88b2e3#c87b50aebfa088c1ad30c74819d4e9829f88b2e3"
dependencies = [
"bitflags",
"pulse-ffi",
@ -3867,7 +3867,7 @@ dependencies = [
[[package]]
name = "pulse-ffi"
version = "0.1.0"
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=c3a51357f9674756311848bf1e5966a0b7c3eef9#c3a51357f9674756311848bf1e5966a0b7c3eef9"
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=c87b50aebfa088c1ad30c74819d4e9829f88b2e3#c87b50aebfa088c1ad30c74819d4e9829f88b2e3"
dependencies = [
"libc",
]

View File

@ -1 +1 @@
{"files":{".editorconfig":"bf047bd1da10cabb99eea666d1e57c321eba4716dccb3e4ed0e2c5fe3ca53858",".github/workflows/build.yml":"5b35f16e3fba6586f190a623ee9fc8b928f964a1c0be623f12bfb1d8f93f1bed","AUTHORS":"0e0ac930a68ce2f6b876126b195add177f0d3886facb9260f4d9b69f1988f0cc","Cargo.toml":"56e90cb82ec36ead07e551a28fc2455fa658fa8308c3d73f8d856d85bfcd2122","LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","README.md":"0079450bb4b013bac065ed1750851e461a3710ebad1f323817da1cb82db0bc4f","src/backend/context.rs":"14507ac042e0d00d2d27715d523c9dfa09ff4800e5f5b5bca95d1918344dbc4a","src/backend/cork_state.rs":"4a0f1afc7d9f333dac89218cc56d7d32fbffb487cd48c1c9a4e03d79cb3b5e28","src/backend/intern.rs":"374a9a3bd79fddc47739dda1dbfc5929aea5a91946794fe65fba3c8d130fbda9","src/backend/mod.rs":"d5da05348bf1a7f65c85b14372964a49dc4849f0aee96c75e2c18b51fb03fcaf","src/backend/stream.rs":"63e13cb76df62cfc9d9909b608c3136c55f35f680fc44909aab44dfe527d4db2","src/capi.rs":"b2c1be8128cadd36caa65c80950440f9d6f2aa0c24cc7bae6a9eaf6347ac454d","src/lib.rs":"b41bbdc562cbfb130ed7c1e53fe69944774f515705341d8ce48a2f82c8c0c2c5"},"package":null}
{"files":{".editorconfig":"bf047bd1da10cabb99eea666d1e57c321eba4716dccb3e4ed0e2c5fe3ca53858",".travis.yml":"0394e2adb041175457685cde5ee05ff04bdab8885fd8a62551f2ff43d9e48872","AUTHORS":"0e0ac930a68ce2f6b876126b195add177f0d3886facb9260f4d9b69f1988f0cc","Cargo.toml":"56e90cb82ec36ead07e551a28fc2455fa658fa8308c3d73f8d856d85bfcd2122","LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","README.md":"e6a98ee5630b9ce1a096a2907d095454f2770e298a5b0976ab552cc53ca96cfc","src/backend/context.rs":"33d9fdf1504fe1ae43d301e288daf6eaeabeb47aa0ef86efa135c6d984425fc4","src/backend/cork_state.rs":"4a0f1afc7d9f333dac89218cc56d7d32fbffb487cd48c1c9a4e03d79cb3b5e28","src/backend/intern.rs":"374a9a3bd79fddc47739dda1dbfc5929aea5a91946794fe65fba3c8d130fbda9","src/backend/mod.rs":"06ce9250865abf0ea461f215b128470636d072a6776821efef3caf5a7b992fb9","src/backend/stream.rs":"b8700fffb4d1537bc2fd3f0e26e7bbb16bc6e7cc7a803723e06704610ca1f6f5","src/capi.rs":"b2c1be8128cadd36caa65c80950440f9d6f2aa0c24cc7bae6a9eaf6347ac454d","src/lib.rs":"7282560d84b134b09acfd8d6282600982e42fb3557f72454c535637cc26c7bf6"},"package":null}

View File

@ -1,40 +0,0 @@
name: Build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-20.04
continue-on-error: ${{ matrix.experimental }}
strategy:
fail-fast: false
matrix:
rust: [stable]
experimental: [false]
include:
- rust: nightly
experimental: true
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Install Rust
run: rustup toolchain install ${{ matrix.rust }} --profile minimal --component rustfmt
- name: Install Dependencies (Linux)
run: sudo apt-get install libpulse-dev
# - name: Check format
# shell: bash
# run: rustup run ${{ matrix.rust }} cargo fmt --all -- --check
- name: Build
shell: bash
run: rustup run ${{ matrix.rust }} cargo build --all
- name: Test
shell: bash
run: rustup run ${{ matrix.rust }} cargo test --all

View File

@ -0,0 +1,70 @@
language: rust
cache: cargo
notifications:
email:
on_success: never
rust:
# Version 1.36 is the minimum version of rust supported by Gecko.
- 1.36.0
- stable
- nightly
env:
# default jobs with and without optional features.
-
- FEATURES=pulse-dlopen
# Invoke cargo with optional target or features switches.
script: >
cargo test
${TARGET:+--target ${TARGET}}
${FEATURES:+--features ${FEATURES}}
# Install cross target if necessary.
before_install:
if test -n "${TARGET}"; then rustup target add ${TARGET}; fi
addons: &apt_64
apt:
packages:
- libpulse-dev
matrix:
include:
# Add in 32-bit builds
- rust: 1.36.0
env:
- TARGET=i686-unknown-linux-gnu
addons: &apt_32
apt:
packages:
- gcc-multilib
- g++-multilib
- libpulse-dev:i386
- libglib2.0-dev:i386
- rust: 1.36.0
env:
- TARGET=i686-unknown-linux-gnu
- FEATURES=pulse-dlopen
addons: *apt_32
- rust: stable
env:
- TARGET=i686-unknown-linux-gnu
addons: *apt_32
- rust: stable
env:
- TARGET=i686-unknown-linux-gnu
- FEATURES=pulse-dlopen
addons: *apt_32
- rust: nightly
env:
- TARGET=i686-unknown-linux-gnu
addons: *apt_32
- rust: nightly
env:
- TARGET=i686-unknown-linux-gnu
- FEATURES=pulse-dlopen
addons: *apt_32
allow_failures:
- rust: nightly

View File

@ -2,4 +2,5 @@
Implementation of PulseAudio backend for Cubeb written in Rust.
[![Build Status](https://github.com/mozilla/cubeb-pulse-rs/actions/workflows/build.yml/badge.svg)](https://github.com/mozilla/cubeb-pulse-rs/actions/workflows/build.yml)
[![Travis Build Status](https://travis-ci.org/djg/cubeb-pulse-rs.svg?branch=master)](https://travis-ci.org/djg/cubeb-pulse-rs)
[![Travis Build Status](https://travis-ci.org/djg/cubeb-pulse-rs.svg?branch=dev)](https://travis-ci.org/djg/cubeb-pulse-rs)

View File

@ -4,10 +4,8 @@
// accompanying file LICENSE for details.
use backend::*;
use cubeb_backend::{
ffi, log_enabled, Context, ContextOps, DeviceCollectionRef, DeviceId, DeviceType, Error, Ops,
Result, Stream, StreamParams, StreamParamsRef,
};
use cubeb_backend::{ffi, log_enabled, Context, ContextOps, DeviceCollectionRef, DeviceId,
DeviceType, Error, Ops, Result, Stream, StreamParams, StreamParamsRef};
use pulse::{self, ProplistExt};
use pulse_ffi::*;
use semver;
@ -94,8 +92,17 @@ impl PulseContext {
}))
}
fn server_info_cb(context: &pulse::Context, info: Option<&pulse::ServerInfo>, u: *mut c_void) {
fn sink_info_cb(_: &pulse::Context, i: *const pulse::SinkInfo, eol: i32, u: *mut c_void) {
fn server_info_cb(
context: &pulse::Context,
info: Option<&pulse::ServerInfo>,
u: *mut c_void,
) {
fn sink_info_cb(
_: &pulse::Context,
i: *const pulse::SinkInfo,
eol: i32,
u: *mut c_void,
) {
let ctx = unsafe { &mut *(u as *mut PulseContext) };
if eol == 0 {
let info = unsafe { &*i };
@ -213,13 +220,11 @@ impl PulseContext {
}
}
} else if (f == pulse::SubscriptionEventFacility::Server)
&& (t == pulse::SubscriptionEventType::Change)
{
&& (t == pulse::SubscriptionEventType::Change) {
cubeb_log!("Server changed {}", index as i32);
let user_data: *mut c_void = ctx as *mut _ as *mut _;
if let Some(ref context) = ctx.context {
if let Err(e) = context.get_server_info(PulseContext::server_info_cb, user_data)
{
if let Err(e) = context.get_server_info(PulseContext::server_info_cb, user_data) {
cubeb_log!("get_server_info ignored failure: {}", e);
}
}

View File

@ -5,8 +5,8 @@
mod context;
mod cork_state;
mod intern;
mod stream;
mod intern;
pub use self::context::PulseContext;
use self::intern::Intern;

View File

@ -3,24 +3,22 @@
// This program is made available under an ISC-style license. See the
// accompanying file LICENSE for details.
use backend::cork_state::CorkState;
use backend::*;
use cubeb_backend::{
ffi, log_enabled, ChannelLayout, DeviceId, DeviceRef, Error, Result, SampleFormat, StreamOps,
StreamParamsRef, StreamPrefs,
};
use backend::cork_state::CorkState;
use cubeb_backend::{ffi, log_enabled, ChannelLayout, DeviceId, DeviceRef, Error, Result,
SampleFormat, StreamOps, StreamParamsRef, StreamPrefs};
use pulse::{self, CVolumeExt, ChannelMapExt, SampleSpecExt, StreamLatency, USecExt};
use pulse_ffi::*;
use ringbuf::RingBuffer;
use std::{mem, ptr};
use std::ffi::{CStr, CString};
use std::os::raw::{c_long, c_void};
use std::slice;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::{mem, ptr};
use ringbuf::RingBuffer;
use self::LinearInputBuffer::*;
use self::RingBufferConsumer::*;
use self::RingBufferProducer::*;
use self::LinearInputBuffer::*;
const PULSE_NO_GAIN: f32 = -1.0;
@ -103,10 +101,12 @@ fn default_layout_for_channels(ch: u32) -> ChannelLayout {
3 => ChannelLayout::_3F,
4 => ChannelLayout::QUAD,
5 => ChannelLayout::_3F2,
6 => ChannelLayout::_3F_LFE | ChannelLayout::SIDE_LEFT | ChannelLayout::SIDE_RIGHT,
6 => ChannelLayout::_3F_LFE
| ChannelLayout::SIDE_LEFT
| ChannelLayout::SIDE_RIGHT,
7 => ChannelLayout::_3F3R_LFE,
8 => ChannelLayout::_3F4_LFE,
_ => panic!("channel must be between 1 to 8."),
_ => panic!("channel must be between 1 to 8.")
}
}
@ -127,63 +127,58 @@ impl Drop for Device {
enum RingBufferConsumer {
IntegerRingBufferConsumer(ringbuf::Consumer<i16>),
FloatRingBufferConsumer(ringbuf::Consumer<f32>),
FloatRingBufferConsumer(ringbuf::Consumer<f32>)
}
enum RingBufferProducer {
IntegerRingBufferProducer(ringbuf::Producer<i16>),
FloatRingBufferProducer(ringbuf::Producer<f32>),
FloatRingBufferProducer(ringbuf::Producer<f32>)
}
enum LinearInputBuffer {
IntegerLinearInputBuffer(Vec<i16>),
FloatLinearInputBuffer(Vec<f32>),
FloatLinearInputBuffer(Vec<f32>)
}
struct BufferManager {
consumer: RingBufferConsumer,
producer: RingBufferProducer,
linear_input_buffer: LinearInputBuffer,
linear_input_buffer: LinearInputBuffer
}
impl BufferManager {
// When opening a duplex stream, the sample-spec are guaranteed to match. It's ok to have
// either the input or output sample-spec here.
fn new(input_buffer_size: usize, sample_spec: &pulse::SampleSpec) -> BufferManager {
if sample_spec.format == PA_SAMPLE_S16BE || sample_spec.format == PA_SAMPLE_S16LE {
let ring = RingBuffer::<i16>::new(input_buffer_size);
let (prod, cons) = ring.split();
return BufferManager {
producer: IntegerRingBufferProducer(prod),
consumer: IntegerRingBufferConsumer(cons),
linear_input_buffer: IntegerLinearInputBuffer(Vec::<i16>::with_capacity(
input_buffer_size,
)),
};
} else {
let ring = RingBuffer::<f32>::new(input_buffer_size);
let (prod, cons) = ring.split();
return BufferManager {
producer: FloatRingBufferProducer(prod),
consumer: FloatRingBufferConsumer(cons),
linear_input_buffer: FloatLinearInputBuffer(Vec::<f32>::with_capacity(
input_buffer_size,
)),
};
}
if sample_spec.format == PA_SAMPLE_S16BE ||
sample_spec.format == PA_SAMPLE_S16LE {
let ring = RingBuffer::<i16>::new(input_buffer_size);
let (prod, cons) = ring.split();
return BufferManager {
producer: IntegerRingBufferProducer(prod),
consumer: IntegerRingBufferConsumer(cons),
linear_input_buffer: IntegerLinearInputBuffer(Vec::<i16>::with_capacity(input_buffer_size))
};
} else {
let ring = RingBuffer::<f32>::new(input_buffer_size);
let (prod, cons) = ring.split();
return BufferManager {
producer: FloatRingBufferProducer(prod),
consumer: FloatRingBufferConsumer(cons),
linear_input_buffer: FloatLinearInputBuffer(Vec::<f32>::with_capacity(input_buffer_size))
};
}
}
fn push_input_data(&mut self, input_data: *const c_void, read_samples: usize) {
match &mut self.producer {
RingBufferProducer::FloatRingBufferProducer(p) => {
let input_data =
unsafe { slice::from_raw_parts::<f32>(input_data as *const f32, read_samples) };
let input_data = unsafe { slice::from_raw_parts::<f32>(input_data as *const f32, read_samples) };
// we don't do anything in particular if we can't push everything
p.push_slice(input_data);
}
RingBufferProducer::IntegerRingBufferProducer(p) => {
let input_data =
unsafe { slice::from_raw_parts::<i16>(input_data as *const i16, read_samples) };
let input_data = unsafe { slice::from_raw_parts::<i16>(input_data as *const i16, read_samples) };
p.push_slice(input_data);
}
}
@ -192,9 +187,7 @@ impl BufferManager {
fn pull_input_data(&mut self, input_data: *mut c_void, needed_samples: usize) {
match &mut self.consumer {
IntegerRingBufferConsumer(p) => {
let mut input: &mut [i16] = unsafe {
slice::from_raw_parts_mut::<i16>(input_data as *mut i16, needed_samples)
};
let mut input: &mut[i16] = unsafe { slice::from_raw_parts_mut::<i16>(input_data as *mut i16, needed_samples) };
let read = p.pop_slice(&mut input);
if read < needed_samples {
for i in 0..(needed_samples - read) {
@ -203,9 +196,7 @@ impl BufferManager {
}
}
FloatRingBufferConsumer(p) => {
let mut input: &mut [f32] = unsafe {
slice::from_raw_parts_mut::<f32>(input_data as *mut f32, needed_samples)
};
let mut input: &mut[f32] = unsafe { slice::from_raw_parts_mut::<f32>(input_data as *mut f32, needed_samples) };
let read = p.pop_slice(&mut input);
if read < needed_samples {
for i in 0..(needed_samples - read) {
@ -251,8 +242,12 @@ impl BufferManager {
}
pub fn available_samples(&mut self) -> usize {
match &self.linear_input_buffer {
LinearInputBuffer::IntegerLinearInputBuffer(b) => b.len(),
LinearInputBuffer::FloatLinearInputBuffer(b) => b.len(),
LinearInputBuffer::IntegerLinearInputBuffer(b) => {
b.len()
}
LinearInputBuffer::FloatLinearInputBuffer(b) => {
b.len()
}
}
}
}
@ -279,7 +274,7 @@ pub struct PulseStream<'ctx> {
shutdown: bool,
volume: f32,
state: ffi::cubeb_state,
input_buffer_manager: Option<BufferManager>,
input_buffer_manager: Option<BufferManager>
}
impl<'ctx> PulseStream<'ctx> {
@ -334,10 +329,7 @@ impl<'ctx> PulseStream<'ctx> {
if stm.output_stream.is_some() {
// duplex stream: push the input data to the ring buffer.
stm.input_buffer_manager
.as_mut()
.unwrap()
.push_input_data(read_data, read_samples);
stm.input_buffer_manager.as_mut().unwrap().push_input_data(read_data, read_samples);
} else {
// input/capture only operation. Call callback directly
let got = unsafe {
@ -381,13 +373,11 @@ impl<'ctx> PulseStream<'ctx> {
let input_buffer_manager = stm.input_buffer_manager.as_mut().unwrap();
if stm.output_frame_count.fetch_add(nframes, Ordering::SeqCst) == 0 {
let buffered_input_frames = input_buffer_manager.available_samples()
/ stm.input_sample_spec.channels as usize;
let buffered_input_frames = input_buffer_manager.available_samples() / stm.input_sample_spec.channels as usize;
if buffered_input_frames > nframes {
// Trim the buffer to ensure minimal roundtrip latency
let popped_frames = buffered_input_frames - nframes;
input_buffer_manager
.trim(nframes * stm.input_sample_spec.channels as usize);
input_buffer_manager.trim(nframes * stm.input_sample_spec.channels as usize);
cubeb_log!("Dropping {} frames in input buffer.", popped_frames);
}
}
@ -416,7 +406,7 @@ impl<'ctx> PulseStream<'ctx> {
shutdown: false,
volume: PULSE_NO_GAIN,
state: ffi::CUBEB_STATE_ERROR,
input_buffer_manager: None,
input_buffer_manager: None
});
if let Some(ref context) = stm.context.context {
@ -431,15 +421,14 @@ impl<'ctx> PulseStream<'ctx> {
s.set_state_callback(check_error, stm.as_mut() as *mut _ as *mut _);
s.set_write_callback(write_data, stm.as_mut() as *mut _ as *mut _);
let buffer_size_bytes =
latency_frames * stm.output_sample_spec.frame_size() as u32;
let buffer_size_bytes = latency_frames * stm.output_sample_spec.frame_size() as u32;
let battr = pa_buffer_attr {
maxlength: u32::max_value(),
prebuf: 0,
prebuf: u32::max_value(),
fragsize: u32::max_value(),
tlength: buffer_size_bytes * 2,
minreq: buffer_size_bytes / 4,
minreq: buffer_size_bytes / 4
};
let device_name = super::try_cstr_from(output_device as *const _);
let mut stream_flags = pulse::StreamFlags::AUTO_TIMING_UPDATE
@ -449,11 +438,16 @@ impl<'ctx> PulseStream<'ctx> {
if device_name.is_some()
|| stream_params
.prefs()
.contains(StreamPrefs::DISABLE_DEVICE_SWITCHING)
{
stream_flags |= pulse::StreamFlags::DONT_MOVE;
.contains(StreamPrefs::DISABLE_DEVICE_SWITCHING) {
stream_flags |= pulse::StreamFlags::DONT_MOVE;
}
let _ = s.connect_playback(device_name, &battr, stream_flags, None, None);
let _ = s.connect_playback(
device_name,
&battr,
stream_flags,
None,
None,
);
stm.output_stream = Some(s);
}
@ -474,14 +468,13 @@ impl<'ctx> PulseStream<'ctx> {
s.set_state_callback(check_error, stm.as_mut() as *mut _ as *mut _);
s.set_read_callback(read_data, stm.as_mut() as *mut _ as *mut _);
let buffer_size_bytes =
latency_frames * stm.input_sample_spec.frame_size() as u32;
let buffer_size_bytes = latency_frames * stm.input_sample_spec.frame_size() as u32;
let battr = pa_buffer_attr {
maxlength: u32::max_value(),
prebuf: u32::max_value(),
fragsize: buffer_size_bytes,
tlength: buffer_size_bytes,
minreq: buffer_size_bytes,
minreq: buffer_size_bytes
};
let device_name = super::try_cstr_from(input_device as *const _);
let mut stream_flags = pulse::StreamFlags::AUTO_TIMING_UPDATE
@ -491,11 +484,14 @@ impl<'ctx> PulseStream<'ctx> {
if device_name.is_some()
|| stream_params
.prefs()
.contains(StreamPrefs::DISABLE_DEVICE_SWITCHING)
{
.contains(StreamPrefs::DISABLE_DEVICE_SWITCHING) {
stream_flags |= pulse::StreamFlags::DONT_MOVE;
}
let _ = s.connect_record(device_name, &battr, stream_flags);
let _ = s.connect_record(
device_name,
&battr,
stream_flags,
);
stm.input_stream = Some(s);
}
@ -510,12 +506,8 @@ impl<'ctx> PulseStream<'ctx> {
// Duplex, set up the ringbuffer
if input_stream_params.is_some() && output_stream_params.is_some() {
// A bit more room in case of output underrun.
let buffer_size_bytes =
2 * latency_frames * stm.input_sample_spec.frame_size() as u32;
stm.input_buffer_manager = Some(BufferManager::new(
buffer_size_bytes as usize,
&stm.input_sample_spec,
))
let buffer_size_bytes = 2 * latency_frames * stm.input_sample_spec.frame_size() as u32;
stm.input_buffer_manager = Some(BufferManager::new(buffer_size_bytes as usize, &stm.input_sample_spec))
}
let r = if stm.wait_until_ready() {
@ -601,9 +593,31 @@ impl<'ctx> Drop for PulseStream<'ctx> {
impl<'ctx> StreamOps for PulseStream<'ctx> {
fn start(&mut self) -> Result<()> {
fn output_preroll(_: &pulse::MainloopApi, u: *mut c_void) {
let stm = unsafe { &mut *(u as *mut PulseStream) };
if !stm.shutdown {
let size = stm.output_stream
.as_ref()
.map_or(0, |s| s.writable_size().unwrap_or(0));
stm.trigger_user_callback(std::ptr::null(), size);
}
}
self.shutdown = false;
self.cork(CorkState::uncork() | CorkState::notify());
if self.output_stream.is_some() {
/* When doing output-only or duplex, we need to manually call user cb once in order to
* make things roll. This is done via a defer event in order to execute it from PA
* server thread. */
self.context.mainloop.lock();
self.context
.mainloop
.get_api()
.once(output_preroll, self as *const _ as *mut _);
self.context.mainloop.unlock();
}
Ok(())
}
@ -612,11 +626,9 @@ impl<'ctx> StreamOps for PulseStream<'ctx> {
self.context.mainloop.lock();
self.shutdown = true;
// If draining is taking place wait to finish
cubeb_log!("Stream stop: waiting for drain.");
while !self.drain_timer.is_null() {
self.context.mainloop.wait();
}
cubeb_log!("Stream stop: waited for drain.");
self.context.mainloop.unlock();
}
self.cork(CorkState::cork() | CorkState::notify());
@ -740,9 +752,13 @@ impl<'ctx> StreamOps for PulseStream<'ctx> {
None => Err(Error::error()),
Some(ref stm) => {
self.context.mainloop.lock();
if let Ok(o) = stm.set_name(name, stream_success, self as *const _ as *mut _) {
self.context.operation_wait(stm, &o);
}
if let Ok(o) = stm.set_name(
name,
stream_success,
self as *const _ as *mut _
) {
self.context.operation_wait(stm, &o);
}
self.context.mainloop.unlock();
Ok(())
}
@ -828,23 +844,15 @@ impl<'ctx> PulseStream<'ctx> {
};
let cm: Option<pa_channel_map> = match stream_params.layout() {
ChannelLayout::UNDEFINED => {
ChannelLayout::UNDEFINED =>
if stream_params.channels() <= 8
&& pulse::ChannelMap::init_auto(
stream_params.channels(),
PA_CHANNEL_MAP_DEFAULT,
)
.is_none()
{
&& pulse::ChannelMap::init_auto(stream_params.channels(), PA_CHANNEL_MAP_DEFAULT).is_none() {
cubeb_log!("Layout undefined and PulseAudio's default layout has not been configured, guess one.");
Some(layout_to_channel_map(default_layout_for_channels(
stream_params.channels(),
)))
Some(layout_to_channel_map(default_layout_for_channels(stream_params.channels())))
} else {
cubeb_log!("Layout undefined, PulseAudio will use its default.");
None
}
}
},
_ => Some(layout_to_channel_map(stream_params.layout())),
};
@ -956,6 +964,7 @@ impl<'ctx> PulseStream<'ctx> {
true
}
#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
fn trigger_user_callback(&mut self, input_data: *const c_void, nbytes: usize) {
fn drained_cb(
@ -964,7 +973,6 @@ impl<'ctx> PulseStream<'ctx> {
_tv: &pulse::TimeVal,
u: *mut c_void,
) {
cubeb_logv!("Drain finished callback.");
let stm = unsafe { &mut *(u as *mut PulseStream) };
debug_assert_eq!(stm.drain_timer, e);
stm.state_change_callback(ffi::CUBEB_STATE_DRAINED);
@ -1045,7 +1053,6 @@ impl<'ctx> PulseStream<'ctx> {
debug_assert!(r.is_ok());
if (got as usize) < size / frame_size {
cubeb_logv!("Draining {} < {}", got, size / frame_size);
let latency = match stm.get_latency() {
Ok(StreamLatency::Positive(l)) => l,
Ok(_) => {
@ -1111,9 +1118,9 @@ fn not_supported() -> Error {
#[cfg(all(test, not(feature = "pulse-dlopen")))]
mod test {
use super::layout_to_channel_map;
use cubeb_backend::ChannelLayout;
use pulse_ffi::*;
use super::layout_to_channel_map;
macro_rules! channel_tests {
{$($name: ident, $layout: ident => [ $($channels: ident),* ]),+} => {

View File

@ -9,10 +9,10 @@
extern crate cubeb_backend;
extern crate pulse;
extern crate pulse_ffi;
extern crate ringbuf;
extern crate semver;
extern crate ringbuf;
mod backend;
mod capi;
mod backend;
pub use capi::pulse_rust_init;

View File

@ -20,7 +20,7 @@ profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional =
mozurl = { path = "../../../../netwerk/base/mozurl" }
webrender_bindings = { path = "../../../../gfx/webrender_bindings", optional = true }
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "ad56ea14ac915f1e7ecbcf6ac38182443b0dd29e", optional = true }
cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="c3a51357f9674756311848bf1e5966a0b7c3eef9", optional = true, features=["pulse-dlopen"] }
cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="c87b50aebfa088c1ad30c74819d4e9829f88b2e3", optional = true, features=["pulse-dlopen"] }
cubeb-sys = { version = "0.9", optional = true, features=["gecko-in-tree"] }
encoding_glue = { path = "../../../../intl/encoding_glue" }
audioipc-client = { git = "https://github.com/mozilla/audioipc-2", rev = "7537bfadad2e981577eb75e4f13662fc517e1a09", optional = true }