From 746715be391a43b354d4c178bddc623cc7a4a515 Mon Sep 17 00:00:00 2001 From: Emi Simpson Date: Wed, 26 Jan 2022 17:18:23 -0500 Subject: [PATCH] Redo metadata -> song pipeline Following the rejection of https://github.com/RustAudio/rodio/pull/410 --- .gitmodules | 4 --- Cargo.lock | 72 ++++++++++++++++++++++++-------------------- Cargo.toml | 4 +-- rodio | 1 - src/controls.rs | 4 +-- src/load_song.rs | 12 ++++++-- src/model/editing.rs | 19 +++++++++--- src/model/mod.rs | 15 ++++++--- src/player.rs | 8 ++--- 9 files changed, 83 insertions(+), 56 deletions(-) delete mode 160000 rodio diff --git a/.gitmodules b/.gitmodules index 40ce689..4b58eee 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ -[submodule "rodio"] - path = rodio - url = https://github.com/Alch-Emi/rodio.git - branch = new-from-format-reader [submodule "iced"] path = iced url = https://github.com/Alch-Emi/iced.git diff --git a/Cargo.lock b/Cargo.lock index 8b13d88..62a7fe6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,12 +96,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" -[[package]] -name = "arrayvec" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269d0f5e68353a7cab87f81e7c736adc008d279a36ebc6a05dfe01193a89f0c9" - [[package]] name = "arrayvec" version = "0.7.2" @@ -2693,7 +2687,9 @@ dependencies = [ [[package]] name = "rodio" -version = "0.14.0" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e" dependencies = [ "cpal", "symphonia", @@ -2970,15 +2966,16 @@ checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" [[package]] name = "symphonia" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fae959d5ea7b4cd0cd8db3b899ec4f549b0d8a298694826a36ae7e5f19d4aa6" +checksum = "a7e5f38aa07e792f4eebb0faa93cee088ec82c48222dd332897aae1569d9a4b7" dependencies = [ "lazy_static", "symphonia-bundle-flac", "symphonia-bundle-mp3", "symphonia-codec-aac", "symphonia-codec-pcm", + "symphonia-codec-vorbis", "symphonia-core", "symphonia-format-isomp4", "symphonia-format-ogg", @@ -2988,9 +2985,9 @@ dependencies = [ [[package]] name = "symphonia-bundle-flac" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b237be42d0ff1ff64c6e073aea4f93985ca51de93b8279f16a4b006e3e5997af" +checksum = "116e5412f5fb4e5d07efd6628d50d6fcd7a61ebef43d98f5012f3cf763b25d02" dependencies = [ "log", "symphonia-core", @@ -3000,9 +2997,9 @@ dependencies = [ [[package]] name = "symphonia-bundle-mp3" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f596fe16d2ae06e9404558644b61e27e2dcfee6c511f559be4699c403283fa" +checksum = "ec4d97c4a61ece4651751dddb393ebecb7579169d9e758ae808fe507a5250790" dependencies = [ "bitflags", "lazy_static", @@ -3013,9 +3010,9 @@ dependencies = [ [[package]] name = "symphonia-codec-aac" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e636422dccfb202b24f8066b8d3ebfa914bbc690dae78db52b54691ba916c3f" +checksum = "bd3d7ab37eb9b7df16ddedd7adb7cc382afe708ff078e525a14dc9b05e57558f" dependencies = [ "lazy_static", "log", @@ -3024,32 +3021,43 @@ dependencies = [ [[package]] name = "symphonia-codec-pcm" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021d8161b186bea81c7cf4a80c67c71fb53862cd9f426cd3e032ae09bdd42dec" +checksum = "ba1d54738758993546107e3a4be2c1da827f2d4489fcffee0fa47867254e44c7" dependencies = [ "log", "symphonia-core", ] [[package]] -name = "symphonia-core" -version = "0.3.0" +name = "symphonia-codec-vorbis" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1742e06f50b4a7ed7abee53433231e050a248b498cd0ae2c639c8a70b115001" +checksum = "a29ed6748078effb35a05064a451493a78038918981dc1a76bdf5a2752d441fa" 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", - "byteorder", + "bytemuck", "lazy_static", "log", ] [[package]] name = "symphonia-format-isomp4" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf3c6b6ca3347caa22d72f04cfd509f0c32683b0dbe01d0cfb63fd2726ac6da5" +checksum = "feee3a7711e7ec1b7540756f3868bbb3cbb0d1195569b9bc26471a24a02f57b5" dependencies = [ "encoding_rs", "log", @@ -3059,9 +3067,9 @@ dependencies = [ [[package]] name = "symphonia-format-ogg" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4898eef85c5a05136e1f3b5ff1afe4423cd7642c8979ed007cc8924b9a4c18c1" +checksum = "d7b2357288a79adfec532cfd86049696cfa5c58efeff83bd51687a528f18a519" dependencies = [ "log", "symphonia-core", @@ -3071,9 +3079,9 @@ dependencies = [ [[package]] name = "symphonia-format-wav" -version = "0.3.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97e863d9a912ea518dfae664292e38b2b961a1eb780251eba89b60e3905fef37" +checksum = "6d9fa5e5b420dea6763ba2547887eb1a02a142c676c5b02ed1b113a247101dad" dependencies = [ "log", "symphonia-core", @@ -3082,9 +3090,9 @@ dependencies = [ [[package]] name = "symphonia-metadata" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db5e36e38a7400f968569135e7ac0f8647de42e93905ad41c79d583aaeae565c" +checksum = "5260599daba18d8fe905ca3eb3b42ba210529a6276886632412cc74984e79b1a" dependencies = [ "encoding_rs", "lazy_static", @@ -3094,9 +3102,9 @@ dependencies = [ [[package]] name = "symphonia-utils-xiph" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47377d86d61acf4d5b1a054b8e7a7cac8266155577a5410e4d746aec6394c42a" +checksum = "6a37026c6948ff842e0bf94b4008579cc71ab16ed0ff9ca70a331f60f4f1e1e9" dependencies = [ "symphonia-core", "symphonia-metadata", diff --git a/Cargo.toml b/Cargo.toml index 1531ba2..7659e39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ blocking = "1.1.0" [dependencies.symphonia] # Music decoding and metadata parsing features = ["isomp4", "aac", "mp3"] -version = "0.3.0" +version = "0.4.0" [dependencies.iced] # Display windows & graphics @@ -50,4 +50,4 @@ path = "./iced/futures" # Playing audio default-features = false features = ["symphonia-all"] -path = "./rodio/" +version = "0.15" diff --git a/rodio b/rodio deleted file mode 160000 index 706abaf..0000000 --- a/rodio +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 706abafcadab2c0049d7a7724cae43f203ba0f67 diff --git a/src/controls.rs b/src/controls.rs index 6cdf791..de9ae57 100644 --- a/src/controls.rs +++ b/src/controls.rs @@ -1,9 +1,9 @@ +use std::fs::File; use iced::Command; use core::time::Duration; use iced::Length; use iced::Color; use iced::Point; -use symphonia::core::formats::FormatReader; use crate::player::PlayerError; use iced::canvas::event::Status; use iced::canvas::Event; @@ -39,7 +39,7 @@ use ErrorState::*; pub struct Controls(pub ErrorState); impl Controls { - pub fn new(song: Box) -> (Self, Command) { + pub fn new(song: File) -> (Self, Command) { match Player::new(song) { Ok(player) => { let duration_task = unblock(player.compute_duration()); diff --git a/src/load_song.rs b/src/load_song.rs index 1091cc9..73e60e2 100644 --- a/src/load_song.rs +++ b/src/load_song.rs @@ -1,3 +1,4 @@ +use std::fs::File; use image::DynamicImage; use std::error::Error; use std::fs::OpenOptions; @@ -11,7 +12,7 @@ use symphonia::core::probe::{Hint, ProbeResult}; use symphonia::core::meta::StandardVisualKey; use symphonia::core::formats::FormatReader; -pub fn load_song(path: &Path) -> Result { +pub fn load_song(path: &Path) -> Result<(File, ProbeResult), LoadError> { let probe = default::get_probe(); let file = OpenOptions::new() @@ -19,7 +20,13 @@ pub fn load_song(path: &Path) -> Result { .write(false) .open(path) .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() .and_then(OsStr::to_str) @@ -36,6 +43,7 @@ pub fn load_song(path: &Path) -> Result { &Default::default(), &Default::default(), ).map_err(LoadError::SymphoniaError) + .map(|fr| (file, fr)) } pub fn extract_cover(format: &mut dyn FormatReader) -> Option{ diff --git a/src/model/editing.rs b/src/model/editing.rs index 9a89918..8079006 100644 --- a/src/model/editing.rs +++ b/src/model/editing.rs @@ -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 core::ops::RangeInclusive; use iced_native::widget::text_input::Value; @@ -11,7 +15,6 @@ use std::time::Duration; use crate::styles::Theme; use crate::controls::Controls; use image::DynamicImage; -use symphonia::core::formats::FormatReader; use iced::widget::text_input; use iced::widget::scrollable; @@ -57,8 +60,11 @@ impl LyricEvent { } impl Editing { - pub fn new(mut song: Box) -> (Self, Command) { - let cover = extract_cover(song.as_mut()); + pub fn new(song_path: &Path) -> Result<(Self, Command), LoadError> { + 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() .map(|cover| { @@ -80,7 +86,10 @@ impl Editing { 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); lyrics.push(Lyric::new()); @@ -92,7 +101,7 @@ impl Editing { controls, theme, cached_resized_bg, lyrics, }; - (editor, cmd) + Ok((editor, cmd)) } pub fn update(&mut self, message: Message) -> Command { diff --git a/src/model/mod.rs b/src/model/mod.rs index d8c9a1e..04f305d 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -31,10 +31,17 @@ impl Model { }, Message::FileOpened(path) => { println!("File opened! {}", path.display()); - let song = load_song(&path).unwrap().format; - let (editing, cmd) = Editing::new(song); - *self = Self::Editing(editing); - cmd + match Editing::new(&path) { + Ok((editing, cmd)) => { + *self = Self::Editing(editing); + cmd + }, + Err(e) => { + eprintln!("yikeys! Problem opening doodad: {}", e); + //TODO! Report the error on the file loader + Command::none() + } + } }, Message::PromptForFile => { let show_dialog = AsyncFileDialog::new() diff --git a/src/player.rs b/src/player.rs index 553a216..aabb95f 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,7 +1,7 @@ +use std::fs::File; use std::time::Instant; use core::time::Duration; use rodio::Decoder; -use symphonia::core::formats::FormatReader; use rodio::source::Buffered; use rodio::OutputStream; use rodio::Sink; @@ -9,7 +9,7 @@ use rodio::Source; use std::fmt; -pub type Song = Buffered>; +pub type Song = Buffered>; pub struct Player { // [Buffered] is a pointer to a linked-list representation of the song, and so cloning @@ -34,9 +34,9 @@ impl Player { /// 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 /// [`compute_duration()`] AND passed back into [`set_duration()`]. - pub fn new(song: Box) -> Result { + pub fn new(song: File) -> Result { - let song = Decoder::new_from_format_reader(song) + let song = Decoder::new(song) .map_err(PlayerError::Decoder)? .buffered();