mirror of
https://github.com/Xevion/byte-me.git
synced 2025-12-06 11:14:36 -06:00
feat: add logging via tracing crate
This commit is contained in:
102
src-tauri/Cargo.lock
generated
102
src-tauri/Cargo.lock
generated
@@ -401,6 +401,8 @@ dependencies = [
|
|||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
"tauri-plugin-opener",
|
"tauri-plugin-opener",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
"ts-rs",
|
"ts-rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2201,6 +2203,15 @@ dependencies = [
|
|||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchers"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||||
|
dependencies = [
|
||||||
|
"regex-automata 0.1.10",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matches"
|
name = "matches"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
@@ -2325,6 +2336,16 @@ version = "0.1.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nu-ansi-term"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||||
|
dependencies = [
|
||||||
|
"overload",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
@@ -2662,6 +2683,12 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "overload"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango"
|
name = "pango"
|
||||||
version = "0.18.3"
|
version = "0.18.3"
|
||||||
@@ -3197,8 +3224,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata",
|
"regex-automata 0.4.9",
|
||||||
"regex-syntax",
|
"regex-syntax 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
dependencies = [
|
||||||
|
"regex-syntax 0.6.29",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3209,9 +3245,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-syntax",
|
"regex-syntax 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@@ -3568,6 +3610,15 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sharded-slab"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
@@ -4332,6 +4383,15 @@ dependencies = [
|
|||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.41"
|
version = "0.3.41"
|
||||||
@@ -4579,6 +4639,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-log"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
||||||
|
dependencies = [
|
||||||
|
"matchers",
|
||||||
|
"nu-ansi-term",
|
||||||
|
"once_cell",
|
||||||
|
"regex",
|
||||||
|
"sharded-slab",
|
||||||
|
"smallvec",
|
||||||
|
"thread_local",
|
||||||
|
"tracing",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4784,6 +4874,12 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "valuable"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version-compare"
|
name = "version-compare"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|||||||
@@ -24,3 +24,5 @@ serde = { version = "1", features = ["derive"] }
|
|||||||
ffprobe = "0.4.0"
|
ffprobe = "0.4.0"
|
||||||
ts-rs = { version = "11.0", features = ["format"] }
|
ts-rs = { version = "11.0", features = ["format"] }
|
||||||
infer = "0.19.0"
|
infer = "0.19.0"
|
||||||
|
tracing = "0.1"
|
||||||
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
|
|||||||
@@ -1,45 +1,109 @@
|
|||||||
use crate::models::StreamDetail;
|
use crate::models::StreamDetail;
|
||||||
|
use tracing::{debug, info, instrument};
|
||||||
|
|
||||||
|
#[instrument(skip(info), fields(stream_count = info.streams.len()))]
|
||||||
pub fn extract_streams(info: &ffprobe::FfProbe) -> Vec<StreamDetail> {
|
pub fn extract_streams(info: &ffprobe::FfProbe) -> Vec<StreamDetail> {
|
||||||
let mut streams = Vec::new();
|
let mut streams = Vec::new();
|
||||||
|
let mut video_count = 0;
|
||||||
|
let mut audio_count = 0;
|
||||||
|
let mut subtitle_count = 0;
|
||||||
|
|
||||||
for stream in &info.streams {
|
info!(total_streams = info.streams.len(), "Extracting streams from media file");
|
||||||
|
|
||||||
|
for (index, stream) in info.streams.iter().enumerate() {
|
||||||
match stream.codec_type.as_deref() {
|
match stream.codec_type.as_deref() {
|
||||||
Some("video") => {
|
Some("video") => {
|
||||||
|
video_count += 1;
|
||||||
|
let codec = stream
|
||||||
|
.codec_name
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| "unknown".to_string());
|
||||||
|
let width = stream.width.map(|w| w as u32);
|
||||||
|
let height = stream.height.map(|h| h as u32);
|
||||||
|
let bit_rate = stream.bit_rate.as_ref().map(|b| b.to_string());
|
||||||
|
let frame_rate = Some(stream.r_frame_rate.clone());
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
stream_index = index,
|
||||||
|
codec = %codec,
|
||||||
|
width = ?width,
|
||||||
|
height = ?height,
|
||||||
|
bit_rate = ?bit_rate,
|
||||||
|
frame_rate = ?frame_rate,
|
||||||
|
"Extracted video stream"
|
||||||
|
);
|
||||||
|
|
||||||
streams.push(StreamDetail::Video {
|
streams.push(StreamDetail::Video {
|
||||||
codec: stream
|
codec,
|
||||||
.codec_name
|
width,
|
||||||
.clone()
|
height,
|
||||||
.unwrap_or_else(|| "unknown".to_string()),
|
bit_rate,
|
||||||
width: stream.width.map(|w| w as u32),
|
frame_rate,
|
||||||
height: stream.height.map(|h| h as u32),
|
|
||||||
bit_rate: stream.bit_rate.as_ref().map(|b| b.to_string()),
|
|
||||||
frame_rate: Some(stream.r_frame_rate.clone()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some("audio") => {
|
Some("audio") => {
|
||||||
|
audio_count += 1;
|
||||||
|
let codec = stream
|
||||||
|
.codec_name
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| "unknown".to_string());
|
||||||
|
let sample_rate = stream.sample_rate.clone();
|
||||||
|
let channels = stream.channels.map(|c| c as u32);
|
||||||
|
let bit_rate = stream.bit_rate.as_ref().map(|b| b.to_string());
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
stream_index = index,
|
||||||
|
codec = %codec,
|
||||||
|
sample_rate = ?sample_rate,
|
||||||
|
channels = ?channels,
|
||||||
|
bit_rate = ?bit_rate,
|
||||||
|
"Extracted audio stream"
|
||||||
|
);
|
||||||
|
|
||||||
streams.push(StreamDetail::Audio {
|
streams.push(StreamDetail::Audio {
|
||||||
codec: stream
|
codec,
|
||||||
.codec_name
|
sample_rate,
|
||||||
.clone()
|
channels,
|
||||||
.unwrap_or_else(|| "unknown".to_string()),
|
bit_rate,
|
||||||
sample_rate: stream.sample_rate.clone(),
|
|
||||||
channels: stream.channels.map(|c| c as u32),
|
|
||||||
bit_rate: stream.bit_rate.as_ref().map(|b| b.to_string()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some("subtitle") => {
|
Some("subtitle") => {
|
||||||
|
subtitle_count += 1;
|
||||||
|
let codec = stream
|
||||||
|
.codec_name
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| "unknown".to_string());
|
||||||
|
let language = stream.tags.as_ref().and_then(|tags| tags.language.clone());
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
stream_index = index,
|
||||||
|
codec = %codec,
|
||||||
|
language = ?language,
|
||||||
|
"Extracted subtitle stream"
|
||||||
|
);
|
||||||
|
|
||||||
streams.push(StreamDetail::Subtitle {
|
streams.push(StreamDetail::Subtitle {
|
||||||
codec: stream
|
codec,
|
||||||
.codec_name
|
language,
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| "unknown".to_string()),
|
|
||||||
language: stream.tags.as_ref().and_then(|tags| tags.language.clone()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_ => {}
|
other => {
|
||||||
|
debug!(
|
||||||
|
stream_index = index,
|
||||||
|
codec_type = ?other,
|
||||||
|
"Skipping unknown stream type"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
video_streams = video_count,
|
||||||
|
audio_streams = audio_count,
|
||||||
|
subtitle_streams = subtitle_count,
|
||||||
|
total_extracted = streams.len(),
|
||||||
|
"Stream extraction completed"
|
||||||
|
);
|
||||||
|
|
||||||
streams
|
streams
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,26 @@
|
|||||||
mod ff;
|
pub mod ff;
|
||||||
mod media;
|
pub mod media;
|
||||||
mod models;
|
pub mod models;
|
||||||
pub mod strings;
|
pub mod strings;
|
||||||
|
|
||||||
use ff::extract_streams;
|
use ff::extract_streams;
|
||||||
use media::{detect_media_type, is_media_file};
|
use media::{detect_media_type, is_media_file};
|
||||||
use models::{StreamResult, StreamResultError};
|
use models::{StreamResult, StreamResultError};
|
||||||
|
use strings::transform_filename;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use tracing::{debug, error, info, instrument, warn};
|
||||||
|
|
||||||
// detection, helpers moved to modules above
|
// detection, helpers moved to modules above
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
#[instrument(skip(paths), fields(file_count = paths.len()))]
|
||||||
fn has_streams(paths: Vec<String>) -> Result<Vec<StreamResult>, StreamResultError> {
|
fn has_streams(paths: Vec<String>) -> Result<Vec<StreamResult>, StreamResultError> {
|
||||||
paths
|
info!(file_count = paths.len(), "Processing files for stream analysis");
|
||||||
|
|
||||||
|
let results = paths
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|path_str| {
|
.enumerate()
|
||||||
|
.map(|(index, path_str)| {
|
||||||
let path = Path::new(&path_str);
|
let path = Path::new(&path_str);
|
||||||
let filename = path
|
let filename = path
|
||||||
.file_name()
|
.file_name()
|
||||||
@@ -22,8 +28,18 @@ fn has_streams(paths: Vec<String>) -> Result<Vec<StreamResult>, StreamResultErro
|
|||||||
.unwrap_or("unknown")
|
.unwrap_or("unknown")
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
|
// Log full path only on first occurrence, then use truncated filename
|
||||||
|
if index == 0 {
|
||||||
|
debug!(full_path = %path_str, filename = %filename, "Processing first file");
|
||||||
|
} else {
|
||||||
|
let truncated_name = transform_filename(&filename, 15);
|
||||||
|
debug!(filename = %truncated_name, "Processing file");
|
||||||
|
}
|
||||||
|
|
||||||
// Check if file exists
|
// Check if file exists
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
|
let truncated_name = transform_filename(&filename, 15);
|
||||||
|
warn!(filename = %truncated_name, "File does not exist");
|
||||||
return Err(StreamResultError {
|
return Err(StreamResultError {
|
||||||
filename: Some(filename),
|
filename: Some(filename),
|
||||||
reason: "File does not exist".to_string(),
|
reason: "File does not exist".to_string(),
|
||||||
@@ -33,6 +49,8 @@ fn has_streams(paths: Vec<String>) -> Result<Vec<StreamResult>, StreamResultErro
|
|||||||
|
|
||||||
// Check if it's a file (not directory)
|
// Check if it's a file (not directory)
|
||||||
if !path.is_file() {
|
if !path.is_file() {
|
||||||
|
let truncated_name = transform_filename(&filename, 15);
|
||||||
|
warn!(filename = %truncated_name, "Path is not a file");
|
||||||
return Err(StreamResultError {
|
return Err(StreamResultError {
|
||||||
filename: Some(filename),
|
filename: Some(filename),
|
||||||
reason: "Not a file (directory or other)".to_string(),
|
reason: "Not a file (directory or other)".to_string(),
|
||||||
@@ -45,11 +63,17 @@ fn has_streams(paths: Vec<String>) -> Result<Vec<StreamResult>, StreamResultErro
|
|||||||
.map(|metadata| metadata.len())
|
.map(|metadata| metadata.len())
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
let truncated_name = transform_filename(&filename, 15);
|
||||||
|
debug!(filename = %truncated_name, size = size, "File metadata retrieved");
|
||||||
|
|
||||||
// Detect media type using magic numbers and fallback to extensions
|
// Detect media type using magic numbers and fallback to extensions
|
||||||
let media_type = detect_media_type(path);
|
let media_type = detect_media_type(path);
|
||||||
|
debug!(filename = %truncated_name, media_type = ?media_type, "Media type detected");
|
||||||
|
|
||||||
// Only try to analyze media files with ffprobe
|
// Only try to analyze media files with ffprobe
|
||||||
if is_media_file(&media_type) {
|
if is_media_file(&media_type) {
|
||||||
|
info!(filename = %truncated_name, media_type = ?media_type, "Analyzing media file with ffprobe");
|
||||||
|
|
||||||
// Analyze with ffprobe
|
// Analyze with ffprobe
|
||||||
match ffprobe::ffprobe(&path_str) {
|
match ffprobe::ffprobe(&path_str) {
|
||||||
Ok(info) => {
|
Ok(info) => {
|
||||||
@@ -59,6 +83,13 @@ fn has_streams(paths: Vec<String>) -> Result<Vec<StreamResult>, StreamResultErro
|
|||||||
.duration
|
.duration
|
||||||
.and_then(|dur_str| dur_str.parse::<f64>().ok());
|
.and_then(|dur_str| dur_str.parse::<f64>().ok());
|
||||||
|
|
||||||
|
info!(
|
||||||
|
filename = %truncated_name,
|
||||||
|
stream_count = streams.len(),
|
||||||
|
duration = ?duration,
|
||||||
|
"Successfully analyzed media file"
|
||||||
|
);
|
||||||
|
|
||||||
Ok(StreamResult {
|
Ok(StreamResult {
|
||||||
filename,
|
filename,
|
||||||
path: path_str,
|
path: path_str,
|
||||||
@@ -69,7 +100,7 @@ fn has_streams(paths: Vec<String>) -> Result<Vec<StreamResult>, StreamResultErro
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("Could not analyze media file with ffprobe: {err:?}");
|
error!(filename = %truncated_name, error = %err, "Failed to analyze media file with ffprobe");
|
||||||
Err(StreamResultError {
|
Err(StreamResultError {
|
||||||
filename: Some(filename),
|
filename: Some(filename),
|
||||||
reason: format!("Could not analyze media file: {err}"),
|
reason: format!("Could not analyze media file: {err}"),
|
||||||
@@ -78,6 +109,7 @@ fn has_streams(paths: Vec<String>) -> Result<Vec<StreamResult>, StreamResultErro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
debug!(filename = %truncated_name, media_type = ?media_type, "Skipping non-media file");
|
||||||
// For non-media files, return an error indicating it's not a media file
|
// For non-media files, return an error indicating it's not a media file
|
||||||
Err(StreamResultError {
|
Err(StreamResultError {
|
||||||
filename: Some(filename),
|
filename: Some(filename),
|
||||||
@@ -86,11 +118,23 @@ fn has_streams(paths: Vec<String>) -> Result<Vec<StreamResult>, StreamResultErro
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>();
|
||||||
|
|
||||||
|
match &results {
|
||||||
|
Ok(streams) => {
|
||||||
|
info!(successful_files = streams.len(), "Successfully processed all files");
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
warn!("Some files failed to process");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
|
info!("Initializing Tauri application");
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_opener::init())
|
.plugin(tauri_plugin_opener::init())
|
||||||
.invoke_handler(tauri::generate_handler![has_streams])
|
.invoke_handler(tauri::generate_handler![has_streams])
|
||||||
|
|||||||
@@ -1,6 +1,19 @@
|
|||||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// Initialize tracing with env-filter
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(
|
||||||
|
EnvFilter::from_default_env()
|
||||||
|
.add_directive("byte_me=debug".parse().unwrap())
|
||||||
|
.add_directive("tauri=info".parse().unwrap()),
|
||||||
|
)
|
||||||
|
.with(tracing_subscriber::fmt::layer())
|
||||||
|
.init();
|
||||||
|
|
||||||
|
tracing::info!("Starting byte-me application");
|
||||||
byte_me_lib::run()
|
byte_me_lib::run()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
use crate::models::MediaType;
|
use crate::models::MediaType;
|
||||||
use std::{fs::File, io::Read, path::Path};
|
use std::{fs::File, io::Read, path::Path};
|
||||||
|
use tracing::{debug, instrument, trace, warn};
|
||||||
|
|
||||||
|
#[instrument(skip(path), fields(path = %path.display()))]
|
||||||
pub fn detect_media_type(path: &Path) -> MediaType {
|
pub fn detect_media_type(path: &Path) -> MediaType {
|
||||||
|
debug!("Starting media type detection");
|
||||||
|
|
||||||
// First try to detect using infer crate (magic number detection)
|
// First try to detect using infer crate (magic number detection)
|
||||||
if let Ok(mut file) = File::open(path) {
|
if let Ok(mut file) = File::open(path) {
|
||||||
let mut buffer = [0; 512];
|
let mut buffer = [0; 512];
|
||||||
if let Ok(bytes_read) = file.read(&mut buffer) {
|
if let Ok(bytes_read) = file.read(&mut buffer) {
|
||||||
|
trace!(bytes_read = bytes_read, "Read file header for magic number detection");
|
||||||
|
|
||||||
if let Some(kind) = infer::get(&buffer[..bytes_read]) {
|
if let Some(kind) = infer::get(&buffer[..bytes_read]) {
|
||||||
return match kind.mime_type() {
|
let mime_type = kind.mime_type();
|
||||||
|
debug!(mime_type = %mime_type, "Detected MIME type from magic numbers");
|
||||||
|
|
||||||
|
let media_type = match mime_type {
|
||||||
// Audio types
|
// Audio types
|
||||||
"audio/mpeg" | "audio/mp3" | "audio/m4a" | "audio/ogg" | "audio/x-flac"
|
"audio/mpeg" | "audio/mp3" | "audio/m4a" | "audio/ogg" | "audio/x-flac"
|
||||||
| "audio/x-wav" | "audio/amr" | "audio/aac" | "audio/x-aiff"
|
| "audio/x-wav" | "audio/amr" | "audio/aac" | "audio/x-aiff"
|
||||||
@@ -90,13 +99,25 @@ pub fn detect_media_type(path: &Path) -> MediaType {
|
|||||||
// Library types (covered by executable types above, but keeping for clarity)
|
// Library types (covered by executable types above, but keeping for clarity)
|
||||||
_ => MediaType::Unknown,
|
_ => MediaType::Unknown,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
debug!(media_type = ?media_type, "Detected media type from magic numbers");
|
||||||
|
return media_type;
|
||||||
|
} else {
|
||||||
|
debug!("Magic number detection failed, falling back to extension-based detection");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Failed to read file for magic number detection");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Failed to open file for magic number detection");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to extension-based detection
|
// Fallback to extension-based detection
|
||||||
if let Some(extension) = path.extension() {
|
if let Some(extension) = path.extension() {
|
||||||
match extension.to_str().unwrap_or("").to_lowercase().as_str() {
|
let ext_str = extension.to_str().unwrap_or("").to_lowercase();
|
||||||
|
debug!(extension = %ext_str, "Detecting media type from file extension");
|
||||||
|
|
||||||
|
let media_type = match ext_str.as_str() {
|
||||||
// Audio extensions
|
// Audio extensions
|
||||||
"mp3" | "wav" | "flac" | "ogg" | "m4a" | "aac" | "wma" | "mid" | "amr" | "aiff"
|
"mp3" | "wav" | "flac" | "ogg" | "m4a" | "aac" | "wma" | "mid" | "amr" | "aiff"
|
||||||
| "dsf" | "ape" => MediaType::Audio,
|
| "dsf" | "ape" => MediaType::Audio,
|
||||||
@@ -127,15 +148,23 @@ pub fn detect_media_type(path: &Path) -> MediaType {
|
|||||||
"so" | "dylib" => MediaType::Library,
|
"so" | "dylib" => MediaType::Library,
|
||||||
|
|
||||||
_ => MediaType::Unknown,
|
_ => MediaType::Unknown,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
debug!(media_type = ?media_type, "Detected media type from extension");
|
||||||
|
media_type
|
||||||
} else {
|
} else {
|
||||||
|
debug!("No file extension found, returning Unknown");
|
||||||
MediaType::Unknown
|
MediaType::Unknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(media_type))]
|
||||||
pub fn is_media_file(media_type: &MediaType) -> bool {
|
pub fn is_media_file(media_type: &MediaType) -> bool {
|
||||||
matches!(
|
let is_media = matches!(
|
||||||
media_type,
|
media_type,
|
||||||
MediaType::Audio | MediaType::Video | MediaType::Image
|
MediaType::Audio | MediaType::Video | MediaType::Image
|
||||||
)
|
);
|
||||||
|
|
||||||
|
debug!(media_type = ?media_type, is_media = is_media, "Checking if file is media type");
|
||||||
|
is_media
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user