style: apply current rustfmt to the tree
A newer rustfmt wraps over-long match arms and call expressions that the version main was last formatted with left on one line. Pure formatting, no semantic change — split out so the friends-list feature commits stay focused on real changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+23
-19
@@ -52,9 +52,8 @@ impl Routing {
|
||||
let pid = std::process::id();
|
||||
let sink_name = format!("pixelpass_capture_{pid}");
|
||||
|
||||
let sink_module =
|
||||
load_module(&["module-null-sink", &format!("sink_name={sink_name}")])
|
||||
.context("failed to load module-null-sink")?;
|
||||
let sink_module = load_module(&["module-null-sink", &format!("sink_name={sink_name}")])
|
||||
.context("failed to load module-null-sink")?;
|
||||
|
||||
// 20ms loopback latency keeps the mirrored audio tight; pactl's
|
||||
// default of 200ms is enough to be perceptible.
|
||||
@@ -205,7 +204,9 @@ fn parse_sink_inputs(stdout: &[u8]) -> Result<Vec<App>> {
|
||||
serde_json::from_slice(stdout).context("pactl returned unparseable JSON")?;
|
||||
let mut counts: BTreeMap<String, u32> = BTreeMap::new();
|
||||
for entry in entries {
|
||||
let Some(name) = entry.properties.application_name else { continue };
|
||||
let Some(name) = entry.properties.application_name else {
|
||||
continue;
|
||||
};
|
||||
let trimmed = name.trim();
|
||||
if trimmed.is_empty() {
|
||||
continue;
|
||||
@@ -359,16 +360,14 @@ fn run_router(
|
||||
) -> Result<()> {
|
||||
use pipewire::{self as pw, types::ObjectType};
|
||||
|
||||
let main_loop = pw::main_loop::MainLoopRc::new(None)
|
||||
.context("pw main loop construction failed")?;
|
||||
let context = pw::context::ContextRc::new(&main_loop, None)
|
||||
.context("pw context construction failed")?;
|
||||
let main_loop =
|
||||
pw::main_loop::MainLoopRc::new(None).context("pw main loop construction failed")?;
|
||||
let context =
|
||||
pw::context::ContextRc::new(&main_loop, None).context("pw context construction failed")?;
|
||||
let core = context
|
||||
.connect_rc(None)
|
||||
.context("pw core connect failed (is the daemon running?)")?;
|
||||
let registry = core
|
||||
.get_registry_rc()
|
||||
.context("pw get_registry failed")?;
|
||||
let registry = core.get_registry_rc().context("pw get_registry failed")?;
|
||||
|
||||
let state = Rc::new(RefCell::new(RouterState {
|
||||
sink_serial: None,
|
||||
@@ -409,20 +408,21 @@ fn run_router(
|
||||
let _reg_listener = registry
|
||||
.add_listener_local()
|
||||
.global(move |obj| {
|
||||
let Some(reg) = registry_weak.upgrade() else { return };
|
||||
let Some(reg) = registry_weak.upgrade() else {
|
||||
return;
|
||||
};
|
||||
match obj.type_ {
|
||||
ObjectType::Node => {
|
||||
let Some(props) = obj.props.as_ref() else { return };
|
||||
let Some(props) = obj.props.as_ref() else {
|
||||
return;
|
||||
};
|
||||
if props.get("node.name") == Some(sink_name_owned.as_str()) {
|
||||
if let Some(serial) = props
|
||||
.get("object.serial")
|
||||
.and_then(|s| s.parse::<u32>().ok())
|
||||
{
|
||||
state_for_reg.borrow_mut().sink_serial = Some(serial);
|
||||
tracing::info!(
|
||||
serial,
|
||||
"audio routing: pixelpass sink registered"
|
||||
);
|
||||
tracing::info!(serial, "audio routing: pixelpass sink registered");
|
||||
try_flush(&state_for_reg, &event_tx_for_reg);
|
||||
}
|
||||
return;
|
||||
@@ -430,7 +430,9 @@ fn run_router(
|
||||
if props.get("media.class") != Some("Stream/Output/Audio") {
|
||||
return;
|
||||
}
|
||||
let Some(app) = props.get("application.name") else { return };
|
||||
let Some(app) = props.get("application.name") else {
|
||||
return;
|
||||
};
|
||||
if !app.eq_ignore_ascii_case(&filter_lower) {
|
||||
return;
|
||||
}
|
||||
@@ -443,7 +445,9 @@ fn run_router(
|
||||
try_flush(&state_for_reg, &event_tx_for_reg);
|
||||
}
|
||||
ObjectType::Metadata => {
|
||||
let Some(props) = obj.props.as_ref() else { return };
|
||||
let Some(props) = obj.props.as_ref() else {
|
||||
return;
|
||||
};
|
||||
if props.get("metadata.name") != Some("default") {
|
||||
return;
|
||||
}
|
||||
|
||||
+34
-7
@@ -256,7 +256,9 @@ fn spawn_kick_listener(sup_tx: mpsc::Sender<SupervisorMsg>) {
|
||||
let Some(id) = line.trim().strip_prefix("kick ") else {
|
||||
continue;
|
||||
};
|
||||
let msg = SupervisorMsg::KickViewer { id: id.trim().to_string() };
|
||||
let msg = SupervisorMsg::KickViewer {
|
||||
id: id.trim().to_string(),
|
||||
};
|
||||
// blocking_send is valid here: this is a plain thread, not inside
|
||||
// the tokio runtime. An Err means the supervisor closed — stop.
|
||||
if sup_tx.blocking_send(msg).is_err() {
|
||||
@@ -315,7 +317,11 @@ async fn supervise(
|
||||
viewers.insert(id.clone(), cancel);
|
||||
let active = viewers.len() as u32;
|
||||
let _ = reply.send(Ok(port));
|
||||
output::emit(output::Event::ViewerJoined { id: &id, active, max: max_viewers });
|
||||
output::emit(output::Event::ViewerJoined {
|
||||
id: &id,
|
||||
active,
|
||||
max: max_viewers,
|
||||
});
|
||||
tracing::info!(active, cap = max_viewers, "viewer joined");
|
||||
}
|
||||
SupervisorMsg::RemoveViewer { id } => {
|
||||
@@ -325,7 +331,11 @@ async fn supervise(
|
||||
continue;
|
||||
}
|
||||
let active = viewers.len() as u32;
|
||||
output::emit(output::Event::ViewerLeft { id: &id, active, max: max_viewers });
|
||||
output::emit(output::Event::ViewerLeft {
|
||||
id: &id,
|
||||
active,
|
||||
max: max_viewers,
|
||||
});
|
||||
tracing::info!(active, cap = max_viewers, "viewer left");
|
||||
if active == 0
|
||||
&& let Some(h) = handle.take()
|
||||
@@ -372,10 +382,25 @@ fn print_host_banner(
|
||||
eprintln!("┌─ PixelPass · host ─────────────────────────────────────────");
|
||||
eprintln!("│ display server : {display:?}");
|
||||
eprintln!("│ capture : {}", capture_summary(opts));
|
||||
eprintln!("│ quality : {} — {}", quality.label, quality.dimensions_summary());
|
||||
eprintln!(
|
||||
"│ quality : {} — {}",
|
||||
quality.label,
|
||||
quality.dimensions_summary()
|
||||
);
|
||||
eprintln!("│ ({})", quality.note);
|
||||
eprintln!("│ hw encode : {}", if opts.no_hwencode { "off (software x264)" } else { "on (VAAPI H.264)" });
|
||||
eprintln!("│ max viewers : {} ({})", resolution.value, resolution.source.label());
|
||||
eprintln!(
|
||||
"│ hw encode : {}",
|
||||
if opts.no_hwencode {
|
||||
"off (software x264)"
|
||||
} else {
|
||||
"on (VAAPI H.264)"
|
||||
}
|
||||
);
|
||||
eprintln!(
|
||||
"│ max viewers : {} ({})",
|
||||
resolution.value,
|
||||
resolution.source.label()
|
||||
);
|
||||
eprintln!("│");
|
||||
if clipboard_ok {
|
||||
eprintln!("│ Your share code has been copied to your clipboard.");
|
||||
@@ -439,7 +464,9 @@ fn resolve_max_viewers(opts: &HostOpts, effective_bitrate: u32) -> MaxViewersRes
|
||||
let n = bandwidth::recommended_max_viewers(upstream, effective_bitrate);
|
||||
return MaxViewersResolution {
|
||||
value: n,
|
||||
source: MaxViewersSource::BandwidthMeasurement { safe_mbps: upstream },
|
||||
source: MaxViewersSource::BandwidthMeasurement {
|
||||
safe_mbps: upstream,
|
||||
},
|
||||
};
|
||||
}
|
||||
MaxViewersResolution {
|
||||
|
||||
@@ -308,7 +308,9 @@ async fn default_audio_monitor() -> Result<String> {
|
||||
.arg("get-default-sink")
|
||||
.output()
|
||||
.await
|
||||
.context("failed to run `pactl get-default-sink` (install pulseaudio-utils or pipewire-pulse)")?;
|
||||
.context(
|
||||
"failed to run `pactl get-default-sink` (install pulseaudio-utils or pipewire-pulse)",
|
||||
)?;
|
||||
if !output.status.success() {
|
||||
bail!(
|
||||
"pactl get-default-sink failed: {}",
|
||||
|
||||
+31
-7
@@ -27,10 +27,26 @@ impl Quality {
|
||||
/// values and resolves to one of the others at runtime (see [`resolve_auto`]).
|
||||
fn preset(self) -> Option<Preset> {
|
||||
let p = match self {
|
||||
Quality::Source => Preset { max_height: None, bitrate: 6000, framerate: 30 },
|
||||
Quality::High => Preset { max_height: Some(1080), bitrate: 4000, framerate: 30 },
|
||||
Quality::Medium => Preset { max_height: Some(720), bitrate: 2500, framerate: 30 },
|
||||
Quality::Low => Preset { max_height: Some(480), bitrate: 1000, framerate: 30 },
|
||||
Quality::Source => Preset {
|
||||
max_height: None,
|
||||
bitrate: 6000,
|
||||
framerate: 30,
|
||||
},
|
||||
Quality::High => Preset {
|
||||
max_height: Some(1080),
|
||||
bitrate: 4000,
|
||||
framerate: 30,
|
||||
},
|
||||
Quality::Medium => Preset {
|
||||
max_height: Some(720),
|
||||
bitrate: 2500,
|
||||
framerate: 30,
|
||||
},
|
||||
Quality::Low => Preset {
|
||||
max_height: Some(480),
|
||||
bitrate: 1000,
|
||||
framerate: 30,
|
||||
},
|
||||
Quality::Auto => return None,
|
||||
};
|
||||
Some(p)
|
||||
@@ -49,7 +65,12 @@ impl Quality {
|
||||
|
||||
/// Fixed presets in descending quality order — Auto walks this to find the
|
||||
/// best one whose per-viewer bitrate fits the measured upstream budget.
|
||||
const AUTO_LADDER: [Quality; 4] = [Quality::Source, Quality::High, Quality::Medium, Quality::Low];
|
||||
const AUTO_LADDER: [Quality; 4] = [
|
||||
Quality::Source,
|
||||
Quality::High,
|
||||
Quality::Medium,
|
||||
Quality::Low,
|
||||
];
|
||||
|
||||
/// Auto's fallback when there is no usable bandwidth measurement.
|
||||
const AUTO_FALLBACK: Quality = Quality::Medium;
|
||||
@@ -146,7 +167,9 @@ fn resolve_auto(safe_mbps: Option<f64>, sizing_viewers: u32) -> (Preset, String,
|
||||
(
|
||||
preset,
|
||||
format!("Auto → {}", chosen.name()),
|
||||
format!("auto: {safe_mbps:.1} Mbps safe ÷ {n} viewer(s) = {budget_mbps:.1} Mbps each"),
|
||||
format!(
|
||||
"auto: {safe_mbps:.1} Mbps safe ÷ {n} viewer(s) = {budget_mbps:.1} Mbps each"
|
||||
),
|
||||
)
|
||||
}
|
||||
None => {
|
||||
@@ -154,7 +177,8 @@ fn resolve_auto(safe_mbps: Option<f64>, sizing_viewers: u32) -> (Preset, String,
|
||||
(
|
||||
preset,
|
||||
format!("Auto → {}", AUTO_FALLBACK.name()),
|
||||
"auto fallback — no bandwidth measurement (run `pixelpass --reconfigure`)".to_string(),
|
||||
"auto fallback — no bandwidth measurement (run `pixelpass --reconfigure`)"
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+15
-5
@@ -26,7 +26,11 @@ pub async fn start(opts: &HostOpts, quality: &EffectiveQuality) -> Result<Captur
|
||||
.context("could not reach the xdg-desktop-portal ScreenCast interface")?;
|
||||
let session = proxy.create_session().await?;
|
||||
|
||||
let source = if opts.window { SourceType::Window } else { SourceType::Monitor };
|
||||
let source = if opts.window {
|
||||
SourceType::Window
|
||||
} else {
|
||||
SourceType::Monitor
|
||||
};
|
||||
proxy
|
||||
.select_sources(
|
||||
&session,
|
||||
@@ -70,10 +74,16 @@ pub async fn start(opts: &HostOpts, quality: &EffectiveQuality) -> Result<Captur
|
||||
"do-timestamp=true".to_string(),
|
||||
];
|
||||
|
||||
pipeline::spawn(opts, quality, Some((w as u32, h as u32)), source_args, move || {
|
||||
// Parent no longer needs the pipewire fd — gst inherited its own copy.
|
||||
let _ = close(raw_fd);
|
||||
})
|
||||
pipeline::spawn(
|
||||
opts,
|
||||
quality,
|
||||
Some((w as u32, h as u32)),
|
||||
source_args,
|
||||
move || {
|
||||
// Parent no longer needs the pipewire fd — gst inherited its own copy.
|
||||
let _ = close(raw_fd);
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user