Show metadata for audio files, part of #56

This commit is contained in:
Jeremy Soller 2025-01-31 15:19:01 -07:00
parent aa9913b2a0
commit 67caa89151
No known key found for this signature in database
GPG key ID: 670FDFB5428E05CA
2 changed files with 118 additions and 82 deletions

View file

@ -1,3 +1,4 @@
album = Album: {$album}
audio = Audio
no-video-or-audio-file-open = No video or audio file open
open-file = Open file

View file

@ -198,6 +198,7 @@ pub struct MprisMeta {
album: String,
album_art_opt: Option<url::Url>,
album_artist: String,
album_year_opt: Option<i32>,
artists: Vec<String>,
title: String,
disc_number: i32,
@ -266,6 +267,7 @@ pub struct App {
dropdown_opt: Option<DropdownKind>,
fullscreen: bool,
key_binds: HashMap<KeyBind, Action>,
mpris_meta: MprisMeta,
mpris_opt: Option<(MprisMeta, MprisState, mpsc::UnboundedSender<MprisEvent>)>,
nav_model: segmented_button::SingleSelectModel,
projects: Vec<(String, PathBuf)>,
@ -585,7 +587,6 @@ impl App {
}
fn update_mpris_meta(&mut self) {
if let Some((old, _, tx)) = &mut self.mpris_opt {
let mut new = MprisMeta {
//TODO: clear url_opt when file is closed
url_opt: self.flags.url_opt.clone(),
@ -601,6 +602,9 @@ impl App {
if let Some(tag) = tags.get::<gst::tags::AlbumArtist>() {
new.album_artist = tag.get().into();
}
if let Some(tag) = tags.get::<gst::tags::DateTime>() {
new.album_year_opt = Some(tag.get().year());
}
if let Some(tag) = tags.get::<gst::tags::Artist>() {
//TODO: how are multiple artists handled by gstreamer?
new.artists = vec![tag.get().into()];
@ -632,9 +636,7 @@ impl App {
{
Ok(mut album_art) => {
match image.write_with_encoder(
image::codecs::png::PngEncoder::new(
&mut album_art,
),
image::codecs::png::PngEncoder::new(&mut album_art),
) {
Ok(()) => self.album_art_opt = Some(album_art),
Err(err) => {
@ -646,10 +648,7 @@ impl App {
}
}
Err(err) => {
log::warn!(
"failed to create temporary image: {}",
err
);
log::warn!("failed to create temporary image: {}", err);
}
}
}
@ -668,11 +667,13 @@ impl App {
new.album_art_opt = url::Url::from_file_path(album_art.path()).ok();
}
}
if let Some((old, _, tx)) = &mut self.mpris_opt {
if new != *old {
*old = new.clone();
let _ = tx.send(MprisEvent::Meta(new));
let _ = tx.send(MprisEvent::Meta(new.clone()));
}
}
self.mpris_meta = new;
}
fn update_mpris_state(&mut self) {
@ -782,6 +783,7 @@ impl Application for App {
dropdown_opt: None,
fullscreen: false,
key_binds: key_binds(),
mpris_meta: MprisMeta::default(),
mpris_opt: None,
nav_model: nav_bar::Model::builder().build(),
projects: Vec::new(),
@ -1222,6 +1224,7 @@ impl Application for App {
let cosmic_theme::Spacing {
space_xxs,
space_xs,
space_s,
space_m,
..
} = theme::active().cosmic().spacing;
@ -1273,14 +1276,46 @@ impl Application for App {
if let Some(album_art) = &self.album_art_opt {
if !video.has_video() {
// This is a hack to have the video player running but not visible (since the controls will cover it as an overlay)
video_player = widget::column::with_children(vec![
let mut col = widget::column();
col = col.push(widget::vertical_space(Length::Fill));
col = col.push(
widget::image(widget::image::Handle::from_path(album_art.path()))
.content_fit(ContentFit::ScaleDown)
.width(Length::Fill)
.height(Length::Fill)
.width(Length::Fill),
);
col = col.push(widget::vertical_space(space_s));
//TODO: fallback if title missing
col = col.push(widget::text::title4(&self.mpris_meta.title));
for artist in self.mpris_meta.artists.iter() {
col = col.push(widget::text::body(artist));
}
col = col.push(widget::vertical_space(space_s));
if !self.mpris_meta.album.is_empty() {
col = col.push(widget::text::body(fl!(
"album",
album = self.mpris_meta.album.as_str()
)));
}
if let Some(year) = &self.mpris_meta.album_year_opt {
col = col.push(widget::text::body(format!("{}", year)));
}
col = col.push(widget::vertical_space(Length::Fill));
// Space to keep from going under control overlay
let mut control_height = space_xxs + 32 + space_xxs;
if self.core.is_condensed() {
control_height += space_xxs + 32;
}
// This is a hack to have the video player running but not visible (since the controls will cover it as an overlay)
video_player = widget::row::with_children(vec![
widget::horizontal_space(Length::Fill).into(),
widget::container(
col.push(widget::container(video_player).height(control_height)),
)
.width(320)
.into(),
widget::container(video_player).height(space_m).into(),
widget::horizontal_space(Length::Fill).into(),
])
.into();
}