Merge pull request #6 from dorindabassey/vsound_newtx

instantiate new backend
This commit is contained in:
dorindabassey 2023-07-03 16:57:26 +02:00 committed by GitHub
commit 4cf4e675ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 121 additions and 14 deletions

View File

@ -10,7 +10,7 @@ license = "Apache-2.0 OR BSD-3-Clause"
edition = "2018"
[features]
default = ["null-backend"]
default = ["null-backend", "pw-backend"]
null-backend = []
pw-backend = ["pipewire", "libspa", "pipewire-sys", "libspa-sys", "bindgen"]

View File

@ -9,13 +9,32 @@ mod pw_backend;
#[cfg(feature = "null-backend")]
use self::null::NullBackend;
#[cfg(feature = "pw-backend")]
use self::pw_backend::PwBackend;
use crate::{Error, Result, SoundRequest};
use self::pw_backend::{PwBackend, PCMParams};
use crate::{Error, Result};
pub trait AudioBackend {
fn write(&self, req: &SoundRequest) -> Result<()>;
fn write(&self, stream_id: u32) -> Result<()>;
fn read(&self, stream_id: u32) -> Result<()>;
fn read(&self, req: &mut SoundRequest) -> Result<()>;
fn set_param(&self, _stream_id: u32, _params: PCMParams) -> Result<()> {
Ok(())
}
fn prepare(&self, _stream_id: u32) -> Result<()> {
Ok(())
}
fn release(&self, _stream_id: u32) -> Result<()> {
Ok(())
}
fn start(&self, _stream_id: u32) -> Result<()> {
Ok(())
}
fn stop(&self, _stream_id: u32) -> Result<()> {
Ok(())
}
}
pub fn alloc_audio_backend(name: String) -> Result<Box<dyn AudioBackend + Send + Sync>> {

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
use super::AudioBackend;
use crate::{Error, Result, SoundRequest};
use crate::{Error, Result};
pub struct NullBackend {}
@ -12,16 +12,20 @@ impl NullBackend {
}
impl AudioBackend for NullBackend {
fn write(&self, _req: &SoundRequest) -> Result<()> {
fn write(&self, stream_id: u32) -> Result<()> {
println!("null backend, writting to stream: {}", stream_id);
Ok(())
}
fn read(&self, req: &mut SoundRequest) -> Result<()> {
fn read(&self, _stream_id: u32) -> Result<()> {
/*
let buf = req.data_slice().ok_or(Error::SoundReqMissingData)?;
let zero_mem = vec![0u8; buf.len()];
buf.copy_from(&zero_mem);
*/
Ok(())
}
}

View File

@ -2,27 +2,111 @@
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
use super::AudioBackend;
use crate::{Error, Result, SoundRequest};
use std::{thread};
use std::{cell::Cell, rc::Rc};
use crate::{Error, Result};
pub struct PwBackend {}
use vm_memory::{Le32, Le64};
use pipewire as pw;
use pw::{sys::*};
#[derive(Default, Debug)]
pub struct StreamInfo {
pub id: usize,
pub params: PCMParams,
pub formats: Le64,
pub rates: Le64,
pub direction: u8,
pub channels_min: u8,
pub channels_max: u8,
}
#[derive(Default, Debug)]
pub struct PCMParams {
pub features: Le32,
/// size of hardware buffer in bytes
pub buffer_bytes: Le32,
/// size of hardware period in bytes
pub period_bytes: Le32,
pub channels: u8,
pub format: u8,
pub rate: u8,
}
// SAFETY: Safe as the structure can be sent to another thread.
unsafe impl Send for WrapMainLoop {}
// SAFETY: Safe as the structure can be shared with another thread as the state
// is protected with a lock.
unsafe impl Sync for WrapMainLoop {}
#[derive(Clone, Debug)]
pub struct WrapMainLoop {
mainloop: pipewire::MainLoop,
}
pub struct PwBackend {
//pub streams: Arc<RwLock<Vec<StreamInfo>>>,
}
impl PwBackend {
pub fn new() -> Self {
PwBackend {}
pw::init();
let wrap_mainloop = WrapMainLoop {
mainloop : pw::MainLoop::new().expect("we can't create mainloop")
};
//let mainloop = pw::MainLoop::new().expect("Failed to create Pipewire Mainloop");
let context = pw::Context::new(&wrap_mainloop.mainloop).expect("Failed to create Pipewire Context");
let core = context
.connect(None)
.expect("Failed to connect to Pipewire Core");
// To comply with Rust's safety rules, we wrap this variable in an `Rc` and a `Cell`.
let done = Rc::new(Cell::new(false));
// Create new reference for each variable so that they can be moved into the closure.
let done_clone = done.clone();
let loop_clone = wrap_mainloop.mainloop.clone();
let pending = core.sync(0).expect("sync failed");
let _listener_core = core
.add_listener_local()
.done(move |id, seq| {
if id == PW_ID_CORE && seq == pending {
done_clone.set(true);
loop_clone.quit();
}
})
.register();
thread::spawn(move || {
wrap_mainloop.mainloop.run();
});
println!("pipewire backend running");
Self {
}
}
}
impl AudioBackend for PwBackend {
fn write(&self, _req: &SoundRequest) -> Result<()> {
fn write(&self, stream_id: u32) -> Result<()> {
println!("pipewire backend, writting to stream: {}", stream_id);
Ok(())
}
fn read(&self, req: &mut SoundRequest) -> Result<()> {
fn read(&self, _stream_id: u32) -> Result<()> {
/*
let buf = req.data_slice().ok_or(Error::SoundReqMissingData)?;
let zero_mem = vec![0u8; buf.len()];
buf.copy_from(&zero_mem);
*/
Ok(())
}
fn set_param(&self, _stream_id: u32, _params: PCMParams) -> Result<()> {
Ok(())
}
}