black screen dead once and for all. now its just loss of input for a bit on first load

This commit is contained in:
RabbyDevs 2025-05-09 21:38:03 +03:00
parent 4c87d13eb8
commit 2e3c44b421
7 changed files with 107 additions and 115 deletions

19
Cargo.lock generated
View file

@ -816,12 +816,6 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "file-format"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ef3d5e8ae27277c8285ac43ed153158178ef0f79567f32024ca8140a0c7cd8"
[[package]]
name = "flate2"
version = "1.1.1"
@ -1627,13 +1621,11 @@ dependencies = [
"glib",
"gstreamer",
"gstreamer-app",
"gstreamer-base",
"iced",
"iced_wgpu",
"log",
"thiserror 2.0.12",
"url",
"yuvutils-rs",
]
[[package]]
@ -3102,7 +3094,6 @@ name = "reversed-rooms-launcher"
version = "0.5.0"
dependencies = [
"directories",
"file-format",
"iced",
"iced_video_player",
"image",
@ -3111,7 +3102,6 @@ dependencies = [
"serde_json",
"strum 0.27.1",
"strum_macros 0.27.1",
"tempfile",
"url",
]
@ -5051,15 +5041,6 @@ dependencies = [
"synstructure",
]
[[package]]
name = "yuvutils-rs"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b699b6503cd14c70b258eaffedd7ada5a781ea23206eeb9066736b99ba37af1"
dependencies = [
"num-traits",
]
[[package]]
name = "zeno"
version = "0.3.2"

View file

@ -10,10 +10,8 @@ iced = { git = "https://github.com/RabbyDevs/iced.git", features = ["tokio", "wg
image = "0.25.6"
serde = { version = "1.0.219", features = ["serde_derive"] }
serde_json = "1.0.140"
tempfile = "3.19.1"
iced_video_player = {path = "./iced_video_player"}
url = "2.5.4"
file-format = "0.26.0"
strum = "0.27.1"
strum_macros = "0.27.1"
reqwest = { version = "0.12.15", features = [

View file

@ -20,12 +20,12 @@ iced = { git = "https://github.com/RabbyDevs/iced.git", features = ["wgpu", "ima
iced_wgpu = { git = "https://github.com/RabbyDevs/iced.git" }
gstreamer = "0.23.5"
gstreamer-app = "0.23.5" # appsink
gstreamer-base = "0.23.5" # basesrc
# gstreamer-base = "0.23.5" # basesrc
glib = "0.20.9" # gobject traits and error type
log = "0.4.27"
thiserror = "2.0.12"
url = "2.5.4" # media uri
yuvutils-rs = "0.8.2"
# yuvutils-rs = "0.8.2"
[package.metadata.nix]
systems = ["x86_64-linux"]

View file

@ -336,7 +336,7 @@ impl Video {
frame,
upload_frame,
looping: false,
looping: true,
is_eos: false,
restart_stream: false,
})))

View file

@ -156,6 +156,7 @@ async fn refresh_kuro_install(proj_dirs: &ProjectDirs, client: &Client) -> Resul
update_file_if_needed(data_dir, client, &bg_information.background_file, "background").await?;
update_file_if_needed(data_dir, client, &bg_information.slogan, "splash").await?;
update_file_if_needed(data_dir, client, &bg_information.first_frame_image, "first_frame_image").await?;
Ok(())
}

View file

@ -96,9 +96,15 @@ enum Launcher {
Loaded(Box<State>),
}
#[derive(Debug)]
struct VideoBackground {
video: Option<Video>,
first_frame: DynamicImage
}
#[derive(Debug)]
enum LauncherBackground {
Video(Video),
Video(VideoBackground),
Image(DynamicImage),
}
@ -117,8 +123,14 @@ impl State {
fn get_background_element(&self) -> Option<Element<Message>> {
if let Some(background) = &self.background {
match background {
LauncherBackground::Video(video) => Some(VideoPlayer::new(video).into()),
LauncherBackground::Image(img) => Some(image(image::Handle::from_rgba(img.width(), img.height(), img.to_rgba8().into_raw())).into()),
LauncherBackground::Video(video_object) => {
if let Some(video) = &video_object.video {
Some(VideoPlayer::new(video).into())
} else {
Some(image(video_object.first_frame.clone().into_handle()).into())
}
},
LauncherBackground::Image(img) => Some(image(img.clone().into_handle()).into()),
}
} else {
None
@ -252,6 +264,7 @@ enum Message {
LoadIcons(HashMap<PossibleGames, DynamicImage>),
LoadSplashes(HashMap<PossibleGames, DynamicImage>),
LoadBackground(()),
LoadVideo(()),
RefreshInstall(Result<(), String>),
GameSelected(PossibleGames),
Close,
@ -328,12 +341,33 @@ impl Launcher {
Task::none()
},
Message::LoadBackground(()) => {
state.background = Some(get_game_background(&state.selected_game));
let (width, height) = state.selected_game.get_game_preferred_size();
window::get_latest().and_then(move |id: window::Id| {
let task = window::get_latest().and_then(move |id: window::Id| {
window::resize(id, Size { width: width as f32, height: height as f32 })
})
});
if let Ok(background) = get_game_background(&state.selected_game, false) {
if let LauncherBackground::Video(_) = background {
state.background = Some(background);
return task.chain(Task::perform(empty(), Message::LoadVideo));
}
state.background = Some(background);
} else {
state.background = None
}
task
},
Message::LoadVideo(()) => {
if let Ok(background) = get_game_background(&state.selected_game, true) {
state.background = Some(background);
} else {
state.background = None
}
Task::none()
},
Message::LoadIcons(icons) => {
state.icon_images = icons;
@ -344,12 +378,22 @@ impl Launcher {
},
Message::GameSelected(game) => {
state.selected_game = game;
state.background = Some(get_game_background(&state.selected_game));
let (width, height) = state.selected_game.get_game_preferred_size();
window::get_latest().and_then(move |id: window::Id| {
let task = window::get_latest().and_then(move |id: window::Id| {
window::resize(id, Size { width: width as f32, height: height as f32 })
})
});
if let Ok(background) = get_game_background(&state.selected_game, false) {
if let LauncherBackground::Video(_) = background {
state.background = Some(background);
return task.chain(Task::perform(empty(), Message::LoadVideo));
}
state.background = Some(background)
} else {
state.background = None
}
task
},
}
}

View file

@ -1,47 +1,60 @@
use std::{fs::DirEntry, io::{Cursor, Write}, sync::Arc};
use std::{io::Cursor, path::PathBuf};
use directories::ProjectDirs;
use file_format::FileFormat;
use iced_video_player::Video;
use ::image::{DynamicImage, ImageReader};
use iced::{gradient, widget::container, Color};
use tempfile::NamedTempFile;
use crate::{LauncherBackground, PossibleGames};
use crate::{LauncherBackground, PossibleGames, VideoBackground};
use super::img_utils::round_image;
pub fn get_game_background(game: &PossibleGames) -> LauncherBackground {
pub fn get_game_background(game: &PossibleGames, make_video: bool) -> Result<LauncherBackground, std::io::Error> {
let proj_dirs = ProjectDirs::from("com", "RabbyDevs", "rr-launcher").unwrap();
let background_bytes = get_background_file(&proj_dirs, game).unwrap();
let data = Arc::new(background_bytes);
let file_format = FileFormat::from_bytes(&*data);
let background_path = get_asset_file(&proj_dirs, game, "background")?;
if file_format.extension() == "mp4" {
let mut temp_file = NamedTempFile::new().unwrap();
temp_file.write_all(&data).unwrap();
let temp_path = temp_file.path().to_str().unwrap().to_string();
match Video::new(&url::Url::from_file_path(temp_path).unwrap()) {
Ok(mut video) => {
video.set_looping(true);
LauncherBackground::Video(video)
},
Err(err) => {
panic!("{:#?}", err)
},
}
} else {
let img = ImageReader::new(Cursor::new(&*data))
if background_path.extension().unwrap().to_str().unwrap() == "mp4" {
let first_frame_path = get_asset_file(&proj_dirs, game, "first_frame_image")?;
let first_frame = ImageReader::new(Cursor::new(std::fs::read(first_frame_path)?))
.with_guessed_format()
.unwrap()
.decode()
.unwrap();
LauncherBackground::Image(img)
if !make_video {
return Ok(LauncherBackground::Video(VideoBackground {
first_frame,
video: None
}));
}
match Video::new(&url::Url::from_file_path(background_path).unwrap()) {
Ok(video) => {
let video_object = VideoBackground {
first_frame,
video: Some(video)
};
Ok(LauncherBackground::Video(video_object))
},
Err(err) => {
eprintln!("{:#?}", err);
Ok(LauncherBackground::Video(VideoBackground {
first_frame,
video: None
}))
},
}
} else {
let img = ImageReader::new(Cursor::new(std::fs::read(background_path)?))
.with_guessed_format()
.unwrap()
.decode()
.unwrap();
Ok(LauncherBackground::Image(img))
}
}
fn get_background_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Result<Vec<u8>, std::io::Error> {
fn get_asset_file(proj_dirs: &ProjectDirs, game: &PossibleGames, identifier: &str) -> Result<PathBuf, std::io::Error> {
let game_dir = match game {
PossibleGames::WutheringWaves => proj_dirs.data_dir().join("kuro/wuwa"),
PossibleGames::ZenlessZoneZero => proj_dirs.data_dir().join("hoyoverse/zzz"),
@ -62,8 +75,8 @@ fn get_background_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Result<
let entry = entry?;
let file_name = entry.file_name().into_string().unwrap_or_default();
if file_name.starts_with("background_") {
return std::fs::read(entry.path());
if file_name.starts_with(format!("{}_", identifier).as_str()) {
return Ok(entry.path());
}
}
@ -75,9 +88,10 @@ fn get_background_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Result<
pub fn get_game_splash_dynamic_image(game: &PossibleGames) -> Option<DynamicImage> {
let proj_dirs = ProjectDirs::from("com", "RabbyDevs", "rr-launcher").unwrap();
let file_data = get_splash_file(&proj_dirs, game);
if let Some(data) = file_data {
let data_cursor = Cursor::new(data);
let file_path = get_asset_file(&proj_dirs, game, "splash");
if let Ok(path) = file_path {
let data_cursor = Cursor::new(std::fs::read(path).unwrap());
Some(ImageReader::new(data_cursor)
.with_guessed_format()
@ -91,9 +105,9 @@ pub fn get_game_icon_dynamic_image(game: &PossibleGames) -> DynamicImage {
let proj_dirs = ProjectDirs::from("com", "RabbyDevs", "rr-launcher").unwrap();
let file_data: &[u8] = match game {
PossibleGames::WutheringWaves => include_bytes!("../../resources/wutheringwaves-icon.png"),
PossibleGames::ZenlessZoneZero => &get_hoyo_game_icon_file(&proj_dirs, game),
PossibleGames::HonkaiStarRail => &get_hoyo_game_icon_file(&proj_dirs, game),
PossibleGames::GenshinImpact => &get_hoyo_game_icon_file(&proj_dirs, game),
PossibleGames::ZenlessZoneZero => &std::fs::read(get_asset_file(&proj_dirs, game, "icon").unwrap()).unwrap(),
PossibleGames::HonkaiStarRail => &std::fs::read(get_asset_file(&proj_dirs, game, "icon").unwrap()).unwrap(),
PossibleGames::GenshinImpact => &std::fs::read(get_asset_file(&proj_dirs, game, "icon").unwrap()).unwrap(),
};
let data_cursor = Cursor::new(file_data);
@ -109,52 +123,6 @@ pub fn get_game_icon_dynamic_image(game: &PossibleGames) -> DynamicImage {
.unwrap()
}
fn get_hoyo_game_icon_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Vec<u8> {
let game_abbrevation = match game {
PossibleGames::ZenlessZoneZero => "zzz",
PossibleGames::HonkaiStarRail => "hsr",
PossibleGames::GenshinImpact => "gi",
_ => panic!("Wuwa inputted in hoyo only func")
};
let data_dir = proj_dirs.data_dir().join(format!("hoyoverse/{}", game_abbrevation));
let icon: Option<DirEntry> = {
let mut icon = None;
for path in data_dir.read_dir().unwrap() {
let path = path.unwrap();
if path.file_name().into_string().unwrap().starts_with("icon_") {
icon = Some(path);
}
}
icon
};
std::fs::read(icon.expect("installation went wrong.").path()).unwrap()
}
fn get_splash_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Option<Vec<u8>> {
let game_path = match game {
PossibleGames::ZenlessZoneZero => "hoyoverse/zzz",
PossibleGames::HonkaiStarRail => "hoyoverse/hsr",
PossibleGames::GenshinImpact => "hoyoverse/gi",
PossibleGames::WutheringWaves => "kuro/wuwa"
};
let data_dir = proj_dirs.data_dir().join(game_path);
let icon: Option<DirEntry> = {
let mut icon = None;
for path in data_dir.read_dir().unwrap() {
let path = path.unwrap();
if path.file_name().into_string().unwrap().starts_with("splash_") {
icon = Some(path);
}
}
icon
};
icon.map(|icon| std::fs::read(icon.path()).unwrap())
}
fn rad(deg: f32) -> f32 {
deg * std::f32::consts::PI / 180.0
}