play_at implemented
This commit is contained in:
parent
c2591bc2a2
commit
fdceee8e54
102
Cargo.lock
generated
102
Cargo.lock
generated
@ -338,12 +338,6 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "extended"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365"
|
||||
|
||||
[[package]]
|
||||
name = "ffmpeg-next"
|
||||
version = "7.0.4"
|
||||
@ -1031,28 +1025,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"symphonia-bundle-flac",
|
||||
"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-metadata",
|
||||
"symphonia-utils-xiph",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1067,48 +1042,6 @@ dependencies = [
|
||||
"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]]
|
||||
name = "symphonia-core"
|
||||
version = "0.5.4"
|
||||
@ -1122,31 +1055,6 @@ dependencies = [
|
||||
"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]]
|
||||
name = "symphonia-metadata"
|
||||
version = "0.5.4"
|
||||
@ -1159,16 +1067,6 @@ dependencies = [
|
||||
"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]]
|
||||
name = "syn"
|
||||
version = "2.0.73"
|
||||
|
@ -8,6 +8,6 @@ file-format = "0.25.0"
|
||||
metadata = "0.1.9"
|
||||
rand = "0.8.5"
|
||||
regex = "1.10.6"
|
||||
rodio = { version = "0.19.0", features = ["symphonia-all"] }
|
||||
rodio = "0.19.0"
|
||||
serde = { version = "1.0.206", features = ["derive"] }
|
||||
serde_yaml = "0.9.34"
|
||||
|
20
cool.yml
20
cool.yml
@ -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
|
@ -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!();
|
||||
}
|
||||
}
|
||||
}
|
31
src/main.rs
31
src/main.rs
@ -4,14 +4,35 @@ use crate::songmeta::songmeta::*;
|
||||
pub mod playlist;
|
||||
use crate::playlist::playlist::*;
|
||||
|
||||
pub mod audioplayer;
|
||||
use crate::audioplayer::audioplayer::*;
|
||||
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
//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 mysong3 = SongMeta::frompath(&String::from("/home/justine/NAS/Musique/Jeux/Superliminal/Matt Christensen - Superliminal/12. Astral.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 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,6 +48,7 @@ pub mod playlist {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Playlist {
|
||||
pub songs: Vec<SongMeta>,
|
||||
pub shuffled: bool,
|
||||
}
|
||||
|
||||
impl Playlist {
|
||||
@ -55,6 +56,7 @@ pub mod playlist {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
songs: vec![],
|
||||
shuffled: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,21 +127,19 @@ pub mod 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 {
|
||||
return false;
|
||||
return Err(Box::new(PlaylistError::IndexNotFound));
|
||||
}
|
||||
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)
|
||||
pub fn remove(&mut self, index: usize) -> Result<(), Box<dyn Error>> {
|
||||
if !self.check_index(index.clone()) {
|
||||
return Err(Box::new(PlaylistError::IndexNotFound));
|
||||
}
|
||||
self.check_index(index.clone())?;
|
||||
self.songs.remove(index);
|
||||
return Ok(());
|
||||
}
|
||||
@ -151,6 +151,7 @@ pub mod playlist {
|
||||
return;
|
||||
}
|
||||
self.songs.shuffle(&mut thread_rng());
|
||||
self.shuffled = true;
|
||||
}
|
||||
|
||||
///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.title.cmp(&b.title))
|
||||
});
|
||||
self.shuffled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user