A lot of pointless stuff
Some checks failed
ci/woodpecker/push/pre_commit_test Pipeline failed
ci/woodpecker/push/code_tests Pipeline failed

This commit is contained in:
2025-12-05 19:32:32 +01:00
parent 50ebac998c
commit 4810b19eea
10 changed files with 238 additions and 36 deletions

View File

@@ -0,0 +1,19 @@
use crate::audio_engine::AudioBackend;
pub(crate) struct CoreAudioBackend {}
impl CoreAudioBackend {}
#[cfg(feature = "coreaudio")]
impl AudioBackend for CoreAudioBackend {
fn start_client(&mut self) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
}
#[cfg(not(feature = "coreaudio"))]
impl AudioBackend for CoreAudioBackend {
fn start_client(&mut self) -> Result<(), Box<dyn std::error::Error>> {
todo!()
}
}

View File

@@ -0,0 +1,15 @@
use crate::audio_engine::AudioBackend;
struct DummyAudioBackend {}
impl DummyAudioBackend {
fn new() -> Self {
Self { }
}
}
impl AudioBackend for DummyAudioBackend {
fn start_client(&mut self) -> Result<(), Box<dyn std::error::Error>> {
todo!()
}
}

View File

@@ -1,24 +1,106 @@
use log::{info, warn};
use std::error::Error;
use crate::audio_engine::AudioBackend;
use crossbeam_channel::bounded;
#[cfg(feature = "jack")]
use jack;
pub(crate) struct JackAudioBackend {
pub(crate) feature_jack: bool,
pub(crate) running: bool,
status: JackStatus,
}
impl JackAudioBackend {
pub(crate) fn new() -> Self {
let feature_jack = cfg!(feature = "jack");
// TODO: It should be retrieved from the system
let running = true;
Self { feature_jack, running }
let status = JackStatus::default();
Self {
feature_jack,
running,
status,
}
}
}
#[cfg(feature = "jack")]
#[derive(Default)]
pub(crate) struct JackStatus {
client: Option<jack::Client>,
status: Option<jack::ClientStatus>,
}
#[cfg(feature = "jack")]
impl AudioBackend for JackAudioBackend {
fn start_client(&self) {
todo!()
fn start_client(&mut self) -> Result<(), Box<dyn Error>> {
info!("starting the jack client");
let (client, status) =
jack::Client::new("termix_engine", jack::ClientOptions::default())?;
//self.status.client = Some(client);
self.status.status = Some(status);
let out_port = client.register_port("termix_output", jack::AudioOut::default())?;
let (tx, rx) = bounded(1_000_000);
struct State {
out_port: jack::Port<jack::AudioOut>,
rx: crossbeam_channel::Receiver<f64>,
frequency: f64,
frame_t: f64,
time: f64,
}
let process = jack::contrib::ClosureProcessHandler::with_state(
State {
out_port,
rx,
frequency: 220.0,
frame_t: 1.0 / client.sample_rate() as f64,
time: 0.0,
},
|state, _, ps| -> jack::Control {
// Get output buffer
let out = state.out_port.as_mut_slice(ps);
// Check frequency requests
while let Ok(f) = state.rx.try_recv() {
state.time = 0.0;
state.frequency = f;
}
// Write output
for v in out.iter_mut() {
let x = state.frequency * state.time * 2.0 * std::f64::consts::PI;
let y = x.sin();
*v = y as f32;
state.time += state.frame_t;
}
// Continue as normal
jack::Control::Continue
},
move |_, _, _| jack::Control::Continue,
);
let active_client = client.activate_async((), process).unwrap();
active_client
.as_client()
.connect_ports_by_name("termix_engine:termix_output", "system:playback_1")
.unwrap();
active_client
.as_client()
.connect_ports_by_name("termix_engine:termix_output", "system:playback_2")
.unwrap();
/* TODO:
* - Create a port for the main output
* - Define the jack options
* - buffer size
* - sample rate
* - Define the callback function
* - Activate the client
*/
Ok(())
}
fn init_client(&self) {
@@ -28,12 +110,21 @@ impl AudioBackend for JackAudioBackend {
fn discover(&self) {
todo!()
}
fn stop_client(&self) -> Result<(), Box<dyn Error>> {
todo!()
}
}
#[cfg(not(feature = "jack"))]
#[derive(Default)]
pub(crate) struct JackStatus {}
#[cfg(not(feature = "jack"))]
impl AudioBackend for JackAudioBackend {
fn start_client(&self) {
unimplemented!()
fn start_client(&mut self) -> Result<(), Box<dyn Error>> {
warn!("jack support is not enabled");
Ok(())
}
fn init_client(&self) {
@@ -43,4 +134,8 @@ impl AudioBackend for JackAudioBackend {
fn discover(&self) {
unimplemented!()
}
fn stop_client(&self) -> Result<(), Box<dyn Error>> {
todo!()
}
}

View File

@@ -1,12 +1,12 @@
use std::error::Error;
pub(crate) mod jack_ab;
pub(crate) mod coreaudio_ab;
pub(crate) mod dummy_ab;
pub(crate) trait AudioBackend {
// Start a audio backend client
// It should be executed either on the startup,
// or when the audio backend is switched
fn start_client(&self);
// Initialization of the client should happen
// when a project is opened.
fn init_client(&self);
fn discover(&self);
fn start_client(&mut self) -> Result<(), Box<dyn Error>>;
}

View File

@@ -1,13 +1,11 @@
use lib::termix::audio_backend::{
self, Backend, BackendList, FILE_DESCRIPTOR_SET,
audio_backend_server::{AudioBackend, AudioBackendServer},
};
use std::result::Result;
use lib::termix::{self, audio_backend::{Backend, BackendList, DesiredAudioBacked, FILE_DESCRIPTOR_SET, SupportedAudioBackends, audio_backend_rpc_server::{AudioBackendRpc, AudioBackendRpcServer}}};
use log::info;
use tonic::{Response, transport::Server};
use tonic_reflection::server;
use crate::{audio_engine::jack_ab::JackAudioBackend, control_pane::ControlPane};
use crate::{audio_engine::{AudioBackend, jack_ab::{self, JackAudioBackend}}, control_pane::ControlPane};
pub(crate) struct Grpc {
pub(crate) port: i32,
@@ -28,7 +26,7 @@ impl ControlPane for Grpc {
server
.add_service(audio_backend_reflections)
.add_service(AudioBackendServer::new(audio_backend))
.add_service(AudioBackendRpcServer::new(audio_backend))
.serve(addr)
.await?;
@@ -40,34 +38,51 @@ impl ControlPane for Grpc {
pub struct TermixAudioBackend {}
#[tonic::async_trait]
impl AudioBackend for TermixAudioBackend {
impl AudioBackendRpc for TermixAudioBackend {
async fn start_client(
&self,
requesa: tonic::Request<()>,
) -> std::result::Result<tonic::Response<()>, tonic::Status> {
request: tonic::Request<DesiredAudioBacked>,
) -> Result<tonic::Response<()>, tonic::Status> {
info!("starting the audio backend client");
match request.get_ref().backend() {
SupportedAudioBackends::AbUnspecified => {
unimplemented!("unsupported backend");
},
SupportedAudioBackends::AbJack => {
info!("trying to use JACK as the backend");
let mut ab = jack_ab::JackAudioBackend::new();
ab.start_client();
},
};
Ok(Response::new(()))
}
async fn stop_client(
&self,
_: tonic::Request<()>,
) -> Result<tonic::Response<()>, tonic::Status> {
todo!()
}
async fn init_connection(
&self,
request: tonic::Request<()>,
) -> std::result::Result<tonic::Response<()>, tonic::Status> {
) -> Result<tonic::Response<()>, tonic::Status> {
info!("initializing the connection to the audio backend");
todo!()
}
async fn get_available_backends(
&self,
request: tonic::Request<()>,
_: tonic::Request<()>,
) -> Result<Response<BackendList>, tonic::Status> {
info!("discovering available backends");
let mut response = BackendList::default();
let jack = JackAudioBackend::new();
if jack.feature_jack {
response.backends.push(Backend {
name: "jack".to_string(),
});
response.backends.push(Backend {
name: "jack".to_string(),
});
}
Ok(Response::new(response))
}