can now show the logs of proton when running the game

This commit is contained in:
ALEZ-DEV 2024-08-24 21:23:36 +02:00
parent bda3226d44
commit 175d6c6a9b
4 changed files with 116 additions and 15 deletions

View File

@ -12,4 +12,8 @@ pub struct Args {
/// command one time to set your launch options to the configuration /// command one time to set your launch options to the configuration
#[arg(long)] #[arg(long)]
pub set_options: Option<String>, pub set_options: Option<String>,
/// Show the logs direcly to the stdout of your terminal
#[arg(long, default_value = "false")]
pub logs: bool,
} }

View File

@ -16,7 +16,7 @@ use wincompatlib::prelude::*;
use crate::{reporter::DownloadReporter, utils}; use crate::{reporter::DownloadReporter, utils};
pub async fn run(launch_options: Option<String>) { pub async fn run(launch_options: Option<String>, show_logs: bool) {
let mut proton_component: Option<ProtonComponent> = None; let mut proton_component: Option<ProtonComponent> = None;
let mut proton: Option<Proton> = None; let mut proton: Option<Proton> = None;
@ -170,6 +170,7 @@ pub async fn run(launch_options: Option<String>) {
.await .await
.expect("Failed to start game, the game directory was not found"), .expect("Failed to start game, the game directory was not found"),
launch_options, launch_options,
show_logs,
) )
.await; .await;
} }

View File

@ -35,5 +35,5 @@ async fn main() {
.expect("Failed to save launch options into the config file"); .expect("Failed to save launch options into the config file");
} }
game::run(args.options).await; game::run(args.options, args.logs).await;
} }

View File

@ -2,12 +2,15 @@ use std::{
io::{BufRead, BufReader}, io::{BufRead, BufReader},
path::PathBuf, path::PathBuf,
process::{Child, Command, Stdio}, process::{Child, Command, Stdio},
sync::Arc, sync::{Arc, Mutex},
}; };
use downloader::progress::Reporter; use downloader::progress::Reporter;
use log::{debug, info}; use log::{debug, info};
use tokio::fs::create_dir_all; use tokio::{
fs::{create_dir_all, remove_file, File, OpenOptions},
io::AsyncWriteExt,
};
use wincompatlib::prelude::*; use wincompatlib::prelude::*;
use crate::{ use crate::{
@ -169,7 +172,12 @@ impl GameManager {
Ok(()) Ok(())
} }
pub async fn start_game(proton: &Proton, game_dir: PathBuf, options: Option<String>) { pub async fn start_game(
proton: &Proton,
game_dir: PathBuf,
options: Option<String>,
show_logs: bool,
) {
let proton_version = proton.wine().version().unwrap(); let proton_version = proton.wine().version().unwrap();
let binary_path = game_dir let binary_path = game_dir
.join(get_game_name()) .join(get_game_name())
@ -192,18 +200,105 @@ impl GameManager {
} }
}; };
let stdout = child.stdout.take().unwrap(); let log_stdout = Arc::new(Mutex::new(None));
let mut bufread = BufReader::new(stdout); let log_stderr = Arc::new(Mutex::new(None));
let mut buf = String::new();
while let Ok(n) = bufread.read_line(&mut buf) { if show_logs {
if n > 0 { let stderr = child.stderr.take().unwrap();
info!("[Wine {:?}] : {}", proton_version, buf.trim()); let stdout = child.stdout.take().unwrap();
buf.clear();
} else { let log_stdout_ref = log_stdout.clone();
break; let log_stderr_ref = log_stderr.clone();
}
tokio::task::spawn(async move {
let bufread = BufReader::new(stdout);
let mut stdout_save = String::new();
let _: Vec<_> = bufread
.lines()
.inspect(|s| {
if let Ok(str) = s {
info!("[Proton] > {}", str);
stdout_save.push_str(str);
}
})
.collect();
*log_stdout_ref.lock().unwrap() = Some(stdout_save);
});
tokio::task::spawn(async move {
let bufread = BufReader::new(stderr);
let mut stderr_save = String::new();
let _: Vec<_> = bufread
.lines()
.inspect(|s| {
if let Ok(str) = s {
info!("[Proton] > {}", str);
stderr_save.push_str(str);
}
})
.collect();
*log_stderr_ref.lock().unwrap() = Some(stderr_save);
});
} }
let output = child
.wait_with_output()
.expect("Failed to wait for the process");
let log_file_path = GameConfig::get_config_directory().await.join("game.log");
if log_file_path.exists() {
remove_file(log_file_path.clone())
.await
.expect("Failed to remove old log file");
}
File::create(log_file_path.clone())
.await
.expect("Failed to create build file");
let mut log_file = OpenOptions::new()
.write(true)
.append(true)
.open(log_file_path)
.await
.expect("Failed to open the log file");
log_file
.write_all("--- stdout ---\n".as_bytes())
.await
.expect("Failed to write the output to the log file");
let log_stdout_value = log_stdout.lock().unwrap();
let v;
let to_write = if log_stdout_value.is_some() {
v = log_stdout_value.clone().unwrap();
v.as_bytes()
} else {
&output.stdout
};
log_file
.write_all(to_write)
.await
.expect("Failed to write the output to the log file");
log_file
.write_all("--- stderr ---\n".as_bytes())
.await
.expect("Failed to write the output to the log file");
let log_stderr_value = log_stderr.lock().unwrap();
let v;
let to_write = if log_stderr_value.is_some() {
debug!("test");
v = log_stderr_value.clone().unwrap();
v.as_bytes()
} else {
&output.stderr
};
log_file
.write_all(to_write)
.await
.expect("Failed to write the output to the log file");
} }
async fn run( async fn run(
@ -233,6 +328,7 @@ impl GameManager {
.arg(binary_path) .arg(binary_path)
.args(&tokens[(index + 1)..tokens.len()]) .args(&tokens[(index + 1)..tokens.len()])
.envs(proton.get_envs()) .envs(proton.get_envs())
.env("PROTON_LOG", "1")
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())