Compare commits

...

4 Commits

Author SHA1 Message Date
Emi Simpson 436403d129
Add a whole bunch more clippy lints 2022-01-26 18:42:31 -05:00
Emi Simpson 29d36a8010
Minor clippy tweak 2022-01-26 17:20:17 -05:00
Emi Simpson 746715be39
Redo metadata -> song pipeline
Following the rejection of https://github.com/RustAudio/rodio/pull/410
2022-01-26 17:18:23 -05:00
Emi Simpson b97ae618b0
Fix images in background 2022-01-26 16:24:10 -05:00
13 changed files with 149 additions and 126 deletions

8
.gitmodules vendored
View File

@ -1,4 +1,4 @@
[submodule "rodio"] [submodule "iced"]
path = rodio path = iced
url = https://github.com/Alch-Emi/rodio.git url = https://github.com/Alch-Emi/iced.git
branch = new-from-format-reader branch = image-modes

82
Cargo.lock generated
View File

@ -96,12 +96,6 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "arrayvec"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "269d0f5e68353a7cab87f81e7c736adc008d279a36ebc6a05dfe01193a89f0c9"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
version = "0.7.2" version = "0.7.2"
@ -1474,7 +1468,6 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]] [[package]]
name = "iced" name = "iced"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/iced-rs/iced.git#b7bc169120d3447ead238e974007027a5152d341"
dependencies = [ dependencies = [
"iced_core", "iced_core",
"iced_futures", "iced_futures",
@ -1487,7 +1480,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_core" name = "iced_core"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/iced-rs/iced.git#b7bc169120d3447ead238e974007027a5152d341"
dependencies = [ dependencies = [
"bitflags", "bitflags",
] ]
@ -1495,7 +1487,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_futures" name = "iced_futures"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/iced-rs/iced.git#b7bc169120d3447ead238e974007027a5152d341"
dependencies = [ dependencies = [
"futures", "futures",
"log", "log",
@ -1506,7 +1497,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_graphics" name = "iced_graphics"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/iced-rs/iced.git#b7bc169120d3447ead238e974007027a5152d341"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"font-kit", "font-kit",
@ -1521,7 +1511,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_lazy" name = "iced_lazy"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/iced-rs/iced.git#b7bc169120d3447ead238e974007027a5152d341"
dependencies = [ dependencies = [
"iced_native", "iced_native",
"ouroboros", "ouroboros",
@ -1530,7 +1519,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_native" name = "iced_native"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/iced-rs/iced.git#b7bc169120d3447ead238e974007027a5152d341"
dependencies = [ dependencies = [
"iced_core", "iced_core",
"iced_futures", "iced_futures",
@ -1543,7 +1531,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_style" name = "iced_style"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/iced-rs/iced.git#b7bc169120d3447ead238e974007027a5152d341"
dependencies = [ dependencies = [
"iced_core", "iced_core",
] ]
@ -1551,7 +1538,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_web" name = "iced_web"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/iced-rs/iced.git#b7bc169120d3447ead238e974007027a5152d341"
dependencies = [ dependencies = [
"base64", "base64",
"dodrio", "dodrio",
@ -1568,7 +1554,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_wgpu" name = "iced_wgpu"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/iced-rs/iced.git#b7bc169120d3447ead238e974007027a5152d341"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"bytemuck", "bytemuck",
@ -1588,7 +1573,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_winit" name = "iced_winit"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/iced-rs/iced.git#b7bc169120d3447ead238e974007027a5152d341"
dependencies = [ dependencies = [
"iced_futures", "iced_futures",
"iced_graphics", "iced_graphics",
@ -2703,7 +2687,9 @@ dependencies = [
[[package]] [[package]]
name = "rodio" name = "rodio"
version = "0.14.0" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e"
dependencies = [ dependencies = [
"cpal", "cpal",
"symphonia", "symphonia",
@ -2980,15 +2966,16 @@ checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2"
[[package]] [[package]]
name = "symphonia" name = "symphonia"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fae959d5ea7b4cd0cd8db3b899ec4f549b0d8a298694826a36ae7e5f19d4aa6" checksum = "a7e5f38aa07e792f4eebb0faa93cee088ec82c48222dd332897aae1569d9a4b7"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"symphonia-bundle-flac", "symphonia-bundle-flac",
"symphonia-bundle-mp3", "symphonia-bundle-mp3",
"symphonia-codec-aac", "symphonia-codec-aac",
"symphonia-codec-pcm", "symphonia-codec-pcm",
"symphonia-codec-vorbis",
"symphonia-core", "symphonia-core",
"symphonia-format-isomp4", "symphonia-format-isomp4",
"symphonia-format-ogg", "symphonia-format-ogg",
@ -2998,9 +2985,9 @@ dependencies = [
[[package]] [[package]]
name = "symphonia-bundle-flac" name = "symphonia-bundle-flac"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b237be42d0ff1ff64c6e073aea4f93985ca51de93b8279f16a4b006e3e5997af" checksum = "116e5412f5fb4e5d07efd6628d50d6fcd7a61ebef43d98f5012f3cf763b25d02"
dependencies = [ dependencies = [
"log", "log",
"symphonia-core", "symphonia-core",
@ -3010,9 +2997,9 @@ dependencies = [
[[package]] [[package]]
name = "symphonia-bundle-mp3" name = "symphonia-bundle-mp3"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f596fe16d2ae06e9404558644b61e27e2dcfee6c511f559be4699c403283fa" checksum = "ec4d97c4a61ece4651751dddb393ebecb7579169d9e758ae808fe507a5250790"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"lazy_static", "lazy_static",
@ -3023,9 +3010,9 @@ dependencies = [
[[package]] [[package]]
name = "symphonia-codec-aac" name = "symphonia-codec-aac"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e636422dccfb202b24f8066b8d3ebfa914bbc690dae78db52b54691ba916c3f" checksum = "bd3d7ab37eb9b7df16ddedd7adb7cc382afe708ff078e525a14dc9b05e57558f"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"log", "log",
@ -3034,32 +3021,43 @@ dependencies = [
[[package]] [[package]]
name = "symphonia-codec-pcm" name = "symphonia-codec-pcm"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "021d8161b186bea81c7cf4a80c67c71fb53862cd9f426cd3e032ae09bdd42dec" checksum = "ba1d54738758993546107e3a4be2c1da827f2d4489fcffee0fa47867254e44c7"
dependencies = [ dependencies = [
"log", "log",
"symphonia-core", "symphonia-core",
] ]
[[package]] [[package]]
name = "symphonia-core" name = "symphonia-codec-vorbis"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1742e06f50b4a7ed7abee53433231e050a248b498cd0ae2c639c8a70b115001" checksum = "a29ed6748078effb35a05064a451493a78038918981dc1a76bdf5a2752d441fa"
dependencies = [ dependencies = [
"arrayvec 0.6.1", "log",
"symphonia-core",
"symphonia-utils-xiph",
]
[[package]]
name = "symphonia-core"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa135e97be0f4a666c31dfe5ef4c75435ba3d355fd6a73d2100aa79b14c104c9"
dependencies = [
"arrayvec 0.7.2",
"bitflags", "bitflags",
"byteorder", "bytemuck",
"lazy_static", "lazy_static",
"log", "log",
] ]
[[package]] [[package]]
name = "symphonia-format-isomp4" name = "symphonia-format-isomp4"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf3c6b6ca3347caa22d72f04cfd509f0c32683b0dbe01d0cfb63fd2726ac6da5" checksum = "feee3a7711e7ec1b7540756f3868bbb3cbb0d1195569b9bc26471a24a02f57b5"
dependencies = [ dependencies = [
"encoding_rs", "encoding_rs",
"log", "log",
@ -3069,9 +3067,9 @@ dependencies = [
[[package]] [[package]]
name = "symphonia-format-ogg" name = "symphonia-format-ogg"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4898eef85c5a05136e1f3b5ff1afe4423cd7642c8979ed007cc8924b9a4c18c1" checksum = "d7b2357288a79adfec532cfd86049696cfa5c58efeff83bd51687a528f18a519"
dependencies = [ dependencies = [
"log", "log",
"symphonia-core", "symphonia-core",
@ -3081,9 +3079,9 @@ dependencies = [
[[package]] [[package]]
name = "symphonia-format-wav" name = "symphonia-format-wav"
version = "0.3.0" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97e863d9a912ea518dfae664292e38b2b961a1eb780251eba89b60e3905fef37" checksum = "6d9fa5e5b420dea6763ba2547887eb1a02a142c676c5b02ed1b113a247101dad"
dependencies = [ dependencies = [
"log", "log",
"symphonia-core", "symphonia-core",
@ -3092,9 +3090,9 @@ dependencies = [
[[package]] [[package]]
name = "symphonia-metadata" name = "symphonia-metadata"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db5e36e38a7400f968569135e7ac0f8647de42e93905ad41c79d583aaeae565c" checksum = "5260599daba18d8fe905ca3eb3b42ba210529a6276886632412cc74984e79b1a"
dependencies = [ dependencies = [
"encoding_rs", "encoding_rs",
"lazy_static", "lazy_static",
@ -3104,9 +3102,9 @@ dependencies = [
[[package]] [[package]]
name = "symphonia-utils-xiph" name = "symphonia-utils-xiph"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47377d86d61acf4d5b1a054b8e7a7cac8266155577a5410e4d746aec6394c42a" checksum = "6a37026c6948ff842e0bf94b4008579cc71ab16ed0ff9ca70a331f60f4f1e1e9"
dependencies = [ dependencies = [
"symphonia-core", "symphonia-core",
"symphonia-metadata", "symphonia-metadata",

View File

@ -26,28 +26,28 @@ blocking = "1.1.0"
[dependencies.symphonia] [dependencies.symphonia]
# Music decoding and metadata parsing # Music decoding and metadata parsing
features = ["isomp4", "aac", "mp3"] features = ["isomp4", "aac", "mp3"]
version = "0.3.0" version = "0.4.0"
[dependencies.iced] [dependencies.iced]
# Display windows & graphics # Display windows & graphics
features = ["canvas", "image"] features = ["canvas", "image"]
git = "https://github.com/iced-rs/iced.git" path = "./iced/"
[dependencies.iced_native] [dependencies.iced_native]
# Native-display only GUI features # Native-display only GUI features
git = "https://github.com/iced-rs/iced.git" path = "./iced/native"
[dependencies.iced_lazy] [dependencies.iced_lazy]
# Responsive widget design # Responsive widget design
git = "https://github.com/iced-rs/iced.git" path = "./iced/lazy"
[dependencies.iced_futures] [dependencies.iced_futures]
# Display windows & graphics # Display windows & graphics
features = ["smol"] features = ["smol"]
git = "https://github.com/iced-rs/iced.git" path = "./iced/futures"
[dependencies.rodio] [dependencies.rodio]
# Playing audio # Playing audio
default-features = false default-features = false
features = ["symphonia-all"] features = ["symphonia-all"]
path = "./rodio/" version = "0.15"

1
rodio

@ -1 +0,0 @@
Subproject commit 706abafcadab2c0049d7a7724cae43f203ba0f67

View File

@ -40,7 +40,7 @@ impl Application for DelyriumApp {
fn new(_: Self::Flags) -> (Self, Command<Message>) { fn new(_: Self::Flags) -> (Self, Command<Message>) {
( (
DelyriumApp(Model::DEFAULT), Self(Model::DEFAULT),
Command::none(), Command::none(),
) )
} }

View File

@ -1,9 +1,9 @@
use std::fs::File;
use iced::Command; use iced::Command;
use core::time::Duration; use core::time::Duration;
use iced::Length; use iced::Length;
use iced::Color; use iced::Color;
use iced::Point; use iced::Point;
use symphonia::core::formats::FormatReader;
use crate::player::PlayerError; use crate::player::PlayerError;
use iced::canvas::event::Status; use iced::canvas::event::Status;
use iced::canvas::Event; use iced::canvas::Event;
@ -39,7 +39,7 @@ use ErrorState::*;
pub struct Controls(pub ErrorState); pub struct Controls(pub ErrorState);
impl Controls { impl Controls {
pub fn new(song: Box<dyn FormatReader>) -> (Self, Command<Message>) { pub fn new(song: File) -> (Self, Command<Message>) {
match Player::new(song) { match Player::new(song) {
Ok(player) => { Ok(player) => {
let duration_task = unblock(player.compute_duration()); let duration_task = unblock(player.compute_duration());
@ -49,7 +49,7 @@ impl Controls {
); );
( (
Controls(NoError { Self(NoError {
has_device: player.has_output_device(), has_device: player.has_output_device(),
player, player,
}), }),
@ -57,12 +57,12 @@ impl Controls {
) )
}, },
Err(e) => { Err(e) => {
(Controls(Error(e)), Command::none()) (Self(Error(e)), Command::none())
} }
} }
} }
pub fn view_progress(&mut self, theme: Theme) -> Canvas<Message, (&Controls, Theme)> { pub fn view_progress(&mut self, theme: Theme) -> Canvas<Message, (&Self, Theme)> {
Canvas::new((&*self, theme)) Canvas::new((&*self, theme))
.width(Length::Units(50)) .width(Length::Units(50))
.height(Length::Fill) .height(Length::Fill)
@ -138,7 +138,7 @@ impl Program<Message> for (&Controls, Theme) {
let background = Color {r: 1., g: 0.1, b: 0.1, a: 1.}; let background = Color {r: 1., g: 0.1, b: 0.1, a: 1.};
frame.fill_rectangle(Point::ORIGIN, bounds.size(), background); frame.fill_rectangle(Point::ORIGIN, bounds.size(), background);
eprintln!("Error!!! {}", e.to_string()); eprintln!("Error!!! {}", e);
} }
} }

View File

@ -6,6 +6,7 @@ use iced::Alignment;
use iced::widget::scrollable::{self, Scrollable}; use iced::widget::scrollable::{self, Scrollable};
use iced::Space; use iced::Space;
use iced::Canvas; use iced::Canvas;
use iced::ContentFit;
use crate::styles::{Theme, FONT_VG5000}; use crate::styles::{Theme, FONT_VG5000};
use crate::controls::Controls; use crate::controls::Controls;
use crate::model::Editing; use crate::model::Editing;
@ -22,10 +23,12 @@ pub fn view_editor(editing: &mut Editing) -> Element<Message> {
let (img1, img2) = ( let (img1, img2) = (
Image::new(margin_bg.clone()) Image::new(margin_bg.clone())
.width(Length::FillPortion(1)) .width(Length::FillPortion(1))
.height(Length::Fill), .height(Length::Fill)
.fit(ContentFit::Cover),
Image::new(margin_bg.clone()) Image::new(margin_bg.clone())
.width(Length::FillPortion(1)) .width(Length::FillPortion(1))
.height(Length::Fill), .height(Length::Fill)
.fit(ContentFit::Cover),
); );
Row::new() Row::new()
@ -55,7 +58,7 @@ pub fn view_lyrics<'a>(lyrics: &'a mut [Lyric], scroll_state: &'a mut scrollable
let scroller = lyrics.iter_mut() let scroller = lyrics.iter_mut()
.enumerate() .enumerate()
.map(|(i, l)| view_lyric(l, is_sole_line, i, theme)) .map(|(i, l)| view_lyric(l, is_sole_line, i, theme))
.fold(Scrollable::new(scroll_state).push(spacers.0), |s, l| s.push(l)) .fold(Scrollable::new(scroll_state).push(spacers.0), Scrollable::push)
.push(spacers.1) .push(spacers.1)
.width(Length::Fill) .width(Length::Fill)
.align_items(Alignment::Center); .align_items(Alignment::Center);

View File

@ -1,3 +1,4 @@
use std::fs::File;
use image::DynamicImage; use image::DynamicImage;
use std::error::Error; use std::error::Error;
use std::fs::OpenOptions; use std::fs::OpenOptions;
@ -11,7 +12,7 @@ use symphonia::core::probe::{Hint, ProbeResult};
use symphonia::core::meta::StandardVisualKey; use symphonia::core::meta::StandardVisualKey;
use symphonia::core::formats::FormatReader; use symphonia::core::formats::FormatReader;
pub fn load_song(path: &Path) -> Result<ProbeResult, LoadError> { pub fn load_song(path: &Path) -> Result<(File, ProbeResult), LoadError> {
let probe = default::get_probe(); let probe = default::get_probe();
let file = OpenOptions::new() let file = OpenOptions::new()
@ -19,16 +20,24 @@ pub fn load_song(path: &Path) -> Result<ProbeResult, LoadError> {
.write(false) .write(false)
.open(path) .open(path)
.map_err(LoadError::OpenError)?; .map_err(LoadError::OpenError)?;
let media_source_stream = MediaSourceStream::new(Box::new(file), Default::default()); let media_source_stream = MediaSourceStream::new(
Box::new(
file.try_clone()
.map_err(LoadError::OpenError)?
),
Default::default()
);
let ext_hint = path.extension() let ext_hint = path.extension()
.and_then(OsStr::to_str) .and_then(OsStr::to_str)
.map(|ext| { .map_or_else(
let mut h = Hint::new(); Hint::new,
h.with_extension(ext); |ext| {
h let mut h = Hint::new();
}) h.with_extension(ext);
.unwrap_or_else(Hint::new); h
}
);
probe.format( probe.format(
&ext_hint, &ext_hint,
@ -36,6 +45,7 @@ pub fn load_song(path: &Path) -> Result<ProbeResult, LoadError> {
&Default::default(), &Default::default(),
&Default::default(), &Default::default(),
).map_err(LoadError::SymphoniaError) ).map_err(LoadError::SymphoniaError)
.map(|fr| (file, fr))
} }
pub fn extract_cover(format: &mut dyn FormatReader) -> Option<DynamicImage>{ pub fn extract_cover(format: &mut dyn FormatReader) -> Option<DynamicImage>{

View File

@ -1,3 +1,7 @@
use std::io::Seek;
use crate::load_song::LoadError;
use crate::model::load_song;
use std::path::Path;
use image::GenericImageView; use image::GenericImageView;
use core::ops::RangeInclusive; use core::ops::RangeInclusive;
use iced_native::widget::text_input::Value; use iced_native::widget::text_input::Value;
@ -11,7 +15,6 @@ use std::time::Duration;
use crate::styles::Theme; use crate::styles::Theme;
use crate::controls::Controls; use crate::controls::Controls;
use image::DynamicImage; use image::DynamicImage;
use symphonia::core::formats::FormatReader;
use iced::widget::text_input; use iced::widget::text_input;
use iced::widget::scrollable; use iced::widget::scrollable;
@ -57,15 +60,20 @@ impl LyricEvent {
} }
impl Editing { impl Editing {
pub fn new(mut song: Box<dyn FormatReader>) -> (Self, Command<Message>) { pub fn new(song_path: &Path) -> Result<(Self, Command<Message>), LoadError> {
let cover = extract_cover(song.as_mut()); let (mut file, fr) = load_song(song_path)?;
let mut fr = fr.format;
let cover = extract_cover(fr.as_mut());
let theme = cover.as_ref() let theme = cover.as_ref()
.map(|cover| { .map_or_else(
Theme::from_palette( Theme::default,
Palette::generate(cover) |cover|
) Theme::from_palette(
}).unwrap_or_else(Theme::default); &Palette::generate(cover)
),
);
let cover = cover.map(|cover| { let cover = cover.map(|cover| {
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
@ -80,7 +88,10 @@ impl Editing {
cover.to_bgra8().into_raw(), cover.to_bgra8().into_raw(),
)); ));
let (controls, cmd) = Controls::new(song); // Reset file handle and drop the format reader
file.rewind().map_err(LoadError::OpenError)?;
let (controls, cmd) = Controls::new(file);
let mut lyrics = Vec::with_capacity(70); let mut lyrics = Vec::with_capacity(70);
lyrics.push(Lyric::new()); lyrics.push(Lyric::new());
@ -92,29 +103,26 @@ impl Editing {
controls, theme, cached_resized_bg, lyrics, controls, theme, cached_resized_bg, lyrics,
}; };
(editor, cmd) Ok((editor, cmd))
} }
pub fn update(&mut self, message: Message) -> Command<Message> { pub fn update(&mut self, message: Message) -> Command<Message> {
let mut command = None; let mut command = None;
match message { match message {
Message::LyricEvent { line_no, kind: LyricEvent::LyricChanged(newval) } => { Message::LyricEvent { line_no, kind: LyricEvent::LyricChanged(newval) } => {
self.lyrics[line_no].value = newval self.lyrics[line_no].value = newval;
}, },
Message::LyricEvent { line_no, kind: LyricEvent::TimestampChanged(newval) } => { Message::LyricEvent { line_no, kind: LyricEvent::TimestampChanged(newval) } => {
self.lyrics[line_no].timestamp_update(newval) self.lyrics[line_no].timestamp_update(newval);
}, },
Message::LyricEvent { line_no, kind: LyricEvent::LineAdvanced } => { Message::LyricEvent { line_no, kind: LyricEvent::LineAdvanced } => {
self.advance_line(line_no, self.controls.position()) self.advance_line(line_no, self.controls.position())
}, },
Message::PasteSent => { Message::PasteSent => {
command = Some(clipboard::read(|clip| command = Some(clipboard::read(|clip| clip.map_or(
if let Some(clip) = clip { Message::Null,
Message::PasteRead(clip) Message::PasteRead,
} else { )));
Message::Null
}
));
}, },
Message::PasteRead(clip_text) => { Message::PasteRead(clip_text) => {
let clip_pasted_len = clip_text.chars() let clip_pasted_len = clip_text.chars()
@ -122,11 +130,11 @@ impl Editing {
.count(); .count();
if let Some(line) = self.current_line_mut() { if let Some(line) = self.current_line_mut() {
line.value.truncate(line.value.len() - clip_pasted_len); line.value.truncate(line.value.len() - clip_pasted_len);
self.insert_text(clip_text); self.insert_text(&clip_text);
} }
}, },
Message::ControlsEvent(e) => { Message::ControlsEvent(e) => {
self.controls.handle_event(e) self.controls.handle_event(e);
}, },
Message::Null | Message::Null |
Message::PromptForFile | Message::PromptForFile |
@ -180,7 +188,7 @@ impl Editing {
self.controls.is_playing() self.controls.is_playing()
} }
pub fn insert_text(&mut self, text: String) { pub fn insert_text(&mut self, text: &str) {
let mut pieces = text.trim_end() let mut pieces = text.trim_end()
.split('\n') .split('\n')
@ -212,7 +220,7 @@ impl Lyric {
} }
pub fn new_with_value(val: String) -> Self { pub fn new_with_value(val: String) -> Self {
Lyric { Self {
main_state: text_input::State::new(), main_state: text_input::State::new(),
timestamp_state: text_input::State::new(), timestamp_state: text_input::State::new(),
timestamp: Duration::ZERO, timestamp: Duration::ZERO,

View File

@ -19,7 +19,7 @@ pub enum Model {
const MAX_TICKS: usize = 900; const MAX_TICKS: usize = 900;
impl Model { impl Model {
pub const DEFAULT: Self = Model::FilePicker { tick: 0 }; pub const DEFAULT: Self = Self::FilePicker { tick: 0 };
pub fn update(&mut self, message: Message) -> Command<Message> { pub fn update(&mut self, message: Message) -> Command<Message> {
match self { match self {
@ -31,10 +31,17 @@ impl Model {
}, },
Message::FileOpened(path) => { Message::FileOpened(path) => {
println!("File opened! {}", path.display()); println!("File opened! {}", path.display());
let song = load_song(&path).unwrap().format; match Editing::new(&path) {
let (editing, cmd) = Editing::new(song); Ok((editing, cmd)) => {
*self = Self::Editing(editing); *self = Self::Editing(editing);
cmd cmd
},
Err(e) => {
eprintln!("yikeys! Problem opening doodad: {}", e);
//TODO! Report the error on the file loader
Command::none()
}
}
}, },
Message::PromptForFile => { Message::PromptForFile => {
let show_dialog = AsyncFileDialog::new() let show_dialog = AsyncFileDialog::new()
@ -42,11 +49,10 @@ impl Model {
.set_title("Select a song") .set_title("Select a song")
.pick_file(); .pick_file();
let to_message = |handle: Option<FileHandle>| if let Some(h) = handle { let to_message = |handle: Option<FileHandle>| handle.map_or(
Message::FileOpened(h.path().to_owned()) Message::Null,
} else { |h| Message::FileOpened(h.path().to_owned()),
Message::Null );
};
Command::perform(show_dialog, to_message) Command::perform(show_dialog, to_message)
}, },

View File

@ -20,7 +20,7 @@ pub struct Palette {
impl Palette { impl Palette {
pub fn generate(img: &DynamicImage) -> Self { pub fn generate(img: &DynamicImage) -> Self {
let _thumb; let thumb;
// Scale the image down if it's too big // Scale the image down if it's too big
let thumb = if img.width() * img.height() > MAX_SIZE_PIXELS { let thumb = if img.width() * img.height() > MAX_SIZE_PIXELS {
@ -31,8 +31,8 @@ impl Palette {
let new_width = (ratio * RESIZE_TARGET_PIXELS).sqrt(); let new_width = (ratio * RESIZE_TARGET_PIXELS).sqrt();
let new_height = RESIZE_TARGET_PIXELS / new_width; let new_height = RESIZE_TARGET_PIXELS / new_width;
_thumb = img.thumbnail(new_width as u32, new_height as u32); thumb = img.thumbnail(new_width as u32, new_height as u32);
&_thumb &thumb
} else { } else {
img img
}; };
@ -45,7 +45,7 @@ impl Palette {
.collect(); .collect();
// Generate histogram // Generate histogram
let histogram = exo_img.iter().cloned().collect(); let histogram = exo_img.iter().copied().collect();
// Generate raw palette // Generate raw palette
let colorspace = SimpleColorSpace::default(); let colorspace = SimpleColorSpace::default();
@ -81,7 +81,7 @@ impl Palette {
} }
} }
pub fn dominant_color(&self) -> &Rgb<u8> { pub fn dominant_color(&self) -> Rgb<u8> {
let max_index = self.color_frequencies let max_index = self.color_frequencies
.iter() .iter()
.enumerate() .enumerate()
@ -89,6 +89,6 @@ impl Palette {
.unwrap() .unwrap()
.0; .0;
&self.raw_colors[max_index] self.raw_colors[max_index]
} }
} }

View File

@ -1,7 +1,7 @@
use std::fs::File;
use std::time::Instant; use std::time::Instant;
use core::time::Duration; use core::time::Duration;
use rodio::Decoder; use rodio::Decoder;
use symphonia::core::formats::FormatReader;
use rodio::source::Buffered; use rodio::source::Buffered;
use rodio::OutputStream; use rodio::OutputStream;
use rodio::Sink; use rodio::Sink;
@ -9,7 +9,7 @@ use rodio::Source;
use std::fmt; use std::fmt;
pub type Song = Buffered<Decoder<std::io::Empty>>; pub type Song = Buffered<Decoder<File>>;
pub struct Player { pub struct Player {
// [Buffered] is a pointer to a linked-list representation of the song, and so cloning // [Buffered] is a pointer to a linked-list representation of the song, and so cloning
@ -34,15 +34,15 @@ impl Player {
/// task, this DOES NOT COMPUTE THE DURATION. All calculations that require a /// task, this DOES NOT COMPUTE THE DURATION. All calculations that require a
/// duration assume a duration of 2:30s until a duration is manually calculated with /// duration assume a duration of 2:30s until a duration is manually calculated with
/// [`compute_duration()`] AND passed back into [`set_duration()`]. /// [`compute_duration()`] AND passed back into [`set_duration()`].
pub fn new(song: Box<dyn FormatReader>) -> Result<Self, PlayerError> { pub fn new(song: File) -> Result<Self, PlayerError> {
let song = Decoder::new_from_format_reader(song) let song = Decoder::new(song)
.map_err(PlayerError::Decoder)? .map_err(PlayerError::Decoder)?
.buffered(); .buffered();
let duration = Duration::from_secs(150); let duration = Duration::from_secs(150);
let mut player = Player { let mut player = Self {
sink: None, sink: None,
start_position: Duration::ZERO, start_position: Duration::ZERO,
playback_started: None, playback_started: None,
@ -172,8 +172,7 @@ impl Player {
let was_stopped = self.sink let was_stopped = self.sink
.as_mut() .as_mut()
.map(|(s, _)| s.is_paused() || s.empty()) .map_or(false, |(s, _)| s.is_paused() || s.empty());
.unwrap_or(false);
let song = self.song.clone(); let song = self.song.clone();
if let Some(sink) = self.try_set_sink()? { if let Some(sink) = self.try_set_sink()? {
@ -244,7 +243,7 @@ impl Player {
/// Technical Details: Currently, this involves decoding and inefficiently counting /// Technical Details: Currently, this involves decoding and inefficiently counting
/// the number of samples in the song. Hopefully, we'll be able to do this more /// the number of samples in the song. Hopefully, we'll be able to do this more
/// efficiently in the future, pending mostly on /// efficiently in the future, pending mostly on
/// https://github.com/RustAudio/rodio/issues/405 /// <https://github.com/RustAudio/rodio/issues/405>
pub fn compute_duration(&self) -> impl FnOnce() -> Duration { pub fn compute_duration(&self) -> impl FnOnce() -> Duration {
let sample_rate = self.song.sample_rate() as u64; let sample_rate = self.song.sample_rate() as u64;
let n_channels = self.song.channels() as u64; let n_channels = self.song.channels() as u64;

View File

@ -26,7 +26,7 @@ enum Subtype {
use Subtype::*; use Subtype::*;
impl Theme { impl Theme {
pub fn from_palette(palette: Palette) -> Self { pub fn from_palette(palette: &Palette) -> Self {
let base_color = img_color_to_iced(palette.dominant_color()); let base_color = img_color_to_iced(palette.dominant_color());
let luma = relative_lum(base_color); let luma = relative_lum(base_color);
let text_color = if luma > 0.2 { let text_color = if luma > 0.2 {
@ -37,20 +37,20 @@ impl Theme {
} else { } else {
Color::WHITE Color::WHITE
}; };
Theme { Self {
subtype: Base, subtype: Base,
base_color, text_color, base_color, text_color,
} }
} }
pub fn reduced_text_color(&self) -> Color { pub const fn reduced_text_color(&self) -> Color {
Color { Color {
a: 0.7, a: 0.7,
..self.text_color ..self.text_color
} }
} }
pub fn active_lyric(&self, active: bool) -> Self { pub const fn active_lyric(&self, active: bool) -> Self {
if active { if active {
self.set_subtype(ActiveLyric) self.set_subtype(ActiveLyric)
} else { } else {
@ -58,8 +58,8 @@ impl Theme {
} }
} }
fn set_subtype(&self, subtype: Subtype) -> Self { const fn set_subtype(&self, subtype: Subtype) -> Self {
Theme { Self {
subtype, subtype,
..*self ..*self
} }
@ -68,7 +68,7 @@ impl Theme {
impl Default for Theme { impl Default for Theme {
fn default() -> Self { fn default() -> Self {
Theme { Self {
base_color: Color {r: 236. / 255., g: 63. / 255., b: 53. / 255., a: 1.}, base_color: Color {r: 236. / 255., g: 63. / 255., b: 53. / 255., a: 1.},
text_color: Color {r: 1., g: 1., b: 1., a: 1.}, text_color: Color {r: 1., g: 1., b: 1., a: 1.},
subtype: Base, subtype: Base,
@ -120,7 +120,7 @@ impl text_input::StyleSheet for Theme {
} }
} }
fn img_color_to_iced(color: &Rgb<u8>) -> Color { fn img_color_to_iced(color: Rgb<u8>) -> Color {
Color { Color {
r: color[0] as f32 / 255., r: color[0] as f32 / 255.,
g: color[1] as f32 / 255., g: color[1] as f32 / 255.,