160 lines
6.5 KiB
Rust
160 lines
6.5 KiB
Rust
use egui::{RichText, Sense, Stroke, Vec2};
|
|
use xmpd_manifest::store::BaseStore;
|
|
|
|
use super::{song_list::SongList, CompGetter, CompUi};
|
|
|
|
|
|
#[derive(Debug)]
|
|
pub struct Player {
|
|
slider_progress: usize,
|
|
old_slider_progress: usize,
|
|
volume_slider: f64,
|
|
}
|
|
|
|
impl Default for Player {
|
|
fn default() -> Self {
|
|
Self {
|
|
volume_slider: 1.0,
|
|
old_slider_progress: 0,
|
|
slider_progress: 0
|
|
}
|
|
}
|
|
}
|
|
|
|
component_register!(Player);
|
|
|
|
|
|
impl CompUi for Player {
|
|
fn draw(ui: &mut egui::Ui, state: &mut crate::GuiState) -> crate::Result<()> {
|
|
let theme = xmpd_settings::Settings::get()?.theme.clone();
|
|
let full_avail = ui.available_size();
|
|
ui.horizontal_centered(|ui| {
|
|
ui.add_space(10.0);
|
|
let icon = egui::Image::new(crate::data::NOTE_ICON)
|
|
.tint(theme.accent_color)
|
|
.sense(Sense::click())
|
|
.fit_to_exact_size(Vec2::new(32.0, 32.0));
|
|
ui.add(icon);
|
|
ui.vertical(|ui| {
|
|
|
|
ui.add_space(5.0);
|
|
let sid = &handle_error_ui!(SongList::get()).selected_sid;
|
|
if let Some(song) = state.manifest.store().get_song(sid) {
|
|
let mut name = song.name().to_string();
|
|
if name.len() > 16 {
|
|
name = (&name)[..16].to_string();
|
|
name.push_str("...");
|
|
}
|
|
ui.label(
|
|
RichText::new(name)
|
|
.size(12.0)
|
|
);
|
|
ui.label(
|
|
RichText::new(song.author())
|
|
.size(8.0)
|
|
.monospace()
|
|
);
|
|
}
|
|
});
|
|
ui.vertical_centered_justified(|ui| {
|
|
let avail = ui.available_size();
|
|
let song_info_w = full_avail.x - avail.x;
|
|
ui.add_space(3.0);
|
|
ui.horizontal(|ui| {
|
|
|
|
{
|
|
let slider_width = full_avail.x * 0.60;
|
|
ui.add_space((((full_avail.x / 2.0) - song_info_w) - slider_width / 2.0).clamp(0.0, f32::MAX));
|
|
ui.style_mut().spacing.slider_width = avail.x * 0.75;
|
|
let s = Stroke {
|
|
color: theme.accent_color,
|
|
width: 2.0
|
|
};
|
|
ui.style_mut().visuals.widgets.inactive.fg_stroke = s;
|
|
ui.style_mut().visuals.widgets.active.fg_stroke = s;
|
|
ui.style_mut().visuals.widgets.hovered.fg_stroke = s;
|
|
|
|
let mut slf = handle_error_ui!(Player::get());
|
|
ui.add(
|
|
egui::Slider::new(&mut slf.slider_progress, 0..=100)
|
|
.show_value(false)
|
|
);
|
|
if slf.slider_progress == slf.old_slider_progress {
|
|
slf.slider_progress = (state.player.get_played_f() * 100.0) as usize;
|
|
slf.old_slider_progress = slf.slider_progress;
|
|
} else {
|
|
handle_error_ui!(state.player.seek_to_f(slf.slider_progress as f64 / 100.0 ));
|
|
slf.old_slider_progress = slf.slider_progress;
|
|
}
|
|
let secs_left = state.player.get_ms_left() as f64 / 1000.0;
|
|
let h = (secs_left/60.0/60.0).floor();
|
|
let m = ((secs_left - h * 60.0)/60.0).floor();
|
|
let s = (secs_left - m * 60.0).floor();
|
|
|
|
ui.label(format!("{h:02}:{m:02}:{s:02}"));
|
|
}
|
|
});
|
|
ui.horizontal(|ui| {
|
|
let icon_size = 16.0;
|
|
ui.add_space(((full_avail.x / 2.0) - song_info_w) - icon_size * 1.5 - ui.spacing().item_spacing.x);
|
|
let pp = if state.player.is_paused() {
|
|
crate::data::PLAY_ICON
|
|
} else {
|
|
crate::data::PAUSE_ICON
|
|
};
|
|
|
|
let prev = egui::Image::new(crate::data::PREV_ICON)
|
|
.tint(theme.accent_color)
|
|
.sense(Sense::click())
|
|
.max_size(Vec2::new(icon_size, icon_size));
|
|
let pp = egui::Image::new(pp)
|
|
.tint(theme.accent_color)
|
|
.sense(Sense::click())
|
|
.max_size(Vec2::new(icon_size, icon_size));
|
|
let next = egui::Image::new(crate::data::NEXT_ICON)
|
|
.tint(theme.accent_color)
|
|
.sense(Sense::click())
|
|
.max_size(Vec2::new(icon_size, icon_size));
|
|
if ui.add(prev).clicked() {
|
|
handle_error_ui!(handle_error_ui!(SongList::get()).play_prev(state));
|
|
}
|
|
if ui.add(pp).clicked() {
|
|
if state.player.is_paused() {
|
|
state.player.play();
|
|
} else {
|
|
state.player.pause();
|
|
}
|
|
}
|
|
if ui.add(next).clicked() || state.player.just_stopped() {
|
|
handle_error_ui!(handle_error_ui!(SongList::get()).play_next(state));
|
|
}
|
|
|
|
|
|
|
|
ui.add_space(15.0);
|
|
ui.style_mut().spacing.slider_width = avail.x * 0.15;
|
|
let s = Stroke {
|
|
color: theme.accent_color,
|
|
width: 1.0
|
|
};
|
|
ui.style_mut().visuals.widgets.inactive.fg_stroke = s;
|
|
ui.style_mut().visuals.widgets.active.fg_stroke = s;
|
|
ui.style_mut().visuals.widgets.hovered.fg_stroke = s;
|
|
|
|
let mut slf = handle_error_ui!(Player::get());
|
|
let slider =ui.add(
|
|
egui::Slider::new(&mut slf.volume_slider, 0.0..=1.0)
|
|
.show_value(false)
|
|
);
|
|
|
|
if slider.changed() {
|
|
state.player.set_volume(slf.volume_slider);
|
|
}
|
|
});
|
|
ui.add_space(3.0);
|
|
});
|
|
});
|
|
Ok(())
|
|
}
|
|
}
|