diff --git a/src/main.rs b/src/main.rs index 8b50999..f21afa7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,14 +5,19 @@ pub mod playlist; use crate::playlist::playlist::*; fn main() { - let mysong = SongMeta::frompath(&String::from("/home/justine/NAS/Musique/A_classer/Bleach/12 Big Cheese.mp3")); - let mysong2 = SongMeta::frompath(&String::from("/home/justine/NAS/Musique/Folk/Galaverna - Dodsdans/Galaverna - Dodsdans - 01 Dods....flac")); + 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 playlist = Playlist::from_file(&String::from("./cool.yml")); - //playlist.remove(0).unwrap(); - let playlist = Playlist::from_file(&String::from("./cool.yml")); + let playlist = Playlist { + songs: vec![mysong, mysong2], + }; - dbg!(playlist); + assert_eq!(false, playlist.check_index(2)); + let playlist = Playlist::new(); + assert_eq!(false, playlist.check_index(0)); + assert_eq!(false, playlist.check_index(10)); } diff --git a/src/playlist.rs b/src/playlist.rs index b4ed2d7..8b52f92 100644 --- a/src/playlist.rs +++ b/src/playlist.rs @@ -99,7 +99,10 @@ pub mod playlist { ///Checks if a number is a valid index in this playlist. pub fn check_index(&self, index: usize) -> bool { - if index > self.songs.len() { + if self.songs.len() == 0 { + return false; + } + if index > (self.songs.len() - 1) { return false; } return true; diff --git a/src/proto.rs b/src/proto.rs index 5bf274b..49fd0e9 100644 --- a/src/proto.rs +++ b/src/proto.rs @@ -7,12 +7,37 @@ use rodio::{Decoder, OutputStream, Sink, Source}; //-----------------------------------------Structs +//Gère tout ce qui est lecture. C'est le lui le "lecteur cd" dans l'histoire. +//Features : play / pause / précédent / suivant / shuffle on/off / mode repeat +//Vidage playlist sans interruption de la chanson en cours +//Poignée de lecture (seek) +//Le "lecteur cd" affiche : volume, poignée de lecture, metadonnées de la chanson, index de la chanson dans la playlist +// Il est entièrement détaché de l'interface et doit pouvoir exister en mode headless +// Ne pas mélanger les fonctionnalités entre les objets : la playlist doit pouvoir se shuffle, ce n'est pas le player qui le fait +// Ne pas oublier qu'on est pas obligé de faire des builder, je peux très bien créer un player en lui filant des valeurs +// Je n'ai pas besoin de faire une boucle dans une fonction de mon player puisque rodio lance un thread et que je garde le sink ! struct AudioPlayer { sink: Sink, playlist: Vec, + //true si mode repeat + repeating: bool, + //false si mode repeat + shuffled: bool, + //Etat actuel du player + state: PlayerState, + //Index de la chanson actuelle dans la playlist + index: usize, + +} + +//-----------------------------------Enums +enum PlayerState { + Playing, + Paused, + Stopped, } @@ -39,38 +64,84 @@ impl AudioPlayer { Self { sink: sink, playlist: playlist, - } - } - - ///Creates a new player from an existing playlist. - ///Does not consume the playlist. - fn from_playlist(playlist: &Playlist) -> Self { - let (_stream, stream_handle) = OutputStream::try_default().unwrap(); - let sink = Sink::try_new(&stream_handle).unwrap(); - - Self { - sink: sink, - playlist: playlist.clone(), + repeating: false, + //false si mode repeat + shuffled: false, + //Etat actuel du player + state: PlayerState::Stopped, + index: 0, } } - ///Appends a playlist to the current one, consuming it. - fn add_playlist(&mut self, playlist: Vec) { - self.playlist.append(&mut playlist); - } + //-----------------------FONCTIONNALITES A IMPLEMENTER + //Ce sont toutes les fonctionnalités de mon player + //Ne pas oublier de bien mettre à jour les variables du player (State, shuffled, random) - //renvoie un result, avance d'une chanson + + //Charge toutes les chansons de la playlist à partir de l'index donné + //Puis lance la lecture dans le sink + //Pas besoin de valider l'index on se contente de remonter les erreurs + //Renvoie un result + fn play_at(&mut self, index: usize); + + + //Renvoie une option contenant le clone de la chanson en cours de lecture + //Ainsi que son index dans la playlist + //Ou None si pas en cours de lecture + //Pour ça, utiliser sink.len() qui donne le nombre de chanson dans la file d'attente du sink + //L'index de la chanson en cours dans la playlist correspond à la longueur de la playlist + //moins (sink.len() + 1) + + //Schéma: + // chanson en cours + // V + //playlist : [0, 1, 2, 3, 4, 5] = longueur 6 + //sink.len: | | = sink.len() = 2 + // index dans la playlist de la chanson en cours = (playlist.songs.len()) - (sink.len() + 1) + // + //Ca marche sauf si la playlist est vide auquel cas on se retrouve à -1 sur un usize... Puisque y'a pas de chanson + // à récupérer dans la playlist vu qu'elle est vide ! Donc renvoyer None au préalable si la playlist est vide + fn get_current_song(&self); + + //renvoie un result, avance d'une chanson avec sink.skip_one fn skip_forward(&mut self); - //renvoie un result, recule d'une chanson + + //renvoie un result, recule d'une chanson en pétant le sink et en le refaisant fn skip_backwards(&mut self); + //met en pause renvoie un result fn pause(&mut self); - //Enleve la pause ou lit la première chanson de la playlist renvoie un result - fn play(&mut self); + + //enlève la pause renvoie un result + fn unpause(&mut self); + + //Renvoie la position (une Duration) dans la chanson actuelle avec sink.get_pos renvoie rien + fn get_pos(&self); + //Change le volume envoie un result fn set_vol(&mut self, vol: f32); + + //Renvoie le volume + fn get_vol(&mut self); + //Saute à la chanson donnée renvoie un result - fn goto(&mut self, index: usize) -> Result<(), PlayerError>; + fn goto(&mut self, index: usize); + + //Active ou désactive le mode shuffle, mélange ou trie la playlist au besoin renvoie rien + //Correspond à un appui sur le bouton shuffle du lecteur cd + fn press_shuffle(&mut self); + + //Active ou désactive le mode repeat + //Correspond à un appui sur le bouton repeat + //Renvoie rien + fn press_repeat(&mut self); + + //Utilise try_seek sur le sink pour mettre la tête de lecture à une Duration donnée + //renvoie un result + fn seek(&mut self, goto: Duration); + + //Stoppe la lecture en cours et vide le sink renvoie rien + fn stop(&mut self); }