code: adding mp3 duration to lock buttons client side
This commit is contained in:
parent
a7da277977
commit
69ec048bc9
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -560,9 +560,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.147"
|
version = "0.2.152"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libloading"
|
name = "libloading"
|
||||||
@ -689,6 +689,15 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mp3-duration"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "348bdc7300502f0801e5b57c448815713cd843b744ef9bda252a2698fdf90a0f"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@ -1145,6 +1154,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"minijinja",
|
"minijinja",
|
||||||
"minimp3",
|
"minimp3",
|
||||||
|
"mp3-duration",
|
||||||
"regex",
|
"regex",
|
||||||
"rodio",
|
"rodio",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -11,8 +11,10 @@ axum = "0.6.18"
|
|||||||
axum-template = { version = "0.19.0", features = ["minijinja"] }
|
axum-template = { version = "0.19.0", features = ["minijinja"] }
|
||||||
cpal = "0.15.2"
|
cpal = "0.15.2"
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
|
# metadata = "0.1.8"
|
||||||
minijinja = { version = "1.0.3", features = ["loader"] }
|
minijinja = { version = "1.0.3", features = ["loader"] }
|
||||||
minimp3 = "0.5.1"
|
minimp3 = "0.5.1"
|
||||||
|
mp3-duration = "0.1.10"
|
||||||
regex = "1.9.0"
|
regex = "1.9.0"
|
||||||
rodio = "0.17.1"
|
rodio = "0.17.1"
|
||||||
serde = { version = "1.0.171", features = ["derive"] }
|
serde = { version = "1.0.171", features = ["derive"] }
|
||||||
|
@ -6,9 +6,11 @@ use std::fs;
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct SoundClip {
|
pub struct SoundClip {
|
||||||
|
title: String,
|
||||||
hash: String,
|
hash: String,
|
||||||
file_name: String,
|
file_name: String,
|
||||||
directory: String,
|
directory: String,
|
||||||
|
length: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SoundClip {
|
impl fmt::Display for SoundClip {
|
||||||
@ -23,8 +25,11 @@ impl fmt::Display for SoundClip {
|
|||||||
|
|
||||||
impl SoundClip {
|
impl SoundClip {
|
||||||
pub fn new(file_name: String, directory: String) -> Self {
|
pub fn new(file_name: String, directory: String) -> Self {
|
||||||
|
let full_file_name = format!("{}/{}", directory, file_name);
|
||||||
Self {
|
Self {
|
||||||
|
title: normalize_filename(&file_name),
|
||||||
hash: encode_filename(&file_name),
|
hash: encode_filename(&file_name),
|
||||||
|
length: get_sound_clip_length(&full_file_name),
|
||||||
file_name: file_name,
|
file_name: file_name,
|
||||||
directory: directory,
|
directory: directory,
|
||||||
}
|
}
|
||||||
@ -49,6 +54,44 @@ fn encode_filename(file_name: &str) -> String {
|
|||||||
hash_hex
|
hash_hex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* // needs metadata to install ffmpeg.
|
||||||
|
fn get_sound_clip_length(file_path: &str) -> Option<u64> {
|
||||||
|
if let Ok(meta) = metadata::media_file::MediaFileMetadata::new(&std::path::Path::new(file_path))
|
||||||
|
{
|
||||||
|
return Some(meta._duration);
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
fn get_sound_clip_length(file_path: &str) -> Option<u64> {
|
||||||
|
let path = std::path::Path::new(file_path);
|
||||||
|
if let Ok(duration) = mp3_duration::from_path(&path) {
|
||||||
|
if let Ok(millis) = duration.as_millis().try_into() {
|
||||||
|
return Some(millis);
|
||||||
|
}
|
||||||
|
return Some(duration.as_secs() * 1000 + 1);
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalize_filename(input: &str) -> String {
|
||||||
|
// List of extensions to be removed
|
||||||
|
let extensions = [".mp3", ".wav", ".flac", ".ogg"];
|
||||||
|
|
||||||
|
// Remove the extension if it matches any in the list
|
||||||
|
let without_extension = extensions.iter().fold(input.to_string(), |acc, &ext| {
|
||||||
|
if acc.ends_with(ext) {
|
||||||
|
acc.trim_end_matches(ext).to_string()
|
||||||
|
} else {
|
||||||
|
acc
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Replace all underscores with spaces
|
||||||
|
without_extension.replace("_", " ")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn scan_directory_for_clips(directory: &str, extensions: &[&str]) -> Option<Vec<SoundClip>> {
|
pub fn scan_directory_for_clips(directory: &str, extensions: &[&str]) -> Option<Vec<SoundClip>> {
|
||||||
let mut sound_clips = Vec::new();
|
let mut sound_clips = Vec::new();
|
||||||
|
|
||||||
|
@ -47,12 +47,42 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function play(hash) {
|
var disableTimeout;
|
||||||
|
var none = null;
|
||||||
|
|
||||||
|
function play(hash, timeout) {
|
||||||
|
|
||||||
|
if (timeout && timeout != "none") {
|
||||||
|
// Add the "disabled" class to all clip buttons
|
||||||
|
$('.clip').addClass('disabled');
|
||||||
|
|
||||||
|
// Add "primary" and "loading" classes to the clicked button
|
||||||
|
var clickedButton = $('#clip-' + hash);
|
||||||
|
clickedButton.addClass('double loading positive');
|
||||||
|
|
||||||
|
// Clear any existing timeout to avoid conflicts
|
||||||
|
clearTimeout(disableTimeout);
|
||||||
|
|
||||||
|
// Set a new timeout
|
||||||
|
disableTimeout = setTimeout(function () {
|
||||||
|
$('.clip').removeClass('disabled');
|
||||||
|
clickedButton.removeClass('double loading positive');
|
||||||
|
}, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
fetch("/play/" + hash);
|
fetch("/play/" + hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stop() {
|
function stop() {
|
||||||
fetch("/stop");
|
fetch("/stop");
|
||||||
|
|
||||||
|
// Clear the timeout
|
||||||
|
clearTimeout(disableTimeout);
|
||||||
|
|
||||||
|
// Remove the "disabled" class from all clip buttons
|
||||||
|
// and the "primary" and "loading" classes from any button that might have them
|
||||||
|
$('.clip').removeClass('disabled');
|
||||||
|
$('.clip').removeClass('double loading positive');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
@ -61,6 +91,10 @@
|
|||||||
/* Define a CSS variable for the width */
|
/* Define a CSS variable for the width */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui.ui.ui.ui.ui.ui.loading.button {
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
.left-column {
|
.left-column {
|
||||||
width: var(--left-column-width) !important;
|
width: var(--left-column-width) !important;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -110,8 +144,9 @@
|
|||||||
|
|
||||||
<div class="ui wrapped compact wrapping spaced /**buttons">
|
<div class="ui wrapped compact wrapping spaced /**buttons">
|
||||||
{% for clip in clips %}
|
{% for clip in clips %}
|
||||||
<button class="ui {{ loop.cycle('red', 'blue', 'green', 'violet', 'orange') }} basic button"
|
<button id="clip-{{clip.hash}}"
|
||||||
onclick="play('{{clip.hash}}')">{{clip.file_name}}</button>
|
class="ui {{ loop.cycle('red', 'blue', 'green', 'violet', 'orange') }} basic button clip"
|
||||||
|
onclick="play('{{clip.hash}}', {{clip.length}})">{{clip.title}}</button>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user