mod cli;
use t_rec::core;
#[cfg(any(target_os = "linux", target_os = "netbsd"))]
use core::linux::*;
#[cfg(target_os = "macos")]
use core::macos::*;
#[cfg(target_os = "windows")]
use core::windows::*;
use crate::cli::utils::parse_delay;
use crate::cli::{
expand_home, handle_init_config, handle_list_profiles, init_logging, launch,
print_recording_summary, resolve_profiled_settings, CliArgs, OutputGenerator, ProfileSettings,
RecordingSession, SessionConfig,
};
use core::common::{Platform, PlatformApiFactory};
use core::generators::{check_for_gif, check_for_mp4};
use core::wallpapers::{resolve_wallpaper, Wallpaper};
use core::PlatformApi;
use anyhow::{bail, Context};
use image::DynamicImage;
use std::env;
use std::time::Duration;
pub use core::{Image, ImageOnHeap, Result, WindowId, WindowList, WindowListEntry};
fn main() -> Result<()> {
init_logging();
let args = launch();
if args.init_config {
return handle_init_config();
}
if args.list_profiles {
return handle_list_profiles();
}
let mut api = Platform::setup()?;
if args.list_windows {
return ls_win(&api);
}
let settings = resolve_profiled_settings(&args)?;
validate_prerequisites(&settings)?;
let program = args
.program
.clone()
.unwrap_or_else(|| env::var("SHELL").unwrap_or_else(|_| DEFAULT_SHELL.to_owned()));
let (win_id, window_name) = current_win_id(&api, &args)?;
api.calibrate(win_id)?;
let wallpaper_config = validate_wallpaper_config(&settings, &api, win_id)?;
let (start_delay, end_delay, idle_pause) = (
parse_delay(settings.start_pause.as_deref(), "start-pause")?,
parse_delay(settings.end_pause.as_deref(), "end-pause")?,
parse_delay(Some(settings.idle_pause()), "idle-pause")?,
);
let session_config = SessionConfig::builder()
.win_id(win_id)
.window_name(window_name)
.program(program)
.using_profile(&settings)
.idle_pause(idle_pause)
.start_delay(start_delay.unwrap_or(Duration::ZERO))
.end_delay(end_delay.unwrap_or(Duration::ZERO))
.wallpaper(wallpaper_config.clone())
.build();
let session = RecordingSession::new(
session_config,
Box::new(api),
cli::recorder::runtime::Runtime::new(),
)?;
let output_config = session.output_config();
let result = session.run()?;
print_recording_summary(&settings, result.frame_count);
OutputGenerator::new(result, output_config).process()?;
Ok(())
}
fn validate_prerequisites(settings: &ProfileSettings) -> Result<()> {
if !settings.video_only() {
check_for_gif()?;
}
if settings.video() || settings.video_only() {
check_for_mp4()?;
}
Ok(())
}
fn validate_wallpaper_config(
settings: &ProfileSettings,
api: &impl PlatformApi,
win_id: WindowId,
) -> Result<Option<(DynamicImage, u32)>> {
let wp_value = match &settings.wallpaper {
Some(v) => v,
None => return Ok(None),
};
let wp_value = expand_home(wp_value);
let wallpaper_type: Wallpaper = wp_value.parse().unwrap(); let padding = settings.wallpaper_padding();
let screenshot = api.capture_window_screenshot(win_id)?;
let terminal_width = screenshot.layout.width;
let terminal_height = screenshot.layout.height;
let wallpaper = resolve_wallpaper(&wallpaper_type, terminal_width, terminal_height, padding)?;
Ok(Some((wallpaper, padding)))
}
fn current_win_id(api: &impl PlatformApi, args: &CliArgs) -> Result<(WindowId, Option<String>)> {
match args.win_id.ok_or_else(|| env::var("WINDOWID")) {
Ok(win_id) => Ok((win_id, None)),
Err(_) => {
let terminal = env::var("TERM_PROGRAM").context(
"Env variable 'TERM_PROGRAM' was empty but is needed for figure out the WindowId. Please set it to e.g. TERM_PROGRAM=alacitty",
);
if let Ok(terminal) = terminal {
let (win_id, name) = get_window_id_for(api, terminal).context(
"Cannot determine the WindowId of this terminal. Please set env variable 'WINDOWID' and try again.",
)?;
Ok((win_id, Some(name)))
} else {
let win_id = api.get_active_window()?;
Ok((win_id, None))
}
}
}
}
pub fn get_window_id_for(api: &impl PlatformApi, terminal: String) -> Result<(WindowId, String)> {
for term in terminal.to_lowercase().split('.') {
for (window_owner, window_id) in api.window_list()? {
if let Some(window_owner) = window_owner {
let window = &window_owner.to_lowercase();
let terminal = &terminal.to_lowercase();
if window.contains(term) || terminal.contains(window) {
return Ok((window_id, terminal.to_owned()));
}
}
}
}
bail!("Cannot determine the window id from the available window list.")
}
pub fn ls_win(api: &impl PlatformApi) -> Result<()> {
let mut list = api.window_list()?;
list.sort();
println!("Window | Id");
for (window_owner, window_id) in list.iter() {
if let (Some(window_owner), window_id) = (window_owner, window_id) {
println!("{} | {}", window_owner, window_id)
}
}
Ok(())
}