Adding black borders
This commit is contained in:
parent
0827583370
commit
da4dcf9968
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -1,5 +1,18 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
|
@ -73,11 +86,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
name = "wlstreamer"
|
name = "wlstreamer"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.117 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.117 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.59 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.59 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
|
"checksum either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
|
||||||
"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
|
"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
|
||||||
"checksum proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
"checksum proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||||
"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
||||||
|
|
|
@ -7,3 +7,4 @@ edition = "2018"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1.0", features = ["derive"]}
|
serde = { version = "1.0", features = ["derive"]}
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
itertools = "0.9"
|
||||||
|
|
369
src/main.rs
369
src/main.rs
|
@ -1,66 +1,218 @@
|
||||||
|
use itertools::Itertools;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::{BufRead, BufReader, Error};
|
use std::io::{BufRead, BufReader, Error};
|
||||||
use std::process::{Child, Command, Stdio};
|
use std::process::{Child, Command, Stdio};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
struct SwayScreenRect {
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
struct SwayWorkspace {
|
struct SwayWorkspace {
|
||||||
id: u32,
|
id: usize,
|
||||||
name: String,
|
name: String,
|
||||||
focus: Vec<u32>,
|
focus: Vec<usize>,
|
||||||
output: String,
|
output: String,
|
||||||
focused: bool,
|
focused: bool,
|
||||||
|
rect: SwayScreenRect,
|
||||||
visible: bool,
|
visible: bool,
|
||||||
num: u32,
|
num: usize,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
type_name: String,
|
type_name: String,
|
||||||
representation: String,
|
representation: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
struct SwayOutputMode {
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
refresh: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
struct SwayOutput {
|
||||||
|
id: usize,
|
||||||
|
name: String,
|
||||||
|
rect: SwayScreenRect,
|
||||||
|
layout: String,
|
||||||
|
orientation: String,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
type_name: String,
|
||||||
|
make: String,
|
||||||
|
model: String,
|
||||||
|
serial: String,
|
||||||
|
current_mode: SwayOutputMode,
|
||||||
|
focused: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Hash, Eq, Debug)]
|
||||||
|
struct Resolution {
|
||||||
|
height: usize,
|
||||||
|
width: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct Config {
|
struct Config {
|
||||||
current_screen: String,
|
current_output: String,
|
||||||
output: String,
|
devices_from: usize,
|
||||||
|
current_device_index: usize,
|
||||||
screen_blacklist: Vec<String>,
|
screen_blacklist: Vec<String>,
|
||||||
workspace_blacklist: Vec<u32>,
|
workspace_blacklist: Vec<usize>,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
|
resolutions: Vec<Resolution>,
|
||||||
|
outputs: HashMap<Resolution, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<Resolution> for Resolution {
|
||||||
|
fn eq(&self, other: &Resolution) -> bool {
|
||||||
|
self.width == other.width && self.height == other.height
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
fn help() {
|
fn help() {
|
||||||
println!("Wrapper around wf-recorder and ffmpeg that automatically switches the screen being recorded based on current window focus");
|
|
||||||
println!("");
|
|
||||||
println!("Usage: wlstreamer [options]");
|
println!("Usage: wlstreamer [options]");
|
||||||
|
println!("Wrapper around wf-recorder and ffmpeg that automatically switches the screen being recorded based on current window focus");
|
||||||
println!("");
|
println!("");
|
||||||
println!("Options:");
|
println!("Options:");
|
||||||
println!(" --not-ws <ws-num> Do not show this workspace. Can be used multiple times. Example: 3");
|
println!(" --not-ws <ws-num> Do not show this workspace. Can be used multiple times. Example: 3");
|
||||||
println!(" --not-screen <screen> Do not show this screen. Can be used multiple times. Example: HDMI-A-1");
|
println!(" --not-screen <screen> Do not show this screen. Can be used multiple times. Example: HDMI-A-1");
|
||||||
println!(" -o|--output <output> Output to this device. Defaults to /dev/video0");
|
println!(" -d|--devices-from <id> Use video devices starting at $id. Defaults to 0. /dev/video$id will be used as output. See DIFFERENT RESOLUTIONS below.");
|
||||||
println!(" -v|--version Display version and exit");
|
println!(" -v|--version Display version and exit");
|
||||||
println!(" --verbose Verbose logging");
|
println!(" --verbose Verbose logging");
|
||||||
println!("");
|
println!("");
|
||||||
println!(
|
println!(
|
||||||
"If there are no screens available for streaming, a black screen will be shown instead."
|
"If there are no screens available for streaming, a black screen will be shown instead."
|
||||||
);
|
);
|
||||||
|
println!("");
|
||||||
|
println!("DIFFERENT RESOLUTIONS");
|
||||||
|
println!("");
|
||||||
|
println!("When running outputs with different resolutions, the resulting stream will be the smallest possible resolution that can fit all output resolutions.");
|
||||||
|
println!("For example, two outputs, one 1600x1200, another 1920x1080, will result in an output stream of 1920x1200. Any remaining space will be padded black.");
|
||||||
|
println!("Another example, two outputs, one 640x480, another 1920x1080, will result in an output stream of 1920x1080. Space will only be padded black on the smaller screen.");
|
||||||
|
println!("");
|
||||||
|
println!("To support this behaviour, wlstreamer needs access to a v4l2loopback device for each resolution, included the combined upscaled one if applicable.");
|
||||||
|
println!("For the first example above, this would mean you would need 3 devices. For the second, you'd need two. If all your outputs have the same resolution, you only need an output device.");
|
||||||
|
println!("");
|
||||||
|
println!("DYNAMICALLY CHANGING RESOLUTIONS");
|
||||||
|
println!("");
|
||||||
|
println!("As long as you have enough v4l2loopback devices available for new resolutions, it should be fine to change resolutions on an output.");
|
||||||
|
println!("However, if your resolution is either wider or taller than the output resolution, this will result in failures, since dynamically changing the v4l2loopback device resolution is not possible.");
|
||||||
|
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn record_screen(config: &mut Config, valid_screens: &Vec<String>) -> Result<Child, Error> {
|
fn stream_black(config: &mut Config) -> Result<Vec<Child>, Error> {
|
||||||
if valid_screens.len() == 0 {
|
let mut cmd = Command::new("ffmpeg")
|
||||||
let cmd = Command::new("ffmpeg")
|
.args(&[
|
||||||
|
"-i",
|
||||||
|
format!(
|
||||||
|
"color=c=black:s={}x{}:r=25/1",
|
||||||
|
config.resolutions[0].width, config.resolutions[0].height
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
"-vcodec",
|
||||||
|
"rawvideo",
|
||||||
|
"-pix_fmt",
|
||||||
|
"yuyv422",
|
||||||
|
"-f",
|
||||||
|
"v4l2",
|
||||||
|
format!("/dev/video{}", config.devices_from).as_str(),
|
||||||
|
])
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.stdout(if config.verbose {
|
||||||
|
Stdio::piped()
|
||||||
|
} else {
|
||||||
|
Stdio::inherit()
|
||||||
|
})
|
||||||
|
.stderr(if config.verbose {
|
||||||
|
Stdio::piped()
|
||||||
|
} else {
|
||||||
|
Stdio::inherit()
|
||||||
|
})
|
||||||
|
.spawn()?;
|
||||||
|
|
||||||
|
config.current_output = "".to_string();
|
||||||
|
|
||||||
|
return Ok(vec![cmd]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn record_screen(config: &mut Config, output: SwayOutput) -> Result<Vec<Child>, Error> {
|
||||||
|
let resolution = Resolution {
|
||||||
|
height: output.current_mode.height,
|
||||||
|
width: output.current_mode.width,
|
||||||
|
};
|
||||||
|
|
||||||
|
let device_number = match config.outputs.get(&resolution) {
|
||||||
|
Some(device_number) => *device_number,
|
||||||
|
None => {
|
||||||
|
config
|
||||||
|
.outputs
|
||||||
|
.insert(resolution, config.current_device_index);
|
||||||
|
config.current_device_index += 1;
|
||||||
|
config.current_device_index
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if config.verbose {
|
||||||
|
println!("Using device number {}", device_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
let output_str = format!("--file=/dev/video{}", device_number);
|
||||||
|
let screen_str = format!("-o{}", output.name.as_str());
|
||||||
|
let recorder = Command::new("wf-recorder")
|
||||||
|
.args(&[
|
||||||
|
"--muxer=v4l2",
|
||||||
|
"--codec=rawvideo",
|
||||||
|
"--pixel-format=yuyv422",
|
||||||
|
screen_str.as_str(),
|
||||||
|
output_str.as_str(),
|
||||||
|
])
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.stdout(if config.verbose {
|
||||||
|
Stdio::inherit()
|
||||||
|
} else {
|
||||||
|
Stdio::piped()
|
||||||
|
})
|
||||||
|
.stderr(if config.verbose {
|
||||||
|
Stdio::inherit()
|
||||||
|
} else {
|
||||||
|
Stdio::piped()
|
||||||
|
})
|
||||||
|
.spawn()?;
|
||||||
|
|
||||||
|
config.current_output = output.name.as_str().to_string();
|
||||||
|
|
||||||
|
let mut processes = vec![recorder];
|
||||||
|
|
||||||
|
if device_number != config.devices_from {
|
||||||
|
if config.verbose {
|
||||||
|
println!("Does not have the maximum combined resolution, filtering through ffmpeg");
|
||||||
|
}
|
||||||
|
|
||||||
|
let upscaler = Command::new("ffmpeg")
|
||||||
.args(&[
|
.args(&[
|
||||||
"-f",
|
|
||||||
"lavfi",
|
|
||||||
"-i",
|
"-i",
|
||||||
"color=c=black:s=1920x1080:r=25/1",
|
format!("/dev/video{}", device_number).as_str(),
|
||||||
"-vcodec",
|
"-vcodec",
|
||||||
"rawvideo",
|
"rawvideo",
|
||||||
"-pix_fmt",
|
"-pix_fmt",
|
||||||
"yuyv422",
|
"yuyv422",
|
||||||
"-f",
|
"-f",
|
||||||
"v4l2",
|
"v4l2",
|
||||||
config.output.as_str(),
|
"-vf",
|
||||||
|
format!("scale={}:{}:force_original_aspect_ratio=decrease,pad={}:{}:(ow-iw)/2:(oh-ih)/2,setsar=1",
|
||||||
|
config.resolutions[0].width, config.resolutions[0].height,
|
||||||
|
config.resolutions[0].width, config.resolutions[0].height).as_str(),
|
||||||
|
format!("/dev/video{}", config.devices_from).as_str(),
|
||||||
])
|
])
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(if config.verbose {
|
.stdout(if config.verbose {
|
||||||
|
@ -75,46 +227,94 @@ fn record_screen(config: &mut Config, valid_screens: &Vec<String>) -> Result<Chi
|
||||||
})
|
})
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
|
|
||||||
config.current_screen = "".to_string();
|
processes.push(upscaler);
|
||||||
|
}
|
||||||
|
format!("/dev/video{}", device_number).as_str();
|
||||||
|
|
||||||
return Ok(cmd);
|
return Ok(processes);
|
||||||
} else {
|
|
||||||
let output_str = format!("--file={}", config.output.as_str());
|
|
||||||
let screen_str = format!("-o{}", valid_screens[0]);
|
|
||||||
println!("Outputting to {}", config.output.as_str());
|
|
||||||
let cmd = Command::new("wf-recorder")
|
|
||||||
.args(&[
|
|
||||||
"--muxer=v4l2",
|
|
||||||
"--codec=rawvideo",
|
|
||||||
"--pixel-format=yuyv422",
|
|
||||||
screen_str.as_str(),
|
|
||||||
output_str.as_str(),
|
|
||||||
])
|
|
||||||
.stdin(Stdio::piped())
|
|
||||||
.stdout(if config.verbose {
|
|
||||||
Stdio::inherit()
|
|
||||||
} else {
|
|
||||||
Stdio::piped()
|
|
||||||
})
|
|
||||||
.stderr(if config.verbose {
|
|
||||||
Stdio::inherit()
|
|
||||||
} else {
|
|
||||||
Stdio::piped()
|
|
||||||
})
|
|
||||||
.spawn()?;
|
|
||||||
|
|
||||||
config.current_screen = valid_screens[0].as_str().to_string();
|
|
||||||
|
|
||||||
return Ok(cmd);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_valid_screens_for_recording(config: &Config) -> Vec<String> {
|
fn get_outputs(config: &mut Config) -> Vec<SwayOutput> {
|
||||||
let mut command = "swaymsg -t get_workspaces";
|
let command = "swaymsg -t get_outputs";
|
||||||
let output = Command::new("sh")
|
let output = Command::new("sh")
|
||||||
.args(&["-c", command])
|
.args(&["-c", command])
|
||||||
.output()
|
.output()
|
||||||
.expect("Couldn't get current focus");
|
.expect("Error running swaymsg");
|
||||||
|
|
||||||
|
let stdout_string = String::from_utf8(output.stdout).expect("Invalid UTF-8 from get_outputs");
|
||||||
|
let outputs: Vec<SwayOutput> =
|
||||||
|
serde_json::from_str(stdout_string.as_str()).expect("Invalid json from get_outputs");
|
||||||
|
|
||||||
|
if config.verbose {
|
||||||
|
println!("Found outputs");
|
||||||
|
for elem in outputs.iter() {
|
||||||
|
println!("{:?}", elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_output(config: &mut Config, screen: &str) -> SwayOutput {
|
||||||
|
let outputs = get_outputs(config);
|
||||||
|
let output = match outputs.iter().find(|o| o.name == screen) {
|
||||||
|
Some(o) => o.to_owned(),
|
||||||
|
None => panic!("Could not find output"),
|
||||||
|
};
|
||||||
|
|
||||||
|
return output.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_resolutions(config: &mut Config) -> Vec<Resolution> {
|
||||||
|
let outputs = get_outputs(config);
|
||||||
|
let mut resolutions: Vec<Resolution> = outputs
|
||||||
|
.iter()
|
||||||
|
.map(|o| Resolution {
|
||||||
|
height: o.current_mode.height,
|
||||||
|
width: o.current_mode.width,
|
||||||
|
})
|
||||||
|
.unique()
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
if config.verbose {
|
||||||
|
println!("{:?}", resolutions);
|
||||||
|
}
|
||||||
|
|
||||||
|
let combined_resolution: Resolution = resolutions.iter().fold(
|
||||||
|
Resolution {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
},
|
||||||
|
|acc, r| Resolution {
|
||||||
|
height: if acc.height > r.height {
|
||||||
|
acc.height
|
||||||
|
} else {
|
||||||
|
r.height
|
||||||
|
},
|
||||||
|
width: if acc.width > r.width {
|
||||||
|
acc.width
|
||||||
|
} else {
|
||||||
|
r.width
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if config.verbose {
|
||||||
|
println!("Combined maximum resolution {:?}", combined_resolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolutions.insert(0, combined_resolution);
|
||||||
|
resolutions = resolutions.into_iter().unique().collect_vec();
|
||||||
|
|
||||||
|
return resolutions;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_valid_screens_for_recording(config: &Config) -> Vec<SwayWorkspace> {
|
||||||
|
let command = "swaymsg -t get_workspaces";
|
||||||
|
let output = Command::new("sh")
|
||||||
|
.args(&["-c", command])
|
||||||
|
.output()
|
||||||
|
.expect("Error running swaymsg");
|
||||||
|
|
||||||
let stdout_string =
|
let stdout_string =
|
||||||
String::from_utf8(output.stdout).expect("Invalid UTF-8 from get_workspaces");
|
String::from_utf8(output.stdout).expect("Invalid UTF-8 from get_workspaces");
|
||||||
|
@ -156,16 +356,20 @@ fn get_valid_screens_for_recording(config: &Config) -> Vec<String> {
|
||||||
Ordering::Greater
|
Ordering::Greater
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return workspaces.into_iter().map(|w| w.output).collect();
|
|
||||||
|
return workspaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut config = Config {
|
let mut config = Config {
|
||||||
current_screen: "".to_string(),
|
current_output: "".to_string(),
|
||||||
output: "/dev/video0".to_string(),
|
devices_from: 0,
|
||||||
|
current_device_index: 0,
|
||||||
screen_blacklist: Vec::new(),
|
screen_blacklist: Vec::new(),
|
||||||
workspace_blacklist: Vec::new(),
|
workspace_blacklist: Vec::new(),
|
||||||
verbose: false,
|
verbose: false,
|
||||||
|
resolutions: Vec::new(),
|
||||||
|
outputs: HashMap::new(),
|
||||||
};
|
};
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
|
|
||||||
|
@ -180,13 +384,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
i += 1;
|
i += 1;
|
||||||
config
|
config
|
||||||
.workspace_blacklist
|
.workspace_blacklist
|
||||||
.push(args[i].clone().parse::<u32>().unwrap());
|
.push(args[i].clone().parse::<usize>().unwrap());
|
||||||
} else if arg == "--not-screen" {
|
} else if arg == "--not-screen" {
|
||||||
i += 1;
|
i += 1;
|
||||||
config.screen_blacklist.push(args[i].clone());
|
config.screen_blacklist.push(args[i].clone());
|
||||||
} else if arg == "-o" || arg == "--output" {
|
} else if arg == "-d" || arg == "--devices-from" {
|
||||||
i += 1;
|
i += 1;
|
||||||
config.output = args[i].clone();
|
config.devices_from = args[i].clone().parse::<usize>().unwrap();
|
||||||
|
config.current_device_index = config.devices_from;
|
||||||
} else if arg == "--verbose" {
|
} else if arg == "--verbose" {
|
||||||
config.verbose = true;
|
config.verbose = true;
|
||||||
} else if arg == "-v" || arg == "--version" {
|
} else if arg == "-v" || arg == "--version" {
|
||||||
|
@ -201,8 +406,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let valid_screens = get_valid_screens_for_recording(&config);
|
config.resolutions = get_resolutions(&mut config);
|
||||||
let mut recorder = record_screen(&mut config, &valid_screens)?;
|
config
|
||||||
|
.outputs
|
||||||
|
.insert(config.resolutions[0], config.devices_from);
|
||||||
|
config.current_device_index += 1;
|
||||||
|
|
||||||
let stdout = match Command::new("sh")
|
let stdout = match Command::new("sh")
|
||||||
.args(&["-c", "swaymsg -t subscribe -m \"['window']\""])
|
.args(&["-c", "swaymsg -t subscribe -m \"['window']\""])
|
||||||
|
@ -213,28 +421,37 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.stdout
|
.stdout
|
||||||
{
|
{
|
||||||
Some(stdout) => stdout,
|
Some(stdout) => stdout,
|
||||||
None => panic!("Could not open stdout"),
|
None => panic!("Could not open swaymsg stdout"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let reader = BufReader::new(stdout);
|
let reader = BufReader::new(stdout);
|
||||||
reader.lines().filter_map(|line| line.ok()).for_each(|_| {
|
reader
|
||||||
println!("Switched focus");
|
.lines()
|
||||||
let valid_screens = get_valid_screens_for_recording(&config);
|
.filter_map(|line| line.ok())
|
||||||
if valid_screens.len() > 0 && valid_screens[0] == config.current_screen {
|
.for_each(|_| -> Result<(), Error> {
|
||||||
return;
|
println!("Switched focus");
|
||||||
}
|
let valid_screens = get_valid_screens_for_recording(&config);
|
||||||
|
if valid_screens.len() > 0 && valid_screens[0].output == config.current_output {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let output = get_output(&mut config, valid_screens[0].output.as_str());
|
||||||
|
for recorder in recorders.iter() {
|
||||||
|
match recorder.kill() {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(err) => panic!("{:?}", err),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
match recorder.kill() {
|
let mut recorders: Vec<Child> = if valid_screens.len() != 0 {
|
||||||
Ok(_) => {}
|
stream_black(&mut config)?
|
||||||
Err(err) => panic!("{:?}", err),
|
} else {
|
||||||
};
|
let output = get_output(&mut config, valid_screens[0].output.as_str());
|
||||||
|
record_screen(&mut config, output)?
|
||||||
|
};
|
||||||
|
println!("Recording {}", config.current_output);
|
||||||
|
|
||||||
recorder = match record_screen(&mut config, &valid_screens) {
|
Ok(())
|
||||||
Ok(recorder) => recorder,
|
});
|
||||||
Err(err) => panic!("{:?}", err),
|
|
||||||
};
|
|
||||||
println!("Recording {}", config.current_screen);
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue