Skip to content

Commit b9cb062

Browse files
committed
[*] refactoring: can easy support different platform
1 parent b8e2be8 commit b9cb062

26 files changed

+330
-273
lines changed

Cargo.lock

Lines changed: 23 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,6 @@ mp4m = { path = "lib/mp4m" }
110110
cutil = { path = "lib/cutil" }
111111
sqldb = { path = "lib/sqldb" }
112112
pmacro = { path = "lib/pmacro" }
113-
recorder = { path = "lib/recorder" }
114113
screen-capture = { path = "lib/screen-capture" }
115-
wayland-wlr-screen-capture = { path = "lib/wayland-wlr-screen-capture" }
114+
recorder = { path = "lib/recorder", default-features = false }
115+
screen-capture-wayland-wlr = { path = "lib/screen-capture-wayland-wlr" }

Makefile

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ desktop-build-env = SLINT_STYLE=fluent $(build-env)
1010
web-build-env = SLINT_STYLE=fluent $(build-env) RUSTFLAGS='--cfg getrandom_backend="wasm_js"'
1111

1212
run-env = RUST_LOG=debug
13-
proj-features = --features=desktop,database,qrcode,center-window
13+
proj-features = --features=${desktop-features},database,qrcode,center-window
14+
desktop-features = desktop-wayland-wlr
1415

1516
all: desktop-build-release
1617

@@ -24,23 +25,22 @@ android-debug:
2425
$(android-build-env) $(run-env) cargo apk run --lib -p ${app-name} --no-default-features --features=mobile,android
2526

2627
desktop-build:
27-
$(desktop-build-env) cargo build --no-default-features --features=desktop
28+
$(desktop-build-env) cargo build --no-default-features --features=${desktop-features}
2829

2930
desktop-build-release:
30-
$(desktop-build-env) cargo build --release --no-default-features --features=desktop
31+
$(desktop-build-env) cargo build --release --no-default-features --features=${desktop-features}
3132

3233
desktop-debug:
33-
$(desktop-build-env) $(run-env) cargo run --bin ${app-name} --no-default-features --features=desktop
34+
$(desktop-build-env) $(run-env) cargo run --bin ${app-name} --no-default-features --features=${desktop-features}
3435

3536
desktop-debug-winit:
36-
SLINT_BACKEND=winit-femtovg $(desktop-build-env) $(run-env) cargo run --bin ${app-name} --no-default-features --features=desktop
37+
SLINT_BACKEND=winit-femtovg $(desktop-build-env) $(run-env) cargo run --bin ${app-name} --no-default-features --features=${desktop-features}
3738

3839
desktop-run-release:
39-
$(desktop-build-env) RUST_LOG=info cargo run --release --bin ${app-name} --no-default-features --features=desktop
40-
40+
$(desktop-build-env) RUST_LOG=info cargo run --release --bin ${app-name} --no-default-features --features=${desktop-features}
4141

4242
desktop-run-release-winit:
43-
SLINT_BACKEND=winit-femtovg $(desktop-build-env) RUST_LOG=info cargo run --release --bin ${app-name} --no-default-features --features=desktop
43+
SLINT_BACKEND=winit-femtovg $(desktop-build-env) RUST_LOG=info cargo run --release --bin ${app-name} --no-default-features --features=${desktop-features}
4444

4545
web-build:
4646
cd $(app-name) && $(web-build-env) wasm-pack build --no-opt --dev --target web --out-dir ./web/pkg --no-default-features --features=web

lib/recorder/Cargo.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ mp4m.workspace = true
1818
hound.workspace = true
1919
image.workspace = true
2020
chrono.workspace = true
21-
pipewire.workspace = true
2221
crossbeam.workspace = true
2322
thiserror.workspace = true
2423
once_cell.workspace = true
@@ -28,12 +27,15 @@ derive_setters.workspace = true
2827
screen-capture.workspace = true
2928
yuv = { workspace = true, features = ["rayon"] }
3029
fast_image_resize = { workspace = true, features = ["rayon"] }
31-
wayland-wlr-screen-capture = { workspace = true, optional = true }
30+
31+
[target.'cfg(target_os = "linux")'.dependencies]
32+
pipewire.workspace = true
33+
screen-capture-wayland-wlr = { workspace = true, optional = true }
3234

3335
[dev-dependencies]
3436
ctrlc.workspace = true
3537
env_logger.workspace = true
3638

3739
[features]
3840
default = ["wayland-wlr"]
39-
wayland-wlr = ["dep:wayland-wlr-screen-capture"]
41+
wayland-wlr = ["dep:screen-capture-wayland-wlr"]

lib/recorder/examples/speaker_recording_demo.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use hound::WavWriter;
2-
use recorder::{SpeakerRecorder, bounded};
2+
use recorder::{SpeakerRecorder, SpeakerRecorderConfig, bounded, platform_speaker_recoder};
33
use std::{
44
error::Error,
55
path::PathBuf,
@@ -32,7 +32,9 @@ fn main() -> Result<(), Box<dyn Error>> {
3232

3333
let handle = thread::spawn(move || {
3434
let save_path = PathBuf::from("/tmp/speaker_output.wav");
35-
let spec = SpeakerRecorder::spec();
35+
let spec = platform_speaker_recoder(SpeakerRecorderConfig::default())
36+
.unwrap()
37+
.spec();
3638

3739
let mut writer = match WavWriter::create(&save_path, spec) {
3840
Ok(writer) => {
@@ -60,9 +62,8 @@ fn main() -> Result<(), Box<dyn Error>> {
6062
}
6163
});
6264

63-
SpeakerRecorder::new(stop_sig)?
64-
.with_frame_sender(Some(sender))
65-
.start_recording()?;
65+
let config = SpeakerRecorderConfig::new(stop_sig).with_frame_sender(Some(sender));
66+
platform_speaker_recoder(config)?.start_recording()?;
6667

6768
handle.join().unwrap();
6869

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use thiserror::Error;
1717
static DENOISE_MODEL: Lazy<RnnModel> = Lazy::new(|| denoise_model());
1818

1919
#[derive(Debug, Error)]
20-
pub enum AudioError {
20+
pub enum AudioRecorderError {
2121
#[error("Audio host error: {0}")]
2222
HostError(String),
2323

@@ -66,15 +66,15 @@ impl AudioRecorder {
6666
}
6767
}
6868

69-
pub fn get_available_devices(&self) -> Result<Vec<AudioDeviceInfo>, AudioError> {
69+
pub fn get_available_devices(&self) -> Result<Vec<AudioDeviceInfo>, AudioRecorderError> {
7070
self.get_input_devices()
7171
}
7272

73-
pub fn get_input_devices(&self) -> Result<Vec<AudioDeviceInfo>, AudioError> {
73+
pub fn get_input_devices(&self) -> Result<Vec<AudioDeviceInfo>, AudioRecorderError> {
7474
let devices = self
7575
.host
7676
.input_devices()
77-
.map_err(|e| AudioError::HostError(e.to_string()))?;
77+
.map_err(|e| AudioRecorderError::HostError(e.to_string()))?;
7878

7979
let mut input_devices = Vec::new();
8080
for device in devices {
@@ -86,20 +86,20 @@ impl AudioRecorder {
8686
Ok(input_devices)
8787
}
8888

89-
pub fn get_default_input_device(&self) -> Result<Option<AudioDeviceInfo>, AudioError> {
89+
pub fn get_default_input_device(&self) -> Result<Option<AudioDeviceInfo>, AudioRecorderError> {
9090
if let Some(device) = self.host.default_input_device() {
9191
self.get_device_info(&device)
9292
.map(Some)
93-
.map_err(|e| AudioError::DeviceError(e.to_string()))
93+
.map_err(|e| AudioRecorderError::DeviceError(e.to_string()))
9494
} else {
9595
Ok(None)
9696
}
9797
}
9898

99-
fn get_device_info(&self, device: &Device) -> Result<AudioDeviceInfo, AudioError> {
99+
fn get_device_info(&self, device: &Device) -> Result<AudioDeviceInfo, AudioRecorderError> {
100100
let name = device
101101
.name()
102-
.map_err(|e| AudioError::DeviceError(e.to_string()))?;
102+
.map_err(|e| AudioRecorderError::DeviceError(e.to_string()))?;
103103

104104
let default_config = device
105105
.default_input_config()
@@ -118,19 +118,27 @@ impl AudioRecorder {
118118
})
119119
}
120120

121-
pub fn find_device_by_name(&self, name: &str) -> Result<Option<AudioDeviceInfo>, AudioError> {
121+
pub fn find_device_by_name(
122+
&self,
123+
name: &str,
124+
) -> Result<Option<AudioDeviceInfo>, AudioRecorderError> {
122125
let devices = self.get_available_devices()?;
123126
Ok(devices.into_iter().find(|device| device.name == name))
124127
}
125128

126-
pub fn get_config(&self, name: &str) -> Result<(StreamConfig, Vec<SampleFormat>), AudioError> {
129+
pub fn get_config(
130+
&self,
131+
name: &str,
132+
) -> Result<(StreamConfig, Vec<SampleFormat>), AudioRecorderError> {
127133
let device_infos = self.find_device_by_name(name)?;
128134
let Some(device_info) = device_infos else {
129-
return Err(AudioError::DeviceError(format!("no found device `{name}`")));
135+
return Err(AudioRecorderError::DeviceError(format!(
136+
"no found device `{name}`"
137+
)));
130138
};
131139

132140
let Some(default_config) = device_info.default_config else {
133-
return Err(AudioError::DeviceError(format!(
141+
return Err(AudioRecorderError::DeviceError(format!(
134142
"no found default_config for device `{name}`"
135143
)));
136144
};
@@ -142,16 +150,16 @@ impl AudioRecorder {
142150
&self,
143151
device_name: &str,
144152
callback: impl FnMut(&[f32], &InputCallbackInfo) + Send + 'static,
145-
) -> Result<Stream, AudioError> {
153+
) -> Result<Stream, AudioRecorderError> {
146154
let (stream_config, _) = self.get_config(device_name)?;
147155

148156
let physical_device = self
149157
.host
150158
.input_devices()
151-
.map_err(|e| AudioError::HostError(e.to_string()))?
159+
.map_err(|e| AudioRecorderError::HostError(e.to_string()))?
152160
.find(|d| d.name().map(|name| name == device_name).unwrap_or(false))
153161
.ok_or_else(|| {
154-
AudioError::DeviceError(format!("Device '{}' not found", device_name))
162+
AudioRecorderError::DeviceError(format!("Device '{}' not found", device_name))
155163
})?;
156164

157165
let stream = physical_device
@@ -161,16 +169,16 @@ impl AudioRecorder {
161169
|err| eprintln!("Audio stream error: {}", err),
162170
None,
163171
)
164-
.map_err(|e| AudioError::StreamError(e.to_string()))?;
172+
.map_err(|e| AudioRecorderError::StreamError(e.to_string()))?;
165173

166174
stream
167175
.play()
168-
.map_err(|e| AudioError::StreamError(e.to_string()))?;
176+
.map_err(|e| AudioRecorderError::StreamError(e.to_string()))?;
169177

170178
Ok(stream)
171179
}
172180

173-
pub fn spec(&self, device_name: &str) -> Result<WavSpec, AudioError> {
181+
pub fn spec(&self, device_name: &str) -> Result<WavSpec, AudioRecorderError> {
174182
let (stream_config, _) = self.get_config(device_name)?;
175183

176184
Ok(WavSpec {
@@ -181,14 +189,14 @@ impl AudioRecorder {
181189
})
182190
}
183191

184-
pub fn start_recording(&mut self, device_name: &str) -> Result<(), AudioError> {
192+
pub fn start_recording(&mut self, device_name: &str) -> Result<(), AudioRecorderError> {
185193
// Note:
186194
// Without calling `denoise.flush` is not a problem.
187195
// Just losing the last frame of real-time samples.
188196
let mut denoiser = if self.enable_denoise {
189197
let spec = self.spec(device_name)?;
190198
let denoiser = RealTimeDenoise::new(&DENOISE_MODEL, spec)
191-
.map_err(|e| AudioError::DenoiseError(e.to_string()))?;
199+
.map_err(|e| AudioRecorderError::DenoiseError(e.to_string()))?;
192200
Some(denoiser)
193201
} else {
194202
None

lib/recorder/src/error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ pub enum RecorderError {
2424
QueueError(String),
2525

2626
#[error("Audio recording failed: {0}")]
27-
AudioError(#[from] super::record_audio::AudioError),
27+
AudioRecorderError(#[from] super::audio_recorder::AudioRecorderError),
2828

2929
#[error("Speaker recording failed: {0}")]
30-
SpeakerError(#[from] super::record_speaker::SpeakerError),
30+
SpeakerRecorderError(#[from] super::speaker_recorder::SpeakerRecorderError),
3131

3232
#[error("Audio mixer config builder failed: {0}")]
3333
AudioMixerConfigBuilderError(#[from] mp4m::audio_processor::AudioProcessorConfigBuilderError),

lib/recorder/src/lib.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
mod audio_level;
2+
mod audio_recorder;
23
mod config;
34
mod denoise;
45
mod error;
5-
mod record_audio;
6-
mod record_speaker;
76
mod recorder;
87
mod resolution;
8+
mod speaker_recorder;
99
mod video_encoder;
1010

1111
pub use audio_level::*;
12+
pub use audio_recorder::{AudioDeviceInfo, AudioRecorder, AudioRecorderError};
1213
pub use config::{FPS, RecorderConfig, SimpleFpsCounter};
1314
pub use crossbeam::channel::{Receiver, Sender, bounded};
1415
pub use denoise::*;
1516
pub use error::RecorderError;
16-
pub use record_audio::{AudioDeviceInfo, AudioError, AudioRecorder};
17-
pub use record_speaker::SpeakerRecorder;
1817
pub use recorder::RecordingSession;
1918
pub use resolution::Resolution;
19+
pub use speaker_recorder::{
20+
SpeakerRecorder, SpeakerRecorderConfig, SpeakerRecorderError, platform_speaker_recoder,
21+
};
2022
pub use video_encoder::{EncodedFrame, VideoEncoder};
2123

2224
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -46,8 +48,8 @@ pub struct FrameUser {
4648
}
4749

4850
pub fn platform_screen_capture() -> impl screen_capture::ScreenCapture + Clone + Send + 'static {
49-
#[cfg(feature = "wayland-wlr")]
50-
let screen_capturer = wayland_wlr_screen_capture::WaylandWlrScreenCapture::new();
51+
#[cfg(all(target_os = "linux", feature = "wayland-wlr"))]
52+
let screen_capturer = screen_capture_wayland_wlr::ScreenCaptureWaylandWlr::default();
5153

5254
screen_capturer
5355
}

0 commit comments

Comments
 (0)