From 6d36616d814c12f5225093aef0af5a096bc08ca4 Mon Sep 17 00:00:00 2001 From: Sheldon Knuth Date: Tue, 2 Jul 2019 11:45:28 +0800 Subject: [PATCH] add no-audio feature while constructing AudioFrontend with no_audio(). --- voxygen/src/audio/base.rs | 56 +++++++++++++++++++++++++-------------- voxygen/src/audio/mod.rs | 28 +++++++++++--------- voxygen/src/main.rs | 4 +-- 3 files changed, 53 insertions(+), 35 deletions(-) diff --git a/voxygen/src/audio/base.rs b/voxygen/src/audio/base.rs index fd04a0f8f7..648f26c2ef 100644 --- a/voxygen/src/audio/base.rs +++ b/voxygen/src/audio/base.rs @@ -2,7 +2,7 @@ use crate::settings::{AudioSettings, Settings}; use common::assets::{load_from_path, read_from_assets}; use crossbeam::{ atomic::AtomicCell, - channel::{unbounded, Receiver, Sender}, + channel::{unbounded, Sender}, queue::SegQueue, sync::{ShardedLock, WaitGroup}, }; @@ -23,6 +23,10 @@ trait StereoMode { fn set_stereo(tx: Sender) -> Self; } +trait DebugMode { + fn set_no_audio(tx: Sender) -> Self; +} + #[derive(Debug)] pub enum SinkError { SinkNotMatch, @@ -32,6 +36,7 @@ pub enum SinkError { pub enum Genre { Bgm, Sfx, + None, } #[derive(Debug)] @@ -78,6 +83,7 @@ impl AudioPlayer { match genre { Genre::Bgm => AudioPlayer::set_mono(tx), Genre::Sfx => unimplemented!(), + Genre::None => AudioPlayer::set_no_audio(tx), } } @@ -182,10 +188,19 @@ impl MonoMode for AudioPlayer { } } +impl DebugMode for AudioPlayer { + /// Don't load `rodio` for `no-audio` feature. + fn set_no_audio(tx: Sender) -> Self { + Self { + event_loop: EventLoop::new(), + paused: AtomicCell::new(true), + tx, + } + } +} + /// TODO: Implement treeview and modellist widgets for GUI design. pub struct Jukebox { - // display the current song. - //current_song: RefCell>, genre: AtomicCell, pub(crate) player: AudioPlayer, pub(crate) device: AudioDevice, @@ -193,7 +208,7 @@ pub struct Jukebox { impl Jukebox { pub(crate) fn new(genre: Genre) -> Self { - let (tx, rx) = unbounded(); + let (tx, _rx) = unbounded(); Self { genre: AtomicCell::new(genre), player: AudioPlayer::new(genre, tx), @@ -201,18 +216,14 @@ impl Jukebox { } } - //pub(crate) fn update(&mut self) { - // if self.mono.stream.empty() { - // let index = rand::random::() % self.soundtracks.len(); - // self.mono.play_from(&self.soundtracks[index]); - // } - //} - - /// Listen by Conrod. - pub(crate) fn update(&mut self, msg: AudioPlayerMsg) {} + // TODO: The `update` function should associate with `conrod` to visualise the audio playlist + // and settings. + pub(crate) fn update(&mut self, msg: AudioPlayerMsg) { + unimplemented!() + } /// Display the current genre. - pub(crate) fn get_genre(self) -> Genre { + pub(crate) fn get_genre(&self) -> Genre { self.genre.load() } } @@ -356,11 +367,6 @@ pub(crate) fn get_default_device() -> String { .name() } -/// Returns vec of devices -fn list_devices_raw() -> Vec { - rodio::output_devices().collect() -} - /// Load the audio file directory selected by genre. pub(crate) fn load_soundtracks(genre: &Genre) -> Vec { match *genre { @@ -398,6 +404,10 @@ pub(crate) fn load_soundtracks(genre: &Genre) -> Vec { soundtracks } + Genre::None => { + let empty_list = Vec::new(); + empty_list + } } } @@ -408,5 +418,11 @@ pub(crate) fn select_random_music(genre: &Genre) -> String { } fn send_msg(tx: &mut Sender, msg: AudioPlayerMsg) { - tx.try_send(msg); + tx.try_send(msg) + .expect("Failed on attempting to send a message into audio channel."); +} + +/// Returns vec of devices +fn list_devices_raw() -> Vec { + rodio::output_devices().collect() } diff --git a/voxygen/src/audio/mod.rs b/voxygen/src/audio/mod.rs index f016d8b829..f6a8b2fe36 100644 --- a/voxygen/src/audio/mod.rs +++ b/voxygen/src/audio/mod.rs @@ -1,16 +1,8 @@ pub mod base; -use base::*; -use crossbeam::{ - channel::{unbounded, Receiver, Sender}, - queue::{PopError, SegQueue}, -}; -use std::thread; +use base::{Genre, Jukebox}; pub struct AudioFrontend { pub(crate) model: Jukebox, - // mpsc sender and receiver used for audio playback threads. - //tx_thread: mpsc::Sender, - //rx_thread: mpsc::Receiver, } impl AudioFrontend { @@ -24,10 +16,20 @@ impl AudioFrontend { pub(crate) fn play(&mut self) { let path = base::select_random_music(&Genre::Bgm); - if self.model.player.is_paused() { - self.model.player.resume(); - } else { - self.model.player.load(&path); + match self.model.player.is_paused() { + true => match self.model.get_genre() { + Genre::Bgm => self.model.player.resume(), + Genre::Sfx => unimplemented!(), // TODO: add support for sound effects. + Genre::None => (), + }, + false => self.model.player.load(&path), + } + } + + /// Construct in `no-audio` mode for debugging. + pub(crate) fn no_audio() -> Self { + Self { + model: Jukebox::new(Genre::None), } } } diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 283179f074..8706ee88d4 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -42,7 +42,7 @@ impl GlobalState { } pub fn maintain(&mut self) { - // TODO: fix this issue. + // TODO: Maintain both `Bgm` and `Sfx` audio threads. self.audio.play(); } } @@ -80,7 +80,7 @@ fn main() { // Set up the global state. let settings = Settings::load(); let mut global_state = GlobalState { - audio: AudioFrontend::new(), + audio: AudioFrontend::new(), // TODO: Provide `AudioFrontend::no_audio()` feature during initialisation, the config will be stored in `ron` object list. window: Window::new(&settings).expect("Failed to create window!"), settings, };