Show metadata for audio files, part of #56
This commit is contained in:
parent
aa9913b2a0
commit
67caa89151
2 changed files with 118 additions and 82 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
album = Album: {$album}
|
||||||
audio = Audio
|
audio = Audio
|
||||||
no-video-or-audio-file-open = No video or audio file open
|
no-video-or-audio-file-open = No video or audio file open
|
||||||
open-file = Open file
|
open-file = Open file
|
||||||
|
|
|
||||||
63
src/main.rs
63
src/main.rs
|
|
@ -198,6 +198,7 @@ pub struct MprisMeta {
|
||||||
album: String,
|
album: String,
|
||||||
album_art_opt: Option<url::Url>,
|
album_art_opt: Option<url::Url>,
|
||||||
album_artist: String,
|
album_artist: String,
|
||||||
|
album_year_opt: Option<i32>,
|
||||||
artists: Vec<String>,
|
artists: Vec<String>,
|
||||||
title: String,
|
title: String,
|
||||||
disc_number: i32,
|
disc_number: i32,
|
||||||
|
|
@ -266,6 +267,7 @@ pub struct App {
|
||||||
dropdown_opt: Option<DropdownKind>,
|
dropdown_opt: Option<DropdownKind>,
|
||||||
fullscreen: bool,
|
fullscreen: bool,
|
||||||
key_binds: HashMap<KeyBind, Action>,
|
key_binds: HashMap<KeyBind, Action>,
|
||||||
|
mpris_meta: MprisMeta,
|
||||||
mpris_opt: Option<(MprisMeta, MprisState, mpsc::UnboundedSender<MprisEvent>)>,
|
mpris_opt: Option<(MprisMeta, MprisState, mpsc::UnboundedSender<MprisEvent>)>,
|
||||||
nav_model: segmented_button::SingleSelectModel,
|
nav_model: segmented_button::SingleSelectModel,
|
||||||
projects: Vec<(String, PathBuf)>,
|
projects: Vec<(String, PathBuf)>,
|
||||||
|
|
@ -585,7 +587,6 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_mpris_meta(&mut self) {
|
fn update_mpris_meta(&mut self) {
|
||||||
if let Some((old, _, tx)) = &mut self.mpris_opt {
|
|
||||||
let mut new = MprisMeta {
|
let mut new = MprisMeta {
|
||||||
//TODO: clear url_opt when file is closed
|
//TODO: clear url_opt when file is closed
|
||||||
url_opt: self.flags.url_opt.clone(),
|
url_opt: self.flags.url_opt.clone(),
|
||||||
|
|
@ -601,6 +602,9 @@ impl App {
|
||||||
if let Some(tag) = tags.get::<gst::tags::AlbumArtist>() {
|
if let Some(tag) = tags.get::<gst::tags::AlbumArtist>() {
|
||||||
new.album_artist = tag.get().into();
|
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>() {
|
if let Some(tag) = tags.get::<gst::tags::Artist>() {
|
||||||
//TODO: how are multiple artists handled by gstreamer?
|
//TODO: how are multiple artists handled by gstreamer?
|
||||||
new.artists = vec![tag.get().into()];
|
new.artists = vec![tag.get().into()];
|
||||||
|
|
@ -632,9 +636,7 @@ impl App {
|
||||||
{
|
{
|
||||||
Ok(mut album_art) => {
|
Ok(mut album_art) => {
|
||||||
match image.write_with_encoder(
|
match image.write_with_encoder(
|
||||||
image::codecs::png::PngEncoder::new(
|
image::codecs::png::PngEncoder::new(&mut album_art),
|
||||||
&mut album_art,
|
|
||||||
),
|
|
||||||
) {
|
) {
|
||||||
Ok(()) => self.album_art_opt = Some(album_art),
|
Ok(()) => self.album_art_opt = Some(album_art),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
@ -646,10 +648,7 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::warn!(
|
log::warn!("failed to create temporary image: {}", err);
|
||||||
"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();
|
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 {
|
if new != *old {
|
||||||
*old = new.clone();
|
*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) {
|
fn update_mpris_state(&mut self) {
|
||||||
|
|
@ -782,6 +783,7 @@ impl Application for App {
|
||||||
dropdown_opt: None,
|
dropdown_opt: None,
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
key_binds: key_binds(),
|
key_binds: key_binds(),
|
||||||
|
mpris_meta: MprisMeta::default(),
|
||||||
mpris_opt: None,
|
mpris_opt: None,
|
||||||
nav_model: nav_bar::Model::builder().build(),
|
nav_model: nav_bar::Model::builder().build(),
|
||||||
projects: Vec::new(),
|
projects: Vec::new(),
|
||||||
|
|
@ -1222,6 +1224,7 @@ impl Application for App {
|
||||||
let cosmic_theme::Spacing {
|
let cosmic_theme::Spacing {
|
||||||
space_xxs,
|
space_xxs,
|
||||||
space_xs,
|
space_xs,
|
||||||
|
space_s,
|
||||||
space_m,
|
space_m,
|
||||||
..
|
..
|
||||||
} = theme::active().cosmic().spacing;
|
} = theme::active().cosmic().spacing;
|
||||||
|
|
@ -1273,14 +1276,46 @@ impl Application for App {
|
||||||
|
|
||||||
if let Some(album_art) = &self.album_art_opt {
|
if let Some(album_art) = &self.album_art_opt {
|
||||||
if !video.has_video() {
|
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)
|
let mut col = widget::column();
|
||||||
video_player = widget::column::with_children(vec![
|
col = col.push(widget::vertical_space(Length::Fill));
|
||||||
|
col = col.push(
|
||||||
widget::image(widget::image::Handle::from_path(album_art.path()))
|
widget::image(widget::image::Handle::from_path(album_art.path()))
|
||||||
.content_fit(ContentFit::ScaleDown)
|
.content_fit(ContentFit::ScaleDown)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill),
|
||||||
.height(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(),
|
.into(),
|
||||||
widget::container(video_player).height(space_m).into(),
|
widget::horizontal_space(Length::Fill).into(),
|
||||||
])
|
])
|
||||||
.into();
|
.into();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue