play_at implemented

This commit is contained in:
Justine 2024-08-12 15:25:40 +02:00
parent c2591bc2a2
commit fdceee8e54
6 changed files with 192 additions and 135 deletions

102
Cargo.lock generated
View File

@ -338,12 +338,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "extended"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365"
[[package]] [[package]]
name = "ffmpeg-next" name = "ffmpeg-next"
version = "7.0.4" version = "7.0.4"
@ -1031,28 +1025,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"symphonia-bundle-flac",
"symphonia-bundle-mp3", "symphonia-bundle-mp3",
"symphonia-codec-aac",
"symphonia-codec-adpcm",
"symphonia-codec-pcm",
"symphonia-codec-vorbis",
"symphonia-core",
"symphonia-format-isomp4",
"symphonia-format-riff",
"symphonia-metadata",
]
[[package]]
name = "symphonia-bundle-flac"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97"
dependencies = [
"log",
"symphonia-core", "symphonia-core",
"symphonia-metadata", "symphonia-metadata",
"symphonia-utils-xiph",
] ]
[[package]] [[package]]
@ -1067,48 +1042,6 @@ dependencies = [
"symphonia-metadata", "symphonia-metadata",
] ]
[[package]]
name = "symphonia-codec-aac"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70"
dependencies = [
"lazy_static",
"log",
"symphonia-core",
]
[[package]]
name = "symphonia-codec-adpcm"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f"
dependencies = [
"log",
"symphonia-core",
]
[[package]]
name = "symphonia-codec-pcm"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b"
dependencies = [
"log",
"symphonia-core",
]
[[package]]
name = "symphonia-codec-vorbis"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30"
dependencies = [
"log",
"symphonia-core",
"symphonia-utils-xiph",
]
[[package]] [[package]]
name = "symphonia-core" name = "symphonia-core"
version = "0.5.4" version = "0.5.4"
@ -1122,31 +1055,6 @@ dependencies = [
"log", "log",
] ]
[[package]]
name = "symphonia-format-isomp4"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844"
dependencies = [
"encoding_rs",
"log",
"symphonia-core",
"symphonia-metadata",
"symphonia-utils-xiph",
]
[[package]]
name = "symphonia-format-riff"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50"
dependencies = [
"extended",
"log",
"symphonia-core",
"symphonia-metadata",
]
[[package]] [[package]]
name = "symphonia-metadata" name = "symphonia-metadata"
version = "0.5.4" version = "0.5.4"
@ -1159,16 +1067,6 @@ dependencies = [
"symphonia-core", "symphonia-core",
] ]
[[package]]
name = "symphonia-utils-xiph"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe"
dependencies = [
"symphonia-core",
"symphonia-metadata",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.73" version = "2.0.73"

View File

@ -8,6 +8,6 @@ file-format = "0.25.0"
metadata = "0.1.9" metadata = "0.1.9"
rand = "0.8.5" rand = "0.8.5"
regex = "1.10.6" regex = "1.10.6"
rodio = { version = "0.19.0", features = ["symphonia-all"] } rodio = "0.19.0"
serde = { version = "1.0.206", features = ["derive"] } serde = { version = "1.0.206", features = ["derive"] }
serde_yaml = "0.9.34" serde_yaml = "0.9.34"

View File

@ -1,20 +0,0 @@
---
songs:
- title: Big Cheese
artist: Nirvana
album: Bleach
track: 12
duration:
secs: 221
nanos: 0
cover_path: /home/justine/NAS/Musique/A_classer/Bleach/cover.jpg
path: /home/justine/NAS/Musique/A_classer/Bleach/12 Big Cheese.mp3
- title: Dods...
artist: Galaverna
album: Dodsdans
track: 1
duration:
secs: 148
nanos: 0
cover_path: /home/justine/NAS/Musique/Folk/Galaverna - Dodsdans/cover.jpg
path: /home/justine/NAS/Musique/Folk/Galaverna - Dodsdans/Galaverna - Dodsdans - 01 Dods....flac

View File

@ -0,0 +1,156 @@
///Contains everything needed to play music.
///The player is akin to a virtual cassette player, where the audio files would be cassettes themselves,
///stored inside the playlist.
pub mod audioplayer {
use std::fs::File;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::time::Duration;
use rodio::{Decoder, OutputStream, Sink, Source};
use std::error::Error;
use std::fmt;
use crate::playlist::playlist::*;
use crate::songmeta::songmeta::*;
use std::io::{Read, Seek};
//-----------------------------------Errors
#[derive(Debug, Clone)]
pub enum PlayerError {
Something,
}
///Main error container for the player.
impl fmt::Display for PlayerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PlayerError::Something => write!(f, "Uh-oh"),
}
}
}
impl Error for PlayerError {}
//-----------------------------------------Structs
pub struct AudioPlayer {
///A facility for controlling the playing of sound.
pub sink: Sink,
///A handle to the sound device. Must live as long as the sink.
stream: OutputStream,
///List of songs to pick from.
pub playlist: Playlist,
///If true, the player will loop back to the beginning of the playlist when it's done
pub repeating: bool,
///Stores the current state of the player, can be used as a source of truth for an UI.
pub state: PlayerState,
}
//-----------------------------------Enums
#[derive(Debug)]
pub enum PlayerState {
Playing,
Paused,
Stopped,
}
//-------------------------------------Impls
impl AudioPlayer {
///Returns a new empty player to the default device.
pub fn new() -> Result<Self, Box<dyn Error>> {
let (stream, stream_handle) = OutputStream::try_default()?;
let sink = Sink::try_new(&stream_handle)?;
let playlist = Playlist::new();
let me = Self {
sink: sink,
stream: stream,
playlist: playlist,
repeating: false,
state: PlayerState::Stopped,
};
Ok(me)
}
///Plays all files in the playlist starting from index.
pub fn play_at(&mut self, index: usize) -> Result<(), Box<dyn Error>> {
self.playlist.check_index(index.clone())?;
self.sink.clear();
self.state = PlayerState::Paused;
for song in &self.playlist.songs[index..] {
let file = BufReader::new(File::open(&song.path)?);
let source = Decoder::new(file)?;
self.sink.append(source);
}
self.sink.play();
self.state = PlayerState::Playing;
return Ok(());
}
fn get_current_song(&self) {
unimplemented!();
}
fn skip_forward(&mut self) {
unimplemented!();
}
fn skip_backwards(&mut self) {
unimplemented!();
}
fn pause(&mut self) {
unimplemented!();
}
fn unpause(&mut self) {
unimplemented!();
}
fn get_pos(&self) {
unimplemented!();
}
fn set_vol(&mut self, vol: f32) {
unimplemented!();
}
fn get_vol(&mut self) {
unimplemented!();
}
fn goto(&mut self, index: usize) {
unimplemented!();
}
fn press_shuffle(&mut self) {
unimplemented!();
}
fn press_repeat(&mut self) {
unimplemented!();
}
fn seek(&mut self, goto: Duration) {
unimplemented!();
}
fn stop(&mut self) {
unimplemented!();
}
fn load_file(&mut self) {
unimplemented!();
}
fn load_folder(&mut self) {
unimplemented!();
}
}
}

View File

@ -4,14 +4,35 @@ use crate::songmeta::songmeta::*;
pub mod playlist; pub mod playlist;
use crate::playlist::playlist::*; use crate::playlist::playlist::*;
pub mod audioplayer;
use crate::audioplayer::audioplayer::*;
use std::thread::sleep;
use std::time::Duration;
fn main() { fn main() {
//let mysong = SongMeta::frompath(&String::from("/home/justine/NAS/Musique/A_classer/Bleach/12 Big Cheese.mp3")).unwrap(); let mysong = SongMeta::frompath(&String::from("/home/justine/NAS/Musique/A_classer/Bleach/12 Big Cheese.mp3")).unwrap();
//let mysong2 = SongMeta::frompath(&String::from("/home/justine/NAS/Musique/Folk/Galaverna - Dodsdans/Galaverna - Dodsdans - 01 Dods....flac")).unwrap(); let mysong2 = SongMeta::frompath(&String::from("/home/justine/NAS/Musique/Folk/Galaverna - Dodsdans/Galaverna - Dodsdans - 01 Dods....flac")).unwrap();
//let mysong3 = SongMeta::frompath(&String::from("/home/justine/NAS/Musique/Jeux/Superliminal/Matt Christensen - Superliminal/12. Astral.mp3")).unwrap(); let mysong3 = SongMeta::frompath(&String::from("/home/justine/NAS/Musique/Jeux/Superliminal/Matt Christensen - Superliminal/12. Astral.mp3")).unwrap();
let playlist = Playlist::from_file("./myplaylist.yml", true); let mut playlist = Playlist::new();
playlist.songs.push(mysong);
playlist.songs.push(mysong2);
playlist.songs.push(mysong3);
let mut player = AudioPlayer::new().unwrap();
player.playlist = playlist;
player.play_at(0).unwrap();
println!("{:?} {:?} {:?}", player.state, player.sink.volume(), player.sink.is_paused());
sleep(Duration::from_secs(10));
player.play_at(2).unwrap();
loop {
dbg!(player.sink.get_pos());
}
dbg!(playlist);
} }

View File

@ -48,6 +48,7 @@ pub mod playlist {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Playlist { pub struct Playlist {
pub songs: Vec<SongMeta>, pub songs: Vec<SongMeta>,
pub shuffled: bool,
} }
impl Playlist { impl Playlist {
@ -55,6 +56,7 @@ pub mod playlist {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
songs: vec![], songs: vec![],
shuffled: false,
} }
} }
@ -125,21 +127,19 @@ pub mod playlist {
} }
///Checks if a number is a valid index in this playlist. ///Checks if a number is a valid index in this playlist.
pub fn check_index(&self, index: usize) -> bool { pub fn check_index(&self, index: usize) -> Result<(), Box<dyn Error>> {
if self.songs.len() == 0 { if self.songs.len() == 0 {
return false; return Err(Box::new(PlaylistError::IndexNotFound));
} }
if index > (self.songs.len() - 1) { if index > (self.songs.len() - 1) {
return false; return Err(Box::new(PlaylistError::IndexNotFound));
} }
return true; return Ok(());
} }
///Removes a song at index (if possible) ///Removes a song at index (if possible)
pub fn remove(&mut self, index: usize) -> Result<(), Box<dyn Error>> { pub fn remove(&mut self, index: usize) -> Result<(), Box<dyn Error>> {
if !self.check_index(index.clone()) { self.check_index(index.clone())?;
return Err(Box::new(PlaylistError::IndexNotFound));
}
self.songs.remove(index); self.songs.remove(index);
return Ok(()); return Ok(());
} }
@ -151,6 +151,7 @@ pub mod playlist {
return; return;
} }
self.songs.shuffle(&mut thread_rng()); self.songs.shuffle(&mut thread_rng());
self.shuffled = true;
} }
///Sorts the playlist by artist, album, trackorder, title ///Sorts the playlist by artist, album, trackorder, title
@ -162,6 +163,7 @@ pub mod playlist {
.then_with(|| a.track.cmp(&b.track)) .then_with(|| a.track.cmp(&b.track))
.then_with(|| a.title.cmp(&b.title)) .then_with(|| a.title.cmp(&b.title))
}); });
self.shuffled = false;
} }
} }
} }