mirror of
https://github.com/G2-Games/lbee-utils.git
synced 2025-04-18 23:02:56 -05:00
Added rather unfortunate audio playback to pak explorer
This commit is contained in:
parent
1ffc88d379
commit
982f55fde6
4 changed files with 106 additions and 18 deletions
|
@ -67,6 +67,17 @@ impl Entry {
|
|||
&self.data
|
||||
}
|
||||
|
||||
/// Get the byte data of an entry, but fixed to be compatible with normal things
|
||||
pub fn cloned_bytes_fixed(&self) -> Vec<u8> {
|
||||
match self.file_type() {
|
||||
EntryType::OGGPAK => {
|
||||
dbg!(self.data[15]);
|
||||
self.data[15..].to_vec()
|
||||
},
|
||||
_ => self.data.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_name(&self) -> String {
|
||||
let mut name = self.name().clone().unwrap_or(self.id().to_string());
|
||||
let entry_type = self.file_type();
|
||||
|
@ -88,6 +99,12 @@ impl Entry {
|
|||
}
|
||||
} else if self.data[0..3] == [b'M', b'V', b'T'] {
|
||||
EntryType::MVT
|
||||
} else if self.data[0..4] == [b'R', b'I', b'F', b'F'] {
|
||||
EntryType::WAV
|
||||
} else if self.data[0..4] == [b'O', b'g', b'g', b'S'] {
|
||||
EntryType::OGG
|
||||
} else if self.data[0..6] == [b'O', b'G', b'G', b'P', b'A', b'K'] {
|
||||
EntryType::OGGPAK
|
||||
} else {
|
||||
EntryType::Unknown
|
||||
}
|
||||
|
@ -96,6 +113,7 @@ impl Entry {
|
|||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum EntryType {
|
||||
// CZ image files
|
||||
CZ0,
|
||||
CZ1,
|
||||
CZ2,
|
||||
|
@ -106,6 +124,14 @@ pub enum EntryType {
|
|||
/// An MVT video file
|
||||
MVT,
|
||||
|
||||
/// OGG Audio file
|
||||
OGG,
|
||||
/// OGGPAK Audio file
|
||||
OGGPAK,
|
||||
|
||||
/// Wav Audio file
|
||||
WAV,
|
||||
|
||||
/// Who knows!
|
||||
Unknown,
|
||||
}
|
||||
|
@ -121,6 +147,9 @@ impl EntryType {
|
|||
Self::CZ4 => ".cz4",
|
||||
Self::CZ5 => ".cz5",
|
||||
Self::MVT => ".mvt",
|
||||
Self::OGG => ".ogg",
|
||||
Self::OGGPAK => ".oggpak",
|
||||
Self::WAV => ".wav",
|
||||
Self::Unknown => "",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ pub struct PakLimits {
|
|||
impl Default for PakLimits {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
entry_limit: 10_000, // 10,000 entries
|
||||
entry_limit: 100_000, // 100,000 entries
|
||||
size_limit: u32::MAX as usize, // 10 gb
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,14 +10,16 @@ authors.workspace = true
|
|||
publish = false
|
||||
|
||||
[dependencies]
|
||||
colog = "1.3.0"
|
||||
colog = "1.3"
|
||||
cz = { path = "../cz/" }
|
||||
eframe = { version = "0.29", default-features = false, features = ["wayland", "x11", "accesskit", "default_fonts", "wgpu"] }
|
||||
egui_extras = "0.29"
|
||||
image = { version = "0.25", default-features = false, features = ["png"] }
|
||||
log = "0.4.22"
|
||||
kira = "0.10"
|
||||
log = "0.4"
|
||||
luca_pak = { path = "../luca_pak/" }
|
||||
rfd = "0.15"
|
||||
symphonia = "0.5.4"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
use colog;
|
||||
use eframe::egui::{
|
||||
self, ColorImage, Image, TextureFilter, TextureHandle, TextureOptions, ThemePreference,
|
||||
self, ColorImage, Image, ProgressBar, TextureFilter, TextureHandle, TextureOptions, ThemePreference
|
||||
};
|
||||
use kira::{backend::Backend, sound::static_sound::{StaticSoundData, StaticSoundHandle}, AudioManager, AudioManagerSettings, DefaultBackend, Tween};
|
||||
use log::error;
|
||||
use luca_pak::{entry::EntryType, Pak};
|
||||
use std::fs;
|
||||
use std::{fs, io::Cursor, time::Duration};
|
||||
|
||||
fn main() -> eframe::Result {
|
||||
colog::default_builder()
|
||||
|
@ -18,13 +19,23 @@ fn main() -> eframe::Result {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
let manager = AudioManager::<DefaultBackend>::new(AudioManagerSettings::default()).unwrap();
|
||||
|
||||
eframe::run_native(
|
||||
"LUCA PAK Explorer",
|
||||
options,
|
||||
Box::new(|ctx| {
|
||||
let ppp = ctx.egui_ctx.pixels_per_point() * 1.5;
|
||||
ctx.egui_ctx.set_pixels_per_point(ppp);
|
||||
Ok(Box::<PakExplorer>::default())
|
||||
Ok(Box::new(PakExplorer {
|
||||
open_file: None,
|
||||
selected_entry: None,
|
||||
image_texture: None,
|
||||
hex_string: None,
|
||||
audio_player: manager,
|
||||
audio_handle: None,
|
||||
audio_duration: None,
|
||||
}))
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
@ -34,17 +45,9 @@ struct PakExplorer {
|
|||
selected_entry: Option<luca_pak::entry::Entry>,
|
||||
image_texture: Option<egui::TextureHandle>,
|
||||
hex_string: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl Default for PakExplorer {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
open_file: None,
|
||||
selected_entry: None,
|
||||
image_texture: None,
|
||||
hex_string: None,
|
||||
}
|
||||
}
|
||||
audio_player: AudioManager,
|
||||
audio_handle: Option<StaticSoundHandle>,
|
||||
audio_duration: Option<Duration>,
|
||||
}
|
||||
|
||||
impl eframe::App for PakExplorer {
|
||||
|
@ -67,6 +70,13 @@ impl eframe::App for PakExplorer {
|
|||
self.selected_entry = None;
|
||||
self.image_texture = None;
|
||||
self.hex_string = None;
|
||||
|
||||
if let Some(a) = self.audio_handle.as_mut() {
|
||||
a.stop(Tween::default());
|
||||
}
|
||||
|
||||
self.audio_handle = None;
|
||||
self.audio_duration = None;
|
||||
}
|
||||
}
|
||||
if let Some(pak) = &self.open_file {
|
||||
|
@ -97,7 +107,7 @@ impl eframe::App for PakExplorer {
|
|||
};
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
egui::ComboBox::from_id_source("my-combobox")
|
||||
egui::ComboBox::from_id_salt("my-combobox")
|
||||
.selected_text(selection.clone())
|
||||
.truncate()
|
||||
.show_ui(ui, |ui| {
|
||||
|
@ -112,6 +122,13 @@ impl eframe::App for PakExplorer {
|
|||
.clicked()
|
||||
{
|
||||
self.image_texture = None;
|
||||
|
||||
if let Some(a) = self.audio_handle.as_mut() {
|
||||
a.stop(Tween::default());
|
||||
}
|
||||
|
||||
self.audio_handle = None;
|
||||
self.audio_duration = None;
|
||||
};
|
||||
}
|
||||
});
|
||||
|
@ -203,6 +220,46 @@ impl eframe::App for PakExplorer {
|
|||
)
|
||||
});
|
||||
}
|
||||
EntryType::OGG
|
||||
| EntryType::OGGPAK
|
||||
| EntryType::WAV => {
|
||||
ui.separator();
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("▶").clicked() && self.audio_handle.is_none() {
|
||||
let sound_data = StaticSoundData::from_cursor(
|
||||
Cursor::new(entry.cloned_bytes_fixed())
|
||||
)
|
||||
.unwrap()
|
||||
.volume(-8.0);
|
||||
|
||||
self.audio_duration = Some(sound_data.duration());
|
||||
self.audio_handle = Some(self.audio_player.play(sound_data.clone()).unwrap());
|
||||
}
|
||||
|
||||
if ui.button("⏹").clicked() && self.audio_handle.is_some() {
|
||||
self.audio_handle.as_mut().unwrap().stop(Tween::default());
|
||||
self.audio_handle = None;
|
||||
self.audio_duration = None;
|
||||
}
|
||||
|
||||
if let Some(a) = &self.audio_handle {
|
||||
let pos = a.position() as f32;
|
||||
|
||||
ui.add(ProgressBar::new(
|
||||
pos / self.audio_duration.as_ref().unwrap().as_secs_f32()
|
||||
).rounding(1.0).text(format!("{:02.0}:{:02.0}", pos / 60.0, pos % 60.0)));
|
||||
|
||||
if pos / self.audio_duration.as_ref().unwrap().as_secs_f32() > 0.99 {
|
||||
self.audio_handle.as_mut().unwrap().stop(Tween::default());
|
||||
self.audio_handle = None;
|
||||
self.audio_duration = None;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.request_repaint_after(Duration::from_millis(50));
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
ui.centered_and_justified(|ui| ui.label("No Preview Available"));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue