зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1687070 - mach vendor rust. r=cubeb-reviewers,kinetik
Differential Revision: https://phabricator.services.mozilla.com/D119955
This commit is contained in:
Родитель
2b7b90b50f
Коммит
52a4c47c98
|
@ -30,7 +30,7 @@ rev = "1bb484e96ae724309e3346968e8ffd4c25e61616"
|
|||
[source."https://github.com/mozilla/cubeb-pulse-rs"]
|
||||
git = "https://github.com/mozilla/cubeb-pulse-rs"
|
||||
replace-with = "vendored-sources"
|
||||
rev = "c87b50aebfa088c1ad30c74819d4e9829f88b2e3"
|
||||
rev = "3ad5978575f501ab10b1753626f176f1bba3f584"
|
||||
|
||||
[source."https://github.com/mozilla/cubeb-coreaudio-rs"]
|
||||
git = "https://github.com/mozilla/cubeb-coreaudio-rs"
|
||||
|
|
|
@ -1027,7 +1027,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cubeb-pulse"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=c87b50aebfa088c1ad30c74819d4e9829f88b2e3#c87b50aebfa088c1ad30c74819d4e9829f88b2e3"
|
||||
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=3ad5978575f501ab10b1753626f176f1bba3f584#3ad5978575f501ab10b1753626f176f1bba3f584"
|
||||
dependencies = [
|
||||
"cubeb-backend",
|
||||
"pulse",
|
||||
|
@ -3999,7 +3999,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "pulse"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=c87b50aebfa088c1ad30c74819d4e9829f88b2e3#c87b50aebfa088c1ad30c74819d4e9829f88b2e3"
|
||||
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=3ad5978575f501ab10b1753626f176f1bba3f584#3ad5978575f501ab10b1753626f176f1bba3f584"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"pulse-ffi",
|
||||
|
@ -4008,7 +4008,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "pulse-ffi"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=c87b50aebfa088c1ad30c74819d4e9829f88b2e3#c87b50aebfa088c1ad30c74819d4e9829f88b2e3"
|
||||
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=3ad5978575f501ab10b1753626f176f1bba3f584#3ad5978575f501ab10b1753626f176f1bba3f584"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"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}
|
||||
{"files":{".editorconfig":"bf047bd1da10cabb99eea666d1e57c321eba4716dccb3e4ed0e2c5fe3ca53858",".github/workflows/build.yml":"95d0d2542c04f0c932f58591b92c3051db5c95657bf5f24b6a6110f7b667568d","AUTHORS":"0e0ac930a68ce2f6b876126b195add177f0d3886facb9260f4d9b69f1988f0cc","Cargo.toml":"56e90cb82ec36ead07e551a28fc2455fa658fa8308c3d73f8d856d85bfcd2122","LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","README.md":"0079450bb4b013bac065ed1750851e461a3710ebad1f323817da1cb82db0bc4f","src/backend/context.rs":"8969b300850b56ace07abe570940e2099774bf0bf20325be1d3ec0f5f408c8ce","src/backend/cork_state.rs":"4a0f1afc7d9f333dac89218cc56d7d32fbffb487cd48c1c9a4e03d79cb3b5e28","src/backend/intern.rs":"11ca424e4eb77f8eb9fd5a6717d1e791facf9743156a8534f0016fcf64d57b0f","src/backend/mod.rs":"d5da05348bf1a7f65c85b14372964a49dc4849f0aee96c75e2c18b51fb03fcaf","src/backend/stream.rs":"deac28f4840dbeeb195deff8734d594e53fbca3b65545a54613e9e6fa22d7dfc","src/capi.rs":"fa0fa020f0d0efe55aa0fc3596405e8407bbe2cbe6c7a558345304e6da87994e","src/lib.rs":"b41bbdc562cbfb130ed7c1e53fe69944774f515705341d8ce48a2f82c8c0c2c5"},"package":null}
|
|
@ -0,0 +1,44 @@
|
|||
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 clippy
|
||||
|
||||
- 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: Clippy
|
||||
shell: bash
|
||||
run: rustup run ${{ matrix.rust }} cargo clippy --all -- -D warnings
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: rustup run ${{ matrix.rust }} cargo build --all
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: rustup run ${{ matrix.rust }} cargo test --all
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
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
|
|
@ -2,5 +2,4 @@
|
|||
|
||||
Implementation of PulseAudio backend for Cubeb written in Rust.
|
||||
|
||||
[![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)
|
||||
[![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)
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
// 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;
|
||||
|
@ -92,17 +94,8 @@ 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 };
|
||||
|
@ -110,7 +103,7 @@ impl PulseContext {
|
|||
ctx.default_sink_info = Some(DefaultInfo {
|
||||
sample_spec: info.sample_spec,
|
||||
channel_map: info.channel_map,
|
||||
flags: flags,
|
||||
flags,
|
||||
});
|
||||
}
|
||||
ctx.mainloop.signal();
|
||||
|
@ -220,11 +213,13 @@ 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);
|
||||
}
|
||||
}
|
||||
|
@ -335,14 +330,14 @@ impl ContextOps for PulseContext {
|
|||
let device_id = ctx.devids.borrow_mut().add(info_name);
|
||||
let friendly_name = info_description.into_raw();
|
||||
let devinfo = ffi::cubeb_device_info {
|
||||
device_id: device_id,
|
||||
device_id,
|
||||
devid: device_id as ffi::cubeb_devid,
|
||||
friendly_name: friendly_name,
|
||||
group_id: group_id,
|
||||
vendor_name: vendor_name,
|
||||
friendly_name,
|
||||
group_id,
|
||||
vendor_name,
|
||||
device_type: ffi::CUBEB_DEVICE_TYPE_OUTPUT,
|
||||
state: ctx.state_from_port(info.active_port),
|
||||
preferred: preferred,
|
||||
preferred,
|
||||
format: ffi::CUBEB_DEVICE_FMT_ALL,
|
||||
default_format: pulse_format_to_cubeb_format(info.sample_spec.format),
|
||||
max_channels: u32::from(info.channel_map.channels),
|
||||
|
@ -396,14 +391,14 @@ impl ContextOps for PulseContext {
|
|||
let device_id = ctx.devids.borrow_mut().add(info_name);
|
||||
let friendly_name = info_description.into_raw();
|
||||
let devinfo = ffi::cubeb_device_info {
|
||||
device_id: device_id,
|
||||
device_id,
|
||||
devid: device_id as ffi::cubeb_devid,
|
||||
friendly_name: friendly_name,
|
||||
group_id: group_id,
|
||||
vendor_name: vendor_name,
|
||||
friendly_name,
|
||||
group_id,
|
||||
vendor_name,
|
||||
device_type: ffi::CUBEB_DEVICE_TYPE_INPUT,
|
||||
state: ctx.state_from_port(info.active_port),
|
||||
preferred: preferred,
|
||||
preferred,
|
||||
format: ffi::CUBEB_DEVICE_FMT_ALL,
|
||||
default_format: pulse_format_to_cubeb_format(info.sample_spec.format),
|
||||
max_channels: u32::from(info.channel_map.channels),
|
||||
|
@ -506,7 +501,7 @@ impl ContextOps for PulseContext {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
|
||||
fn stream_init(
|
||||
&mut self,
|
||||
stream_name: Option<&CStr>,
|
||||
|
@ -591,10 +586,7 @@ impl PulseContext {
|
|||
}
|
||||
|
||||
self.context = {
|
||||
let name = match self.context_name.as_ref() {
|
||||
Some(s) => Some(s.as_ref()),
|
||||
None => None,
|
||||
};
|
||||
let name = self.context_name.as_ref().map(|s| s.as_ref());
|
||||
pulse::Context::new(&self.mainloop.get_api(), name)
|
||||
};
|
||||
|
||||
|
@ -723,7 +715,7 @@ impl<'a> PulseDevListData<'a> {
|
|||
default_sink_name: CString::default(),
|
||||
default_source_name: CString::default(),
|
||||
devinfo: Vec::new(),
|
||||
context: context,
|
||||
context,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::os::raw::c_char;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Intern {
|
||||
vec: Vec<Box<CString>>,
|
||||
vec: Vec<CString>,
|
||||
}
|
||||
|
||||
impl Intern {
|
||||
|
@ -26,7 +26,7 @@ impl Intern {
|
|||
}
|
||||
}
|
||||
|
||||
self.vec.push(Box::new(string.to_owned()));
|
||||
self.vec.push(string.to_owned());
|
||||
self.vec.last().unwrap().as_ptr()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
mod context;
|
||||
mod cork_state;
|
||||
mod stream;
|
||||
mod intern;
|
||||
mod stream;
|
||||
|
||||
pub use self::context::PulseContext;
|
||||
use self::intern::Intern;
|
||||
|
|
|
@ -3,22 +3,24 @@
|
|||
// This program is made available under an ISC-style license. See the
|
||||
// accompanying file LICENSE for details.
|
||||
|
||||
use backend::*;
|
||||
use backend::cork_state::CorkState;
|
||||
use cubeb_backend::{ffi, log_enabled, ChannelLayout, DeviceId, DeviceRef, Error, Result,
|
||||
SampleFormat, StreamOps, StreamParamsRef, StreamPrefs};
|
||||
use backend::*;
|
||||
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 std::{mem, ptr};
|
||||
use ringbuf::RingBuffer;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::{c_long, c_void};
|
||||
use std::slice;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use ringbuf::RingBuffer;
|
||||
use std::{mem, ptr};
|
||||
|
||||
use self::LinearInputBuffer::*;
|
||||
use self::RingBufferConsumer::*;
|
||||
use self::RingBufferProducer::*;
|
||||
use self::LinearInputBuffer::*;
|
||||
|
||||
const PULSE_NO_GAIN: f32 = -1.0;
|
||||
|
||||
|
@ -101,12 +103,10 @@ 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,58 +127,63 @@ 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();
|
||||
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();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -187,7 +192,9 @@ 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) {
|
||||
|
@ -196,7 +203,9 @@ 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) {
|
||||
|
@ -221,7 +230,7 @@ impl BufferManager {
|
|||
}
|
||||
self.pull_input_data(p, nsamples);
|
||||
|
||||
return p;
|
||||
p
|
||||
}
|
||||
|
||||
pub fn trim(&mut self, final_size: usize) {
|
||||
|
@ -242,12 +251,8 @@ 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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -274,11 +279,11 @@ 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> {
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
|
||||
pub fn new(
|
||||
context: &'ctx PulseContext,
|
||||
stream_name: Option<&CStr>,
|
||||
|
@ -305,7 +310,7 @@ impl<'ctx> PulseStream<'ctx> {
|
|||
buffer: *mut *const c_void,
|
||||
size: *mut usize,
|
||||
) -> i32 {
|
||||
let readable_size: i32 = s.readable_size().and_then(|s| Ok(s as i32)).unwrap_or(-1);
|
||||
let readable_size = s.readable_size().map(|s| s as i32).unwrap_or(-1);
|
||||
if readable_size > 0 && unsafe { s.peek(buffer, size).is_err() } {
|
||||
return -1;
|
||||
}
|
||||
|
@ -329,7 +334,10 @@ 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 {
|
||||
|
@ -373,11 +381,13 @@ 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);
|
||||
}
|
||||
}
|
||||
|
@ -393,12 +403,12 @@ impl<'ctx> PulseStream<'ctx> {
|
|||
}
|
||||
|
||||
let mut stm = Box::new(PulseStream {
|
||||
context: context,
|
||||
context,
|
||||
output_stream: None,
|
||||
input_stream: None,
|
||||
data_callback: data_callback,
|
||||
state_callback: state_callback,
|
||||
user_ptr: user_ptr,
|
||||
data_callback,
|
||||
state_callback,
|
||||
user_ptr,
|
||||
drain_timer: ptr::null_mut(),
|
||||
output_sample_spec: pulse::SampleSpec::default(),
|
||||
input_sample_spec: pulse::SampleSpec::default(),
|
||||
|
@ -406,7 +416,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 {
|
||||
|
@ -421,14 +431,15 @@ 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: u32::max_value(),
|
||||
prebuf: 0,
|
||||
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
|
||||
|
@ -438,16 +449,11 @@ 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);
|
||||
}
|
||||
|
@ -460,7 +466,7 @@ impl<'ctx> PulseStream<'ctx> {
|
|||
}
|
||||
|
||||
// Set up input stream
|
||||
if let Some(ref stream_params) = input_stream_params {
|
||||
if let Some(stream_params) = input_stream_params {
|
||||
match PulseStream::stream_init(context, stream_params, stream_name) {
|
||||
Ok(s) => {
|
||||
stm.input_sample_spec = *s.get_sample_spec();
|
||||
|
@ -468,13 +474,14 @@ 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
|
||||
|
@ -484,14 +491,11 @@ 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);
|
||||
}
|
||||
|
@ -506,8 +510,12 @@ 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() {
|
||||
|
@ -593,31 +601,9 @@ 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(())
|
||||
}
|
||||
|
||||
|
@ -626,9 +612,11 @@ 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());
|
||||
|
@ -691,9 +679,7 @@ impl<'ctx> StreamOps for PulseStream<'ctx> {
|
|||
}
|
||||
// Input stream can be negative only if it is attached to a
|
||||
// monitor source device
|
||||
Ok(StreamLatency::Negative(_)) => {
|
||||
return Ok(0);
|
||||
}
|
||||
Ok(StreamLatency::Negative(_)) => Ok(0),
|
||||
Err(_) => Err(Error::error()),
|
||||
},
|
||||
}
|
||||
|
@ -752,13 +738,9 @@ 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(())
|
||||
}
|
||||
|
@ -844,15 +826,23 @@ 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())),
|
||||
};
|
||||
|
||||
|
@ -964,7 +954,6 @@ 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(
|
||||
|
@ -973,6 +962,7 @@ 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);
|
||||
|
@ -1002,8 +992,7 @@ impl<'ctx> PulseStream<'ctx> {
|
|||
size,
|
||||
read_offset
|
||||
);
|
||||
let read_ptr =
|
||||
unsafe { (input_data as *const u8).offset(read_offset as isize) };
|
||||
let read_ptr = unsafe { (input_data as *const u8).add(read_offset) };
|
||||
let got = unsafe {
|
||||
self.data_callback.unwrap()(
|
||||
self as *const _ as *mut _,
|
||||
|
@ -1053,6 +1042,7 @@ 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(_) => {
|
||||
|
@ -1118,9 +1108,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),* ]),+} => {
|
||||
|
|
|
@ -7,7 +7,11 @@ use backend::PulseContext;
|
|||
use cubeb_backend::{capi, ffi};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
|
||||
/// Entry point from C code.
|
||||
/// # Safety
|
||||
///
|
||||
/// Entry point from C code. This function is unsafe because it dereferences
|
||||
/// the given `c` and `context_name` pointers. The caller should ensure those
|
||||
/// pointers are valid.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn pulse_rust_init(
|
||||
c: *mut *mut ffi::cubeb,
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
extern crate cubeb_backend;
|
||||
extern crate pulse;
|
||||
extern crate pulse_ffi;
|
||||
extern crate semver;
|
||||
extern crate ringbuf;
|
||||
extern crate semver;
|
||||
|
||||
mod capi;
|
||||
mod backend;
|
||||
mod capi;
|
||||
|
||||
pub use capi::pulse_rust_init;
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"86bb1c8ebc438416c3a1f71b41494f19a85f698860b8c12d4875c8247f9c3664","src/ffi_funcs.rs":"8e79fc30a6ae800efdd026a7f29808abf039491fedac3491e22e0b1399b5c06b","src/ffi_types.rs":"fd6ca280be7601ae1990d4d0626fa9c4c6c9c958040c29e651764d06386d15c1","src/lib.rs":"edb03c6d9bcddc69a688160ffda0b8bdb69f1f87ccbc3e3b005574c9d5484991"},"package":null}
|
||||
{"files":{"Cargo.toml":"86bb1c8ebc438416c3a1f71b41494f19a85f698860b8c12d4875c8247f9c3664","src/ffi_funcs.rs":"a16646c5e7c49e94b907a7a404cfcadf3007688005c689cca936f0c2ee2e28e6","src/ffi_types.rs":"2ca56bc3638a40d331e53117a5dd175d0a6e102b1e0eccb9c2adc565c6861a33","src/lib.rs":"6aff308de11954a067d0f6ef95bf3126aabb6d928a5191e91d9a38ebadba91c2"},"package":null}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -54,7 +54,10 @@ pub type pa_context_state_t = c_int;
|
|||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn PA_CONTEXT_IS_GOOD(x: pa_context_state_t) -> bool {
|
||||
x == PA_CONTEXT_CONNECTING || x == PA_CONTEXT_AUTHORIZING || x == PA_CONTEXT_SETTING_NAME || x == PA_CONTEXT_READY
|
||||
x == PA_CONTEXT_CONNECTING
|
||||
|| x == PA_CONTEXT_AUTHORIZING
|
||||
|| x == PA_CONTEXT_SETTING_NAME
|
||||
|| x == PA_CONTEXT_READY
|
||||
}
|
||||
|
||||
pub const PA_STREAM_UNCONNECTED: c_int = 0;
|
||||
|
@ -297,46 +300,63 @@ pub const PA_IO_EVENT_HANGUP: c_int = 4;
|
|||
pub const PA_IO_EVENT_ERROR: c_int = 8;
|
||||
pub type pa_io_event_flags_t = c_int;
|
||||
|
||||
pub enum pa_io_event { }
|
||||
pub type pa_io_event_cb_t = Option<unsafe extern "C" fn(ea: *mut pa_mainloop_api,
|
||||
e: *mut pa_io_event,
|
||||
fd: c_int,
|
||||
events: pa_io_event_flags_t,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_io_event_destroy_cb_t = Option<unsafe extern "C" fn(a: *mut pa_mainloop_api,
|
||||
e: *mut pa_io_event,
|
||||
userdata: *mut c_void)>;
|
||||
pub enum pa_time_event { }
|
||||
pub type pa_time_event_cb_t = Option<unsafe extern "C" fn(a: *mut pa_mainloop_api,
|
||||
e: *mut pa_time_event,
|
||||
tv: *const timeval,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_time_event_destroy_cb_t = Option<unsafe extern "C" fn(a: *mut pa_mainloop_api,
|
||||
e: *mut pa_time_event,
|
||||
userdata: *mut c_void)>;
|
||||
pub enum pa_io_event {}
|
||||
pub type pa_io_event_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
ea: *mut pa_mainloop_api,
|
||||
e: *mut pa_io_event,
|
||||
fd: c_int,
|
||||
events: pa_io_event_flags_t,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
pub type pa_io_event_destroy_cb_t = Option<
|
||||
unsafe extern "C" fn(a: *mut pa_mainloop_api, e: *mut pa_io_event, userdata: *mut c_void),
|
||||
>;
|
||||
pub enum pa_time_event {}
|
||||
pub type pa_time_event_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
a: *mut pa_mainloop_api,
|
||||
e: *mut pa_time_event,
|
||||
tv: *const timeval,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
pub type pa_time_event_destroy_cb_t = Option<
|
||||
unsafe extern "C" fn(a: *mut pa_mainloop_api, e: *mut pa_time_event, userdata: *mut c_void),
|
||||
>;
|
||||
|
||||
pub enum pa_defer_event { }
|
||||
pub type pa_defer_event_cb_t = Option<unsafe extern "C" fn(a: *mut pa_mainloop_api,
|
||||
e: *mut pa_defer_event,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_defer_event_destroy_cb_t = Option<unsafe extern "C" fn(a: *mut pa_mainloop_api,
|
||||
e: *mut pa_defer_event,
|
||||
userdata: *mut c_void)>;
|
||||
pub type IoNewFn = Option<unsafe extern "C" fn(a: *mut pa_mainloop_api,
|
||||
fd: c_int,
|
||||
events: pa_io_event_flags_t,
|
||||
cb: pa_io_event_cb_t,
|
||||
userdata: *mut c_void)
|
||||
-> *mut pa_io_event>;
|
||||
pub type TimeNewFn = Option<unsafe extern "C" fn(a: *mut pa_mainloop_api,
|
||||
tv: *const timeval,
|
||||
cb: pa_time_event_cb_t,
|
||||
userdata: *mut c_void)
|
||||
-> *mut pa_time_event>;
|
||||
pub type DeferNewFn = Option<unsafe extern "C" fn(a: *mut pa_mainloop_api,
|
||||
cb: pa_defer_event_cb_t,
|
||||
userdata: *mut c_void)
|
||||
-> *mut pa_defer_event>;
|
||||
pub enum pa_defer_event {}
|
||||
pub type pa_defer_event_cb_t = Option<
|
||||
unsafe extern "C" fn(a: *mut pa_mainloop_api, e: *mut pa_defer_event, userdata: *mut c_void),
|
||||
>;
|
||||
pub type pa_defer_event_destroy_cb_t = Option<
|
||||
unsafe extern "C" fn(a: *mut pa_mainloop_api, e: *mut pa_defer_event, userdata: *mut c_void),
|
||||
>;
|
||||
pub type IoNewFn = Option<
|
||||
unsafe extern "C" fn(
|
||||
a: *mut pa_mainloop_api,
|
||||
fd: c_int,
|
||||
events: pa_io_event_flags_t,
|
||||
cb: pa_io_event_cb_t,
|
||||
userdata: *mut c_void,
|
||||
) -> *mut pa_io_event,
|
||||
>;
|
||||
pub type TimeNewFn = Option<
|
||||
unsafe extern "C" fn(
|
||||
a: *mut pa_mainloop_api,
|
||||
tv: *const timeval,
|
||||
cb: pa_time_event_cb_t,
|
||||
userdata: *mut c_void,
|
||||
) -> *mut pa_time_event,
|
||||
>;
|
||||
pub type DeferNewFn = Option<
|
||||
unsafe extern "C" fn(
|
||||
a: *mut pa_mainloop_api,
|
||||
cb: pa_defer_event_cb_t,
|
||||
userdata: *mut c_void,
|
||||
) -> *mut pa_defer_event,
|
||||
>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -345,15 +365,18 @@ pub struct pa_mainloop_api {
|
|||
pub io_new: IoNewFn,
|
||||
pub io_enable: Option<unsafe extern "C" fn(e: *mut pa_io_event, events: pa_io_event_flags_t)>,
|
||||
pub io_free: Option<unsafe extern "C" fn(e: *mut pa_io_event)>,
|
||||
pub io_set_destroy: Option<unsafe extern "C" fn(e: *mut pa_io_event, cb: pa_io_event_destroy_cb_t)>,
|
||||
pub io_set_destroy:
|
||||
Option<unsafe extern "C" fn(e: *mut pa_io_event, cb: pa_io_event_destroy_cb_t)>,
|
||||
pub time_new: TimeNewFn,
|
||||
pub time_restart: Option<unsafe extern "C" fn(e: *mut pa_time_event, tv: *const timeval)>,
|
||||
pub time_free: Option<unsafe extern "C" fn(e: *mut pa_time_event)>,
|
||||
pub time_set_destroy: Option<unsafe extern "C" fn(e: *mut pa_time_event, cb: pa_time_event_destroy_cb_t)>,
|
||||
pub time_set_destroy:
|
||||
Option<unsafe extern "C" fn(e: *mut pa_time_event, cb: pa_time_event_destroy_cb_t)>,
|
||||
pub defer_new: DeferNewFn,
|
||||
pub defer_enable: Option<unsafe extern "C" fn(e: *mut pa_defer_event, b: c_int)>,
|
||||
pub defer_free: Option<unsafe extern "C" fn(e: *mut pa_defer_event)>,
|
||||
pub defer_set_destroy: Option<unsafe extern "C" fn(e: *mut pa_defer_event, cb: pa_defer_event_destroy_cb_t)>,
|
||||
pub defer_set_destroy:
|
||||
Option<unsafe extern "C" fn(e: *mut pa_defer_event, cb: pa_defer_event_destroy_cb_t)>,
|
||||
pub quit: Option<unsafe extern "C" fn(a: *mut pa_mainloop_api, retval: c_int)>,
|
||||
}
|
||||
|
||||
|
@ -363,9 +386,10 @@ impl ::std::default::Default for pa_mainloop_api {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_mainloop_api_once_cb_t = Option<unsafe extern "C" fn(m: *mut pa_mainloop_api, userdata: *mut c_void)>;
|
||||
pub type pa_mainloop_api_once_cb_t =
|
||||
Option<unsafe extern "C" fn(m: *mut pa_mainloop_api, userdata: *mut c_void)>;
|
||||
|
||||
pub enum pa_proplist { }
|
||||
pub enum pa_proplist {}
|
||||
|
||||
pub const PA_UPDATE_SET: c_int = 0;
|
||||
pub const PA_UPDATE_MERGE: c_int = 1;
|
||||
|
@ -486,18 +510,23 @@ pub const PA_PROP_TYPE_STRING_ARRAY: c_int = 4;
|
|||
pub const PA_PROP_TYPE_INVALID: c_int = -1;
|
||||
pub type pa_prop_type_t = c_int;
|
||||
|
||||
pub enum pa_operation { }
|
||||
pub type pa_operation_notify_cb_t = Option<unsafe extern "C" fn(o: *mut pa_operation, userdata: *mut c_void)>;
|
||||
pub enum pa_operation {}
|
||||
pub type pa_operation_notify_cb_t =
|
||||
Option<unsafe extern "C" fn(o: *mut pa_operation, userdata: *mut c_void)>;
|
||||
|
||||
pub enum pa_context { }
|
||||
pub type pa_context_notify_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context, userdata: *mut c_void)>;
|
||||
pub type pa_context_success_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
success: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_context_event_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
name: *const c_char,
|
||||
p: *mut pa_proplist,
|
||||
userdata: *mut c_void)>;
|
||||
pub enum pa_context {}
|
||||
pub type pa_context_notify_cb_t =
|
||||
Option<unsafe extern "C" fn(c: *mut pa_context, userdata: *mut c_void)>;
|
||||
pub type pa_context_success_cb_t =
|
||||
Option<unsafe extern "C" fn(c: *mut pa_context, success: c_int, userdata: *mut c_void)>;
|
||||
pub type pa_context_event_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
name: *const c_char,
|
||||
p: *mut pa_proplist,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
|
||||
pub type pa_volume_t = u32;
|
||||
|
||||
|
@ -514,16 +543,21 @@ impl ::std::default::Default for pa_cvolume {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum pa_stream { }
|
||||
pub type pa_stream_success_cb_t = Option<unsafe extern "C" fn(s: *mut pa_stream,
|
||||
success: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_stream_request_cb_t = Option<unsafe extern "C" fn(p: *mut pa_stream, nbytes: usize, userdata: *mut c_void)>;
|
||||
pub type pa_stream_notify_cb_t = Option<unsafe extern "C" fn(p: *mut pa_stream, userdata: *mut c_void)>;
|
||||
pub type pa_stream_event_cb_t = Option<unsafe extern "C" fn(p: *mut pa_stream,
|
||||
name: *const c_char,
|
||||
pl: *mut pa_proplist,
|
||||
userdata: *mut c_void)>;
|
||||
pub enum pa_stream {}
|
||||
pub type pa_stream_success_cb_t =
|
||||
Option<unsafe extern "C" fn(s: *mut pa_stream, success: c_int, userdata: *mut c_void)>;
|
||||
pub type pa_stream_request_cb_t =
|
||||
Option<unsafe extern "C" fn(p: *mut pa_stream, nbytes: usize, userdata: *mut c_void)>;
|
||||
pub type pa_stream_notify_cb_t =
|
||||
Option<unsafe extern "C" fn(p: *mut pa_stream, userdata: *mut c_void)>;
|
||||
pub type pa_stream_event_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
p: *mut pa_stream,
|
||||
name: *const c_char,
|
||||
pl: *mut pa_proplist,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -575,10 +609,14 @@ impl ::std::default::Default for pa_sink_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_sink_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_sink_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_sink_info_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
i: *const pa_sink_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -615,10 +653,14 @@ impl ::std::default::Default for pa_source_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_source_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_source_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_source_info_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
i: *const pa_source_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -640,9 +682,9 @@ impl ::std::default::Default for pa_server_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_server_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_server_info,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_server_info_cb_t = Option<
|
||||
unsafe extern "C" fn(c: *mut pa_context, i: *const pa_server_info, userdata: *mut c_void),
|
||||
>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -661,11 +703,16 @@ impl ::std::default::Default for pa_module_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_module_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_module_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_context_index_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context, idx: u32, userdata: *mut c_void)>;
|
||||
pub type pa_module_info_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
i: *const pa_module_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
pub type pa_context_index_cb_t =
|
||||
Option<unsafe extern "C" fn(c: *mut pa_context, idx: u32, userdata: *mut c_void)>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -683,10 +730,14 @@ impl ::std::default::Default for pa_client_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_client_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_client_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_client_info_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
i: *const pa_client_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -765,10 +816,14 @@ impl ::std::default::Default for pa_card_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_card_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_card_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_card_info_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
i: *const pa_card_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -799,10 +854,14 @@ impl ::std::default::Default for pa_sink_input_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_sink_input_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_sink_input_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_sink_input_info_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
i: *const pa_sink_input_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -833,10 +892,14 @@ impl ::std::default::Default for pa_source_output_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_source_output_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_source_output_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_source_output_info_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
i: *const pa_source_output_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -854,9 +917,8 @@ impl ::std::default::Default for pa_stat_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_stat_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_stat_info,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_stat_info_cb_t =
|
||||
Option<unsafe extern "C" fn(c: *mut pa_context, i: *const pa_stat_info, userdata: *mut c_void)>;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -879,10 +941,14 @@ impl ::std::default::Default for pa_sample_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_sample_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_sample_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_sample_info_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
i: *const pa_sample_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
|
||||
pub const PA_AUTOLOAD_SINK: c_int = 0;
|
||||
pub const PA_AUTOLOAD_SOURCE: c_int = 1;
|
||||
|
@ -904,33 +970,47 @@ impl ::std::default::Default for pa_autoload_info {
|
|||
}
|
||||
}
|
||||
|
||||
pub type pa_autoload_info_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
i: *const pa_autoload_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_context_subscribe_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
t: pa_subscription_event_type_t,
|
||||
idx: u32,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_context_play_sample_cb_t = Option<unsafe extern "C" fn(c: *mut pa_context,
|
||||
idx: u32,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_autoload_info_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
i: *const pa_autoload_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
pub type pa_context_subscribe_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
c: *mut pa_context,
|
||||
t: pa_subscription_event_type_t,
|
||||
idx: u32,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
pub type pa_context_play_sample_cb_t =
|
||||
Option<unsafe extern "C" fn(c: *mut pa_context, idx: u32, userdata: *mut c_void)>;
|
||||
|
||||
pub enum pa_threaded_mainloop { }
|
||||
pub enum pollfd { }
|
||||
pub enum pa_mainloop { }
|
||||
pub enum pa_threaded_mainloop {}
|
||||
pub enum pollfd {}
|
||||
pub enum pa_mainloop {}
|
||||
|
||||
pub type pa_poll_func = Option<unsafe extern "C" fn(ufds: *mut pollfd,
|
||||
nfds: c_ulong,
|
||||
timeout: c_int,
|
||||
userdata: *mut c_void)
|
||||
-> c_int>;
|
||||
pub enum pa_signal_event { }
|
||||
pub type pa_poll_func = Option<
|
||||
unsafe extern "C" fn(
|
||||
ufds: *mut pollfd,
|
||||
nfds: c_ulong,
|
||||
timeout: c_int,
|
||||
userdata: *mut c_void,
|
||||
) -> c_int,
|
||||
>;
|
||||
pub enum pa_signal_event {}
|
||||
|
||||
pub type pa_signal_cb_t = Option<unsafe extern "C" fn(api: *mut pa_mainloop_api,
|
||||
e: *mut pa_signal_event,
|
||||
sig: c_int,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_signal_destroy_cb_t = Option<unsafe extern "C" fn(api: *mut pa_mainloop_api,
|
||||
e: *mut pa_signal_event,
|
||||
userdata: *mut c_void)>;
|
||||
pub type pa_signal_cb_t = Option<
|
||||
unsafe extern "C" fn(
|
||||
api: *mut pa_mainloop_api,
|
||||
e: *mut pa_signal_event,
|
||||
sig: c_int,
|
||||
userdata: *mut c_void,
|
||||
),
|
||||
>;
|
||||
pub type pa_signal_destroy_cb_t = Option<
|
||||
unsafe extern "C" fn(api: *mut pa_mainloop_api, e: *mut pa_signal_event, userdata: *mut c_void),
|
||||
>;
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
#[cfg(feature = "dlopen")]
|
||||
extern crate libc;
|
||||
|
||||
mod ffi_types;
|
||||
mod ffi_funcs;
|
||||
mod ffi_types;
|
||||
|
||||
pub use ffi_types::*;
|
||||
pub use ffi_funcs::*;
|
||||
pub use ffi_types::*;
|
||||
|
||||
#[cfg(feature = "dlopen")]
|
||||
pub unsafe fn open() -> Option<LibLoader> {
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"961d0d5d82f0d128d23dd753ad89beccdefdc0bc830ff646c785ee87eed261db","src/context.rs":"5e43131c0a989336e149b5408e0b362c0ef8176854785f98191f86b75ef5d76a","src/error.rs":"7be0ad689b6519a5be3771c29a102ff394bdc5ee46502d418bced90268e912dd","src/lib.rs":"8636d18c55b7ccd8e79d45a8d12ea84ba94b7aeef8ac3975292c94a28ed4a2b1","src/mainloop_api.rs":"b4a6c7e1a507490157c5b4a25af367cf810e1ef64c7a96f71575a15674d9b649","src/operation.rs":"c0d3e28ef7db52d60b19f931fe7bb44271127009b2e82693da2b7e342e804022","src/proplist.rs":"65bfc2b90f31bc3969aef69eb3e26b34ac657a2149f1b6515791403d752f3fc5","src/stream.rs":"7205d53d3aa5de7473339e6baa02bd32998e6ae15f76e8aa94420449354ba570","src/threaded_mainloop.rs":"958181a46363ded3ac8e0d9c9d912587cb6f9f26ae6f190881014adbda2d3211","src/util.rs":"d971486fd828b8b9d81db61a21a77960ea34a99a59b96fceaf77c2b84ed2accc"},"package":null}
|
||||
{"files":{"Cargo.toml":"961d0d5d82f0d128d23dd753ad89beccdefdc0bc830ff646c785ee87eed261db","src/context.rs":"849333d1d3b443700ea13e07696c68b3fe7ad3c4ee136b17ea888c494e871812","src/error.rs":"7cca3f0b0a238743db01d707881eee0c7b5b2ba530d579b6a2bd82bc8dd7dd30","src/lib.rs":"52891e08b0cfbe434a63074a226bec16580cfeb96e2eeaf30079dd213657e6a2","src/mainloop_api.rs":"6374f8f62233277f4cf460b9978db0347a8829eb04f62101eaaa5533b6aca769","src/operation.rs":"c0d3e28ef7db52d60b19f931fe7bb44271127009b2e82693da2b7e342e804022","src/proplist.rs":"ce53f1e92fae51727aa564d371b1e0d59078f5cbbd655b39bc1c7741c8ba2f87","src/stream.rs":"ba14551ff34f6b23e94e450384487b3c35be75ac4456c22c14b36ade23282978","src/threaded_mainloop.rs":"057928b5b84b1ea8c839150840ccd88cb944b60ca0aa2ec5389aaa6676c8e505","src/util.rs":"1613909f460eb008b282801ac803dd28b4bfe59926c14fe030da6482fdacd70f"},"package":null}
|
|
@ -3,13 +3,13 @@
|
|||
// This program is made available under an ISC-style license. See the
|
||||
// accompanying file LICENSE for details.
|
||||
|
||||
use ::*;
|
||||
use ffi;
|
||||
use std::ffi::CStr;
|
||||
use std::mem::{forget, MaybeUninit};
|
||||
use std::os::raw::{c_int, c_void};
|
||||
use std::ptr;
|
||||
use util::UnwrapCStr;
|
||||
use *;
|
||||
|
||||
// A note about `wrapped` functions
|
||||
//
|
||||
|
@ -57,7 +57,7 @@ macro_rules! op_or_err {
|
|||
} else {
|
||||
Ok(unsafe { operation::from_raw_ptr(o) })
|
||||
}
|
||||
}}
|
||||
}};
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -66,7 +66,8 @@ pub struct Context(*mut ffi::pa_context);
|
|||
|
||||
impl Context {
|
||||
pub fn new<'a, OPT>(api: &MainloopApi, name: OPT) -> Option<Self>
|
||||
where OPT: Into<Option<&'a CStr>>
|
||||
where
|
||||
OPT: Into<Option<&'a CStr>>,
|
||||
{
|
||||
let ptr = unsafe { ffi::pa_context_new(api.raw_mut(), name.unwrap_cstr()) };
|
||||
if ptr.is_null() {
|
||||
|
@ -94,13 +95,15 @@ impl Context {
|
|||
}
|
||||
|
||||
pub fn set_state_callback<CB>(&self, _: CB, userdata: *mut c_void)
|
||||
where CB: Fn(&Context, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Context, *mut c_void),
|
||||
{
|
||||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context, userdata: *mut c_void)
|
||||
where F: Fn(&Context, *mut c_void)
|
||||
where
|
||||
F: Fn(&Context, *mut c_void),
|
||||
{
|
||||
let ctx = context::from_raw_ptr(c);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -120,19 +123,26 @@ impl Context {
|
|||
}
|
||||
|
||||
pub fn get_state(&self) -> ContextState {
|
||||
ContextState::try_from(unsafe {
|
||||
ffi::pa_context_get_state(self.raw_mut())
|
||||
}).expect("pa_context_get_state returned invalid ContextState")
|
||||
ContextState::try_from(unsafe { ffi::pa_context_get_state(self.raw_mut()) })
|
||||
.expect("pa_context_get_state returned invalid ContextState")
|
||||
}
|
||||
|
||||
pub fn connect<'a, OPT>(&self, server: OPT, flags: ContextFlags, api: *const ffi::pa_spawn_api) -> Result<()>
|
||||
where OPT: Into<Option<&'a CStr>>
|
||||
pub fn connect<'a, OPT>(
|
||||
&self,
|
||||
server: OPT,
|
||||
flags: ContextFlags,
|
||||
api: *const ffi::pa_spawn_api,
|
||||
) -> Result<()>
|
||||
where
|
||||
OPT: Into<Option<&'a CStr>>,
|
||||
{
|
||||
let r = unsafe {
|
||||
ffi::pa_context_connect(self.raw_mut(),
|
||||
server.into().unwrap_cstr(),
|
||||
flags.into(),
|
||||
api)
|
||||
ffi::pa_context_connect(
|
||||
self.raw_mut(),
|
||||
server.into().unwrap_cstr(),
|
||||
flags.into(),
|
||||
api,
|
||||
)
|
||||
};
|
||||
error_result!((), r)
|
||||
}
|
||||
|
@ -143,15 +153,16 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn drain<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
|
||||
where CB: Fn(&Context, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Context, *mut c_void),
|
||||
{
|
||||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context, userdata: *mut c_void)
|
||||
where F: Fn(&Context, *mut c_void)
|
||||
where
|
||||
F: Fn(&Context, *mut c_void),
|
||||
{
|
||||
let ctx = context::from_raw_ptr(c);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -161,21 +172,31 @@ impl Context {
|
|||
result
|
||||
}
|
||||
|
||||
op_or_err!(self,
|
||||
ffi::pa_context_drain(self.raw_mut(), Some(wrapped::<CB>), userdata))
|
||||
op_or_err!(
|
||||
self,
|
||||
ffi::pa_context_drain(self.raw_mut(), Some(wrapped::<CB>), userdata)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn rttime_new<CB>(&self, usec: USec, _: CB, userdata: *mut c_void) -> *mut ffi::pa_time_event
|
||||
where CB: Fn(&MainloopApi, *mut ffi::pa_time_event, &TimeVal, *mut c_void)
|
||||
pub fn rttime_new<CB>(
|
||||
&self,
|
||||
usec: USec,
|
||||
_: CB,
|
||||
userdata: *mut c_void,
|
||||
) -> *mut ffi::pa_time_event
|
||||
where
|
||||
CB: Fn(&MainloopApi, *mut ffi::pa_time_event, &TimeVal, *mut c_void),
|
||||
{
|
||||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(a: *mut ffi::pa_mainloop_api,
|
||||
e: *mut ffi::pa_time_event,
|
||||
tv: *const TimeVal,
|
||||
userdata: *mut c_void)
|
||||
where F: Fn(&MainloopApi, *mut ffi::pa_time_event, &TimeVal, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
a: *mut ffi::pa_mainloop_api,
|
||||
e: *mut ffi::pa_time_event,
|
||||
tv: *const TimeVal,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&MainloopApi, *mut ffi::pa_time_event, &TimeVal, *mut c_void),
|
||||
{
|
||||
let api = mainloop_api::from_raw_ptr(a);
|
||||
let timeval = &*tv;
|
||||
|
@ -190,19 +211,20 @@ impl Context {
|
|||
}
|
||||
|
||||
pub fn get_server_info<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
|
||||
where CB: Fn(&Context, Option<&ServerInfo>, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Context, Option<&ServerInfo>, *mut c_void),
|
||||
{
|
||||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context, i: *const ffi::pa_server_info, userdata: *mut c_void)
|
||||
where F: Fn(&Context, Option<&ServerInfo>, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
c: *mut ffi::pa_context,
|
||||
i: *const ffi::pa_server_info,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Context, Option<&ServerInfo>, *mut c_void),
|
||||
{
|
||||
let info = if i.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(&*i)
|
||||
};
|
||||
let info = if i.is_null() { None } else { Some(&*i) };
|
||||
let ctx = context::from_raw_ptr(c);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
let result = (*cb.as_ptr())(&ctx, info, userdata);
|
||||
|
@ -211,11 +233,18 @@ impl Context {
|
|||
result
|
||||
}
|
||||
|
||||
op_or_err!(self,
|
||||
ffi::pa_context_get_server_info(self.raw_mut(), Some(wrapped::<CB>), userdata))
|
||||
op_or_err!(
|
||||
self,
|
||||
ffi::pa_context_get_server_info(self.raw_mut(), Some(wrapped::<CB>), userdata)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_sink_info_by_name<'str, CS, CB>(&self, name: CS, _: CB, userdata: *mut c_void) -> Result<Operation>
|
||||
pub fn get_sink_info_by_name<'str, CS, CB>(
|
||||
&self,
|
||||
name: CS,
|
||||
_: CB,
|
||||
userdata: *mut c_void,
|
||||
) -> Result<Operation>
|
||||
where
|
||||
CB: Fn(&Context, *const SinkInfo, i32, *mut c_void),
|
||||
CS: Into<Option<&'str CStr>>,
|
||||
|
@ -223,11 +252,13 @@ impl Context {
|
|||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context,
|
||||
info: *const ffi::pa_sink_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)
|
||||
where F: Fn(&Context, *const SinkInfo, i32, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
c: *mut ffi::pa_context,
|
||||
info: *const ffi::pa_sink_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Context, *const SinkInfo, i32, *mut c_void),
|
||||
{
|
||||
let ctx = context::from_raw_ptr(c);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -237,24 +268,31 @@ impl Context {
|
|||
result
|
||||
}
|
||||
|
||||
op_or_err!(self,
|
||||
ffi::pa_context_get_sink_info_by_name(self.raw_mut(),
|
||||
name.into().unwrap_cstr(),
|
||||
Some(wrapped::<CB>),
|
||||
userdata))
|
||||
op_or_err!(
|
||||
self,
|
||||
ffi::pa_context_get_sink_info_by_name(
|
||||
self.raw_mut(),
|
||||
name.into().unwrap_cstr(),
|
||||
Some(wrapped::<CB>),
|
||||
userdata
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_sink_info_list<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
|
||||
where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Context, *const SinkInfo, i32, *mut c_void),
|
||||
{
|
||||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context,
|
||||
info: *const ffi::pa_sink_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)
|
||||
where F: Fn(&Context, *const SinkInfo, i32, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
c: *mut ffi::pa_context,
|
||||
info: *const ffi::pa_sink_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Context, *const SinkInfo, i32, *mut c_void),
|
||||
{
|
||||
let ctx = context::from_raw_ptr(c);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -264,21 +302,31 @@ impl Context {
|
|||
result
|
||||
}
|
||||
|
||||
op_or_err!(self,
|
||||
ffi::pa_context_get_sink_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata))
|
||||
op_or_err!(
|
||||
self,
|
||||
ffi::pa_context_get_sink_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_sink_input_info<CB>(&self, idx: u32, _: CB, userdata: *mut c_void) -> Result<Operation>
|
||||
where CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void)
|
||||
pub fn get_sink_input_info<CB>(
|
||||
&self,
|
||||
idx: u32,
|
||||
_: CB,
|
||||
userdata: *mut c_void,
|
||||
) -> Result<Operation>
|
||||
where
|
||||
CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void),
|
||||
{
|
||||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context,
|
||||
info: *const ffi::pa_sink_input_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)
|
||||
where F: Fn(&Context, *const SinkInputInfo, i32, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
c: *mut ffi::pa_context,
|
||||
info: *const ffi::pa_sink_input_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Context, *const SinkInputInfo, i32, *mut c_void),
|
||||
{
|
||||
let ctx = context::from_raw_ptr(c);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -288,21 +336,26 @@ impl Context {
|
|||
result
|
||||
}
|
||||
|
||||
op_or_err!(self,
|
||||
ffi::pa_context_get_sink_input_info(self.raw_mut(), idx, Some(wrapped::<CB>), userdata))
|
||||
op_or_err!(
|
||||
self,
|
||||
ffi::pa_context_get_sink_input_info(self.raw_mut(), idx, Some(wrapped::<CB>), userdata)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_source_info_list<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
|
||||
where CB: Fn(&Context, *const SourceInfo, i32, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Context, *const SourceInfo, i32, *mut c_void),
|
||||
{
|
||||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context,
|
||||
info: *const ffi::pa_source_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void)
|
||||
where F: Fn(&Context, *const SourceInfo, i32, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
c: *mut ffi::pa_context,
|
||||
info: *const ffi::pa_source_info,
|
||||
eol: c_int,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Context, *const SourceInfo, i32, *mut c_void),
|
||||
{
|
||||
let ctx = context::from_raw_ptr(c);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -312,23 +365,31 @@ impl Context {
|
|||
result
|
||||
}
|
||||
|
||||
op_or_err!(self,
|
||||
ffi::pa_context_get_source_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata))
|
||||
op_or_err!(
|
||||
self,
|
||||
ffi::pa_context_get_source_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn set_sink_input_volume<CB>(&self,
|
||||
idx: u32,
|
||||
volume: &CVolume,
|
||||
_: CB,
|
||||
userdata: *mut c_void)
|
||||
-> Result<Operation>
|
||||
where CB: Fn(&Context, i32, *mut c_void)
|
||||
pub fn set_sink_input_volume<CB>(
|
||||
&self,
|
||||
idx: u32,
|
||||
volume: &CVolume,
|
||||
_: CB,
|
||||
userdata: *mut c_void,
|
||||
) -> Result<Operation>
|
||||
where
|
||||
CB: Fn(&Context, i32, *mut c_void),
|
||||
{
|
||||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context, success: c_int, userdata: *mut c_void)
|
||||
where F: Fn(&Context, i32, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
c: *mut ffi::pa_context,
|
||||
success: c_int,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Context, i32, *mut c_void),
|
||||
{
|
||||
let ctx = context::from_raw_ptr(c);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -338,18 +399,36 @@ impl Context {
|
|||
result
|
||||
}
|
||||
|
||||
op_or_err!(self,
|
||||
ffi::pa_context_set_sink_input_volume(self.raw_mut(), idx, volume, Some(wrapped::<CB>), userdata))
|
||||
op_or_err!(
|
||||
self,
|
||||
ffi::pa_context_set_sink_input_volume(
|
||||
self.raw_mut(),
|
||||
idx,
|
||||
volume,
|
||||
Some(wrapped::<CB>),
|
||||
userdata
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn subscribe<CB>(&self, m: SubscriptionMask, _: CB, userdata: *mut c_void) -> Result<Operation>
|
||||
where CB: Fn(&Context, i32, *mut c_void)
|
||||
pub fn subscribe<CB>(
|
||||
&self,
|
||||
m: SubscriptionMask,
|
||||
_: CB,
|
||||
userdata: *mut c_void,
|
||||
) -> Result<Operation>
|
||||
where
|
||||
CB: Fn(&Context, i32, *mut c_void),
|
||||
{
|
||||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context, success: c_int, userdata: *mut c_void)
|
||||
where F: Fn(&Context, i32, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
c: *mut ffi::pa_context,
|
||||
success: c_int,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Context, i32, *mut c_void),
|
||||
{
|
||||
let ctx = context::from_raw_ptr(c);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -359,8 +438,10 @@ impl Context {
|
|||
result
|
||||
}
|
||||
|
||||
op_or_err!(self,
|
||||
ffi::pa_context_subscribe(self.raw_mut(), m.into(), Some(wrapped::<CB>), userdata))
|
||||
op_or_err!(
|
||||
self,
|
||||
ffi::pa_context_subscribe(self.raw_mut(), m.into(), Some(wrapped::<CB>), userdata)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn clear_subscribe_callback(&self) {
|
||||
|
@ -370,20 +451,23 @@ impl Context {
|
|||
}
|
||||
|
||||
pub fn set_subscribe_callback<CB>(&self, _: CB, userdata: *mut c_void)
|
||||
where CB: Fn(&Context, SubscriptionEvent, u32, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Context, SubscriptionEvent, u32, *mut c_void),
|
||||
{
|
||||
assert_eq!(::std::mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context,
|
||||
t: ffi::pa_subscription_event_type_t,
|
||||
idx: u32,
|
||||
userdata: *mut c_void)
|
||||
where F: Fn(&Context, SubscriptionEvent, u32, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
c: *mut ffi::pa_context,
|
||||
t: ffi::pa_subscription_event_type_t,
|
||||
idx: u32,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Context, SubscriptionEvent, u32, *mut c_void),
|
||||
{
|
||||
let ctx = context::from_raw_ptr(c);
|
||||
let event = SubscriptionEvent::try_from(t)
|
||||
.expect("pa_context_subscribe_cb_t passed invalid pa_subscription_event_type_t");
|
||||
.expect("pa_context_subscribe_cb_t passed invalid pa_subscription_event_type_t");
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
let result = (*cb.as_ptr())(&ctx, event, idx, userdata);
|
||||
forget(ctx);
|
||||
|
|
|
@ -14,7 +14,7 @@ macro_rules! error_result {
|
|||
} else {
|
||||
Err(ErrorCode::from_error_result($err))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
@ -32,9 +32,7 @@ impl ErrorCode {
|
|||
|
||||
pub fn from_error_code(err: ffi::pa_error_code_t) -> Self {
|
||||
debug_assert!(err > 0);
|
||||
ErrorCode {
|
||||
err: err,
|
||||
}
|
||||
ErrorCode { err: err }
|
||||
}
|
||||
|
||||
fn desc(&self) -> &'static str {
|
||||
|
|
|
@ -86,10 +86,10 @@ impl ContextState {
|
|||
// It must match the version from PA headers.
|
||||
pub fn is_good(self) -> bool {
|
||||
match self {
|
||||
ContextState::Connecting |
|
||||
ContextState::Authorizing |
|
||||
ContextState::SettingName |
|
||||
ContextState::Ready => true,
|
||||
ContextState::Connecting
|
||||
| ContextState::Authorizing
|
||||
| ContextState::SettingName
|
||||
| ContextState::Ready => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +216,6 @@ impl Into<ffi::pa_device_type_t> for DeviceType {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[repr(i32)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum StreamDirection {
|
||||
|
@ -269,18 +268,29 @@ bitflags! {
|
|||
|
||||
impl StreamFlags {
|
||||
pub fn try_from(x: ffi::pa_stream_flags_t) -> Option<Self> {
|
||||
if (x &
|
||||
!(ffi::PA_STREAM_NOFLAGS | ffi::PA_STREAM_START_CORKED | ffi::PA_STREAM_INTERPOLATE_TIMING |
|
||||
ffi::PA_STREAM_NOT_MONOTONIC | ffi::PA_STREAM_AUTO_TIMING_UPDATE |
|
||||
ffi::PA_STREAM_NO_REMAP_CHANNELS |
|
||||
ffi::PA_STREAM_NO_REMIX_CHANNELS | ffi::PA_STREAM_FIX_FORMAT | ffi::PA_STREAM_FIX_RATE |
|
||||
ffi::PA_STREAM_FIX_CHANNELS |
|
||||
ffi::PA_STREAM_DONT_MOVE | ffi::PA_STREAM_VARIABLE_RATE | ffi::PA_STREAM_PEAK_DETECT |
|
||||
ffi::PA_STREAM_START_MUTED | ffi::PA_STREAM_ADJUST_LATENCY |
|
||||
ffi::PA_STREAM_EARLY_REQUESTS |
|
||||
ffi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND |
|
||||
ffi::PA_STREAM_START_UNMUTED | ffi::PA_STREAM_FAIL_ON_SUSPEND |
|
||||
ffi::PA_STREAM_RELATIVE_VOLUME | ffi::PA_STREAM_PASSTHROUGH)) == 0 {
|
||||
if (x & !(ffi::PA_STREAM_NOFLAGS
|
||||
| ffi::PA_STREAM_START_CORKED
|
||||
| ffi::PA_STREAM_INTERPOLATE_TIMING
|
||||
| ffi::PA_STREAM_NOT_MONOTONIC
|
||||
| ffi::PA_STREAM_AUTO_TIMING_UPDATE
|
||||
| ffi::PA_STREAM_NO_REMAP_CHANNELS
|
||||
| ffi::PA_STREAM_NO_REMIX_CHANNELS
|
||||
| ffi::PA_STREAM_FIX_FORMAT
|
||||
| ffi::PA_STREAM_FIX_RATE
|
||||
| ffi::PA_STREAM_FIX_CHANNELS
|
||||
| ffi::PA_STREAM_DONT_MOVE
|
||||
| ffi::PA_STREAM_VARIABLE_RATE
|
||||
| ffi::PA_STREAM_PEAK_DETECT
|
||||
| ffi::PA_STREAM_START_MUTED
|
||||
| ffi::PA_STREAM_ADJUST_LATENCY
|
||||
| ffi::PA_STREAM_EARLY_REQUESTS
|
||||
| ffi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
|
||||
| ffi::PA_STREAM_START_UNMUTED
|
||||
| ffi::PA_STREAM_FAIL_ON_SUSPEND
|
||||
| ffi::PA_STREAM_RELATIVE_VOLUME
|
||||
| ffi::PA_STREAM_PASSTHROUGH))
|
||||
== 0
|
||||
{
|
||||
Some(unsafe { ::std::mem::transmute(x) })
|
||||
} else {
|
||||
None
|
||||
|
@ -299,7 +309,7 @@ pub enum StreamLatency {
|
|||
Negative(u64),
|
||||
}
|
||||
|
||||
bitflags!{
|
||||
bitflags! {
|
||||
pub struct SubscriptionMask : u32 {
|
||||
const SINK = ffi::PA_SUBSCRIPTION_MASK_SINK;
|
||||
const SOURCE = ffi::PA_SUBSCRIPTION_MASK_SOURCE;
|
||||
|
@ -358,7 +368,9 @@ pub enum SubscriptionEventType {
|
|||
pub struct SubscriptionEvent(ffi::pa_subscription_event_type_t);
|
||||
impl SubscriptionEvent {
|
||||
pub fn try_from(x: ffi::pa_subscription_event_type_t) -> Option<Self> {
|
||||
if (x & !(ffi::PA_SUBSCRIPTION_EVENT_TYPE_MASK | ffi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK)) == 0 {
|
||||
if (x & !(ffi::PA_SUBSCRIPTION_EVENT_TYPE_MASK | ffi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK))
|
||||
== 0
|
||||
{
|
||||
Some(SubscriptionEvent(x))
|
||||
} else {
|
||||
None
|
||||
|
@ -415,11 +427,18 @@ bitflags! {
|
|||
|
||||
impl SinkFlags {
|
||||
pub fn try_from(x: ffi::pa_sink_flags_t) -> Option<SinkFlags> {
|
||||
if (x &
|
||||
!(ffi::PA_SINK_NOFLAGS | ffi::PA_SINK_HW_VOLUME_CTRL | ffi::PA_SINK_LATENCY |
|
||||
ffi::PA_SINK_HARDWARE | ffi::PA_SINK_NETWORK | ffi::PA_SINK_HW_MUTE_CTRL |
|
||||
ffi::PA_SINK_DECIBEL_VOLUME | ffi::PA_SINK_DYNAMIC_LATENCY |
|
||||
ffi::PA_SINK_FLAT_VOLUME | ffi::PA_SINK_SET_FORMATS)) == 0 {
|
||||
if (x & !(ffi::PA_SINK_NOFLAGS
|
||||
| ffi::PA_SINK_HW_VOLUME_CTRL
|
||||
| ffi::PA_SINK_LATENCY
|
||||
| ffi::PA_SINK_HARDWARE
|
||||
| ffi::PA_SINK_NETWORK
|
||||
| ffi::PA_SINK_HW_MUTE_CTRL
|
||||
| ffi::PA_SINK_DECIBEL_VOLUME
|
||||
| ffi::PA_SINK_DYNAMIC_LATENCY
|
||||
| ffi::PA_SINK_FLAT_VOLUME
|
||||
| ffi::PA_SINK_SET_FORMATS))
|
||||
== 0
|
||||
{
|
||||
Some(unsafe { ::std::mem::transmute(x) })
|
||||
} else {
|
||||
None
|
||||
|
@ -438,7 +457,7 @@ pub enum SinkState {
|
|||
Unlinked = ffi::PA_SINK_UNLINKED,
|
||||
}
|
||||
|
||||
bitflags!{
|
||||
bitflags! {
|
||||
pub struct SourceFlags: u32 {
|
||||
const HW_VOLUME_CTRL = ffi::PA_SOURCE_HW_VOLUME_CTRL;
|
||||
const LATENCY = ffi::PA_SOURCE_LATENCY;
|
||||
|
@ -607,9 +626,8 @@ impl ChannelMapExt for ChannelMap {
|
|||
}
|
||||
fn init_auto(ch: u32, def: ffi::pa_channel_map_def_t) -> Option<ChannelMap> {
|
||||
let mut cm = ChannelMap::default();
|
||||
let r: *mut ffi::pa_channel_map = unsafe {
|
||||
ffi::pa_channel_map_init_auto(&mut cm, ch, def)
|
||||
};
|
||||
let r: *mut ffi::pa_channel_map =
|
||||
unsafe { ffi::pa_channel_map_init_auto(&mut cm, ch, def) };
|
||||
if r.is_null() {
|
||||
None
|
||||
} else {
|
||||
|
|
|
@ -7,17 +7,18 @@ use ffi;
|
|||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type pa_once_cb_t = Option<unsafe extern "C" fn(m: *mut ffi::pa_mainloop_api,
|
||||
userdata: *mut c_void)>;
|
||||
type pa_once_cb_t =
|
||||
Option<unsafe extern "C" fn(m: *mut ffi::pa_mainloop_api, userdata: *mut c_void)>;
|
||||
fn wrap_once_cb<F>(_: F) -> pa_once_cb_t
|
||||
where F: Fn(&MainloopApi, *mut c_void)
|
||||
where
|
||||
F: Fn(&MainloopApi, *mut c_void),
|
||||
{
|
||||
assert!(mem::size_of::<F>() == 0);
|
||||
|
||||
unsafe extern "C" fn wrapped<F>(m: *mut ffi::pa_mainloop_api, userdata: *mut c_void)
|
||||
where F: Fn(&MainloopApi, *mut c_void)
|
||||
where
|
||||
F: Fn(&MainloopApi, *mut c_void),
|
||||
{
|
||||
let api = from_raw_ptr(m);
|
||||
let result = mem::transmute::<_, &F>(&())(&api, userdata);
|
||||
|
@ -36,7 +37,8 @@ impl MainloopApi {
|
|||
}
|
||||
|
||||
pub fn once<CB>(&self, cb: CB, userdata: *mut c_void)
|
||||
where CB: Fn(&MainloopApi, *mut c_void)
|
||||
where
|
||||
CB: Fn(&MainloopApi, *mut c_void),
|
||||
{
|
||||
let wrapped = wrap_once_cb(cb);
|
||||
unsafe {
|
||||
|
|
|
@ -11,7 +11,8 @@ pub struct Proplist(*mut ffi::pa_proplist);
|
|||
|
||||
impl Proplist {
|
||||
pub fn gets<T>(&self, key: T) -> Option<&CStr>
|
||||
where T: Into<Vec<u8>>
|
||||
where
|
||||
T: Into<Vec<u8>>,
|
||||
{
|
||||
let key = match CString::new(key) {
|
||||
Ok(k) => k,
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// This program is made available under an ISC-style license. See the
|
||||
// accompanying file LICENSE for details.
|
||||
|
||||
use ::*;
|
||||
use context;
|
||||
use ffi;
|
||||
use operation;
|
||||
|
@ -12,19 +11,28 @@ use std::mem::{self, forget, MaybeUninit};
|
|||
use std::os::raw::{c_int, c_void};
|
||||
use std::ptr;
|
||||
use util::*;
|
||||
use *;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stream(*mut ffi::pa_stream);
|
||||
|
||||
impl Stream {
|
||||
pub fn new<'a, CM>(c: &Context, name: &::std::ffi::CStr, ss: &SampleSpec, map: CM) -> Option<Self>
|
||||
where CM: Into<Option<&'a ChannelMap>>
|
||||
pub fn new<'a, CM>(
|
||||
c: &Context,
|
||||
name: &::std::ffi::CStr,
|
||||
ss: &SampleSpec,
|
||||
map: CM,
|
||||
) -> Option<Self>
|
||||
where
|
||||
CM: Into<Option<&'a ChannelMap>>,
|
||||
{
|
||||
let ptr = unsafe {
|
||||
ffi::pa_stream_new(c.raw_mut(),
|
||||
name.as_ptr(),
|
||||
ss as *const _,
|
||||
to_ptr(map.into()))
|
||||
ffi::pa_stream_new(
|
||||
c.raw_mut(),
|
||||
name.as_ptr(),
|
||||
ss as *const _,
|
||||
to_ptr(map.into()),
|
||||
)
|
||||
};
|
||||
if ptr.is_null() {
|
||||
None
|
||||
|
@ -45,9 +53,8 @@ impl Stream {
|
|||
}
|
||||
|
||||
pub fn get_state(&self) -> StreamState {
|
||||
StreamState::try_from(unsafe {
|
||||
ffi::pa_stream_get_state(self.raw_mut())
|
||||
}).expect("pa_stream_get_state returned invalid StreamState")
|
||||
StreamState::try_from(unsafe { ffi::pa_stream_get_state(self.raw_mut()) })
|
||||
.expect("pa_stream_get_state returned invalid StreamState")
|
||||
}
|
||||
|
||||
pub fn get_context(&self) -> Option<Context> {
|
||||
|
@ -87,38 +94,45 @@ impl Stream {
|
|||
error_result!(r != 0, r)
|
||||
}
|
||||
|
||||
pub fn connect_playback<'a, D, A, V, S>(&self,
|
||||
dev: D,
|
||||
attr: A,
|
||||
flags: StreamFlags,
|
||||
volume: V,
|
||||
sync_stream: S)
|
||||
-> Result<()>
|
||||
where D: Into<Option<&'a CStr>>,
|
||||
A: Into<Option<&'a BufferAttr>>,
|
||||
V: Into<Option<&'a CVolume>>,
|
||||
S: Into<Option<&'a mut Stream>>
|
||||
pub fn connect_playback<'a, D, A, V, S>(
|
||||
&self,
|
||||
dev: D,
|
||||
attr: A,
|
||||
flags: StreamFlags,
|
||||
volume: V,
|
||||
sync_stream: S,
|
||||
) -> Result<()>
|
||||
where
|
||||
D: Into<Option<&'a CStr>>,
|
||||
A: Into<Option<&'a BufferAttr>>,
|
||||
V: Into<Option<&'a CVolume>>,
|
||||
S: Into<Option<&'a mut Stream>>,
|
||||
{
|
||||
let r = unsafe {
|
||||
ffi::pa_stream_connect_playback(self.raw_mut(),
|
||||
str_to_ptr(dev.into()),
|
||||
to_ptr(attr.into()),
|
||||
flags.into(),
|
||||
to_ptr(volume.into()),
|
||||
map_to_mut_ptr(sync_stream.into(), |p| p.0))
|
||||
ffi::pa_stream_connect_playback(
|
||||
self.raw_mut(),
|
||||
str_to_ptr(dev.into()),
|
||||
to_ptr(attr.into()),
|
||||
flags.into(),
|
||||
to_ptr(volume.into()),
|
||||
map_to_mut_ptr(sync_stream.into(), |p| p.0),
|
||||
)
|
||||
};
|
||||
error_result!((), r)
|
||||
}
|
||||
|
||||
pub fn connect_record<'a, D, A>(&self, dev: D, attr: A, flags: StreamFlags) -> Result<()>
|
||||
where D: Into<Option<&'a CStr>>,
|
||||
A: Into<Option<&'a BufferAttr>>
|
||||
where
|
||||
D: Into<Option<&'a CStr>>,
|
||||
A: Into<Option<&'a BufferAttr>>,
|
||||
{
|
||||
let r = unsafe {
|
||||
ffi::pa_stream_connect_record(self.raw_mut(),
|
||||
str_to_ptr(dev.into()),
|
||||
to_ptr(attr.into()),
|
||||
flags.into())
|
||||
ffi::pa_stream_connect_record(
|
||||
self.raw_mut(),
|
||||
str_to_ptr(dev.into()),
|
||||
to_ptr(attr.into()),
|
||||
flags.into(),
|
||||
)
|
||||
};
|
||||
error_result!((), r)
|
||||
}
|
||||
|
@ -140,8 +154,16 @@ impl Stream {
|
|||
error_result!((), r)
|
||||
}
|
||||
|
||||
pub fn write(&self, data: *const c_void, nbytes: usize, offset: i64, seek: SeekMode) -> Result<()> {
|
||||
let r = unsafe { ffi::pa_stream_write(self.raw_mut(), data, nbytes, None, offset, seek.into()) };
|
||||
pub fn write(
|
||||
&self,
|
||||
data: *const c_void,
|
||||
nbytes: usize,
|
||||
offset: i64,
|
||||
seek: SeekMode,
|
||||
) -> Result<()> {
|
||||
let r = unsafe {
|
||||
ffi::pa_stream_write(self.raw_mut(), data, nbytes, None, offset, seek.into())
|
||||
};
|
||||
error_result!((), r)
|
||||
}
|
||||
|
||||
|
@ -182,13 +204,18 @@ impl Stream {
|
|||
}
|
||||
|
||||
pub fn update_timing_info<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
|
||||
where CB: Fn(&Stream, i32, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Stream, i32, *mut c_void),
|
||||
{
|
||||
assert_eq!(mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(s: *mut ffi::pa_stream, success: c_int, userdata: *mut c_void)
|
||||
where F: Fn(&Stream, i32, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
s: *mut ffi::pa_stream,
|
||||
success: c_int,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Stream, i32, *mut c_void),
|
||||
{
|
||||
let mut stm = stream::from_raw_ptr(s);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -198,7 +225,9 @@ impl Stream {
|
|||
result
|
||||
}
|
||||
|
||||
let r = unsafe { ffi::pa_stream_update_timing_info(self.raw_mut(), Some(wrapped::<CB>), userdata) };
|
||||
let r = unsafe {
|
||||
ffi::pa_stream_update_timing_info(self.raw_mut(), Some(wrapped::<CB>), userdata)
|
||||
};
|
||||
if r.is_null() {
|
||||
let err = if let Some(c) = self.get_context() {
|
||||
c.errno()
|
||||
|
@ -217,13 +246,15 @@ impl Stream {
|
|||
}
|
||||
|
||||
pub fn set_state_callback<CB>(&self, _: CB, userdata: *mut c_void)
|
||||
where CB: Fn(&Stream, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Stream, *mut c_void),
|
||||
{
|
||||
assert_eq!(mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(s: *mut ffi::pa_stream, userdata: *mut c_void)
|
||||
where F: Fn(&Stream, *mut c_void)
|
||||
where
|
||||
F: Fn(&Stream, *mut c_void),
|
||||
{
|
||||
let mut stm = stream::from_raw_ptr(s);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -245,13 +276,18 @@ impl Stream {
|
|||
}
|
||||
|
||||
pub fn set_write_callback<CB>(&self, _: CB, userdata: *mut c_void)
|
||||
where CB: Fn(&Stream, usize, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Stream, usize, *mut c_void),
|
||||
{
|
||||
assert_eq!(mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(s: *mut ffi::pa_stream, nbytes: usize, userdata: *mut c_void)
|
||||
where F: Fn(&Stream, usize, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
s: *mut ffi::pa_stream,
|
||||
nbytes: usize,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Stream, usize, *mut c_void),
|
||||
{
|
||||
let mut stm = stream::from_raw_ptr(s);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -273,13 +309,18 @@ impl Stream {
|
|||
}
|
||||
|
||||
pub fn set_read_callback<CB>(&self, _: CB, userdata: *mut c_void)
|
||||
where CB: Fn(&Stream, usize, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Stream, usize, *mut c_void),
|
||||
{
|
||||
assert_eq!(mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(s: *mut ffi::pa_stream, nbytes: usize, userdata: *mut c_void)
|
||||
where F: Fn(&Stream, usize, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
s: *mut ffi::pa_stream,
|
||||
nbytes: usize,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Stream, usize, *mut c_void),
|
||||
{
|
||||
let mut stm = stream::from_raw_ptr(s);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -295,13 +336,18 @@ impl Stream {
|
|||
}
|
||||
|
||||
pub fn cork<CB>(&self, b: i32, _: CB, userdata: *mut c_void) -> Result<Operation>
|
||||
where CB: Fn(&Stream, i32, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Stream, i32, *mut c_void),
|
||||
{
|
||||
assert_eq!(mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(s: *mut ffi::pa_stream, success: c_int, userdata: *mut c_void)
|
||||
where F: Fn(&Stream, i32, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
s: *mut ffi::pa_stream,
|
||||
success: c_int,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Stream, i32, *mut c_void),
|
||||
{
|
||||
let mut stm = stream::from_raw_ptr(s);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -368,13 +414,18 @@ impl Stream {
|
|||
}
|
||||
|
||||
pub fn set_name<CB>(&self, name: &CStr, _: CB, userdata: *mut c_void) -> Result<Operation>
|
||||
where CB: Fn(&Stream, i32, *mut c_void)
|
||||
where
|
||||
CB: Fn(&Stream, i32, *mut c_void),
|
||||
{
|
||||
assert_eq!(mem::size_of::<CB>(), 0);
|
||||
|
||||
// See: A note about `wrapped` functions
|
||||
unsafe extern "C" fn wrapped<F>(s: *mut ffi::pa_stream, success: c_int, userdata: *mut c_void)
|
||||
where F: Fn(&Stream, i32, *mut c_void)
|
||||
unsafe extern "C" fn wrapped<F>(
|
||||
s: *mut ffi::pa_stream,
|
||||
success: c_int,
|
||||
userdata: *mut c_void,
|
||||
) where
|
||||
F: Fn(&Stream, i32, *mut c_void),
|
||||
{
|
||||
let mut stm = stream::from_raw_ptr(s);
|
||||
let cb = MaybeUninit::<F>::uninit();
|
||||
|
@ -384,7 +435,9 @@ impl Stream {
|
|||
result
|
||||
}
|
||||
|
||||
let r = unsafe { ffi::pa_stream_set_name(self.raw_mut(), name.as_ptr(), Some(wrapped::<CB>), userdata) };
|
||||
let r = unsafe {
|
||||
ffi::pa_stream_set_name(self.raw_mut(), name.as_ptr(), Some(wrapped::<CB>), userdata)
|
||||
};
|
||||
if r.is_null() {
|
||||
let err = if let Some(c) = self.get_context() {
|
||||
c.errno()
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
// This program is made available under an ISC-style license. See the
|
||||
// accompanying file LICENSE for details.
|
||||
|
||||
use ErrorCode;
|
||||
use Result;
|
||||
use ffi;
|
||||
use mainloop_api;
|
||||
use mainloop_api::MainloopApi;
|
||||
use ErrorCode;
|
||||
use Result;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ThreadedMainloop(*mut ffi::pa_threaded_mainloop);
|
||||
|
|
|
@ -12,7 +12,8 @@ pub trait UnwrapCStr {
|
|||
}
|
||||
|
||||
impl<'a, U> UnwrapCStr for U
|
||||
where U: Into<Option<&'a CStr>>
|
||||
where
|
||||
U: Into<Option<&'a CStr>>,
|
||||
{
|
||||
fn unwrap_cstr(self) -> *const c_char {
|
||||
self.into().map(|o| o.as_ptr()).unwrap_or(0 as *const _)
|
||||
|
|
Загрузка…
Ссылка в новой задаче