diff --git a/voxygen/src/audio/channel.rs b/voxygen/src/audio/channel.rs index 5dde4544fa..d4daae40e2 100644 --- a/voxygen/src/audio/channel.rs +++ b/voxygen/src/audio/channel.rs @@ -20,7 +20,7 @@ use crate::audio::{ fader::{FadeDirection, Fader}, Listener, }; -use rodio::{Device, OutputStream, OutputStreamHandle, Sample, Sink, Source, SpatialSink}; +use rodio::{OutputStreamHandle, Sample, Sink, Source, SpatialSink}; use vek::*; #[derive(PartialEq, Clone, Copy)] diff --git a/voxygen/src/audio/mod.rs b/voxygen/src/audio/mod.rs index 7f81e5aebf..b77262cf1a 100644 --- a/voxygen/src/audio/mod.rs +++ b/voxygen/src/audio/mod.rs @@ -13,7 +13,7 @@ use std::time::Duration; use tracing::warn; use common::assets; -use cpal::traits::DeviceTrait; +use cpal::traits::{DeviceTrait, HostTrait}; use rodio::{source::Source, Decoder, Device, OutputStream, OutputStreamHandle, StreamError}; use vek::*; @@ -31,9 +31,10 @@ pub struct Listener { /// Voxygen's [`GlobalState`](../struct.GlobalState.html#structfield.audio) to /// provide access to devices and playback control in-game pub struct AudioFrontend { - //pub device: String, + pub device: String, + pub device_list: Vec, + pub audio_device: Option, pub stream: Option, - //pub device_list: Vec, audio_stream: Option, sound_cache: SoundCache, @@ -46,12 +47,33 @@ pub struct AudioFrontend { impl AudioFrontend { /// Construct with given device - pub fn new(max_sfx_channels: usize) -> Self { - //let audio_device = get_device_raw(&device); + pub fn new(dev: String, max_sfx_channels: usize) -> Self { + let audio_device = get_device_raw(&dev); + let device = match get_default_device() { + Some(d) => d, + None => "".to_string(), + }; + //if let Some(this_device) = device { + //let (stream, audio_stream) = match get_stream(&device.clone().unwrap()) { + // Ok(s) => (Some(s.0), Some(s.1)), + // Err(_) => (None, None), + //}; + //} else { let (stream, audio_stream) = match get_default_stream() { Ok(s) => (Some(s.0), Some(s.1)), Err(_) => (None, None), }; + //} + //let (stream, audio_stream) = match &device { + // Some(dev) => match get_stream(&dev) { + // Ok(s) => (Some(s.0), Some(s.1)), + // Err(_) => (None, None), + // }, + // None => match get_default_stream() { + // Ok(s) => (Some(s.0), Some(s.1)), + // Err(_) => (None, None), + // }, + //}; let mut sfx_channels = Vec::with_capacity(max_sfx_channels); if let Some(audio_stream) = &audio_stream { @@ -59,8 +81,9 @@ impl AudioFrontend { }; Self { - //device, - //device_list: list_devices(), + device, + device_list: list_devices(), + audio_device, stream, audio_stream, sound_cache: SoundCache::default(), @@ -75,9 +98,9 @@ impl AudioFrontend { /// Construct in `no-audio` mode for debugging pub fn no_audio() -> Self { Self { - //device: "none".to_string(), - //device_list: Vec::new(), - //audio_device: None, + device: "".to_string(), + device_list: Vec::new(), + audio_device: None, stream: None, audio_stream: None, sound_cache: SoundCache::default(), @@ -266,11 +289,11 @@ impl AudioFrontend { } } - //// TODO: figure out how badly this will break things when it is called - //pub fn set_device(&mut self, name: String) { - // self.device = name.clone(); - // self.audio_device = get_device_raw(&name); - //} + // TODO: figure out how badly this will break things when it is called + pub fn set_device(&mut self, name: String) { + self.device = name.clone(); + self.audio_device = get_device_raw(&name); + } } ///// Returns the default audio device. @@ -281,12 +304,25 @@ impl AudioFrontend { // None => None, // } //} +pub fn get_default_device() -> Option { + match cpal::default_host().default_output_device() { + Some(x) => Some(x.name().ok()?), + None => None, + } +} /// Returns the default stream pub fn get_default_stream() -> Result<(OutputStream, OutputStreamHandle), StreamError> { rodio::OutputStream::try_default() } +/// Returns a stream on the specified device +pub fn get_stream( + device: &rodio::Device, +) -> Result<(OutputStream, OutputStreamHandle), StreamError> { + rodio::OutputStream::try_from_device(device) +} + ///// Returns a vec of the audio devices available. ///// Does not return rodio Device struct in case our audio backend changes. //pub fn list_devices() -> Vec { @@ -309,9 +345,25 @@ pub fn get_default_stream() -> Result<(OutputStream, OutputStreamHandle), Stream // }, // } //} +fn list_devices_raw() -> Vec { + match cpal::default_host().devices() { + Ok(devices) => devices.filter(|d| d.name().is_ok()).collect(), + Err(_) => { + warn!("Failed to enumerate audio output devices, audio will not be available"); + Vec::new() + }, + } +} + +fn list_devices() -> Vec { + list_devices_raw() + .iter() + .map(|x| x.name().unwrap()) + .collect() +} // -//fn get_device_raw(device: &str) -> Option { -// list_devices_raw() -// .into_iter() -// .find(|d| d.name().unwrap() == device) -//} +fn get_device_raw(device: &str) -> Option { + list_devices_raw() + .into_iter() + .find(|d| d.name().unwrap() == device) +} diff --git a/voxygen/src/audio/sfx/event_mapper/block/mod.rs b/voxygen/src/audio/sfx/event_mapper/block/mod.rs index f0004df1b8..e4ceccd17e 100644 --- a/voxygen/src/audio/sfx/event_mapper/block/mod.rs +++ b/voxygen/src/audio/sfx/event_mapper/block/mod.rs @@ -131,7 +131,9 @@ impl EventMapper for BlockEventMapper { for sounds in sounds.iter() { if !(sounds.cond)(state) { continue; - } else if sounds.sfx == SfxEvent::Birdcall && thread_rng().gen_bool(0.995) { + } else if (sounds.sfx == SfxEvent::Birdcall || sounds.sfx == SfxEvent::Owl) + && thread_rng().gen_bool(0.995) + { continue; } @@ -159,7 +161,7 @@ impl EventMapper for BlockEventMapper { // Iterate through each individual block for block in blocks { - if sounds.sfx == SfxEvent::Birdcall && thread_rng().gen_bool(0.999) { + if (sounds.sfx == SfxEvent::Birdcall || sounds.sfx == SfxEvent::Owl) && thread_rng().gen_bool(0.999) { continue; } let block_pos: Vec3 = absolute_pos + block; diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 6377d57d8a..1ccf95d029 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -319,7 +319,7 @@ pub enum Event { AdjustFigureLoDRenderDistance(u32), AdjustMusicVolume(f32), AdjustSfxVolume(f32), - //ChangeAudioDevice(String), + ChangeAudioDevice(String), ChangeMaxFPS(u32), ChangeFOV(u16), ChangeGamma(f32), @@ -2131,9 +2131,9 @@ impl Hud { settings_window::Event::MaximumFPS(max_fps) => { events.push(Event::ChangeMaxFPS(max_fps)); }, - //settings_window::Event::ChangeAudioDevice(name) => { - // events.push(Event::ChangeAudioDevice(name)); - //}, + settings_window::Event::ChangeAudioDevice(name) => { + events.push(Event::ChangeAudioDevice(name)); + }, settings_window::Event::CrosshairType(crosshair_type) => { events.push(Event::CrosshairType(crosshair_type)); }, diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index 506b0f1aa8..29ea570eda 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -291,7 +291,7 @@ pub enum Event { ChangeRenderMode(Box), AdjustMusicVolume(f32), AdjustSfxVolume(f32), - //ChangeAudioDevice(String), + ChangeAudioDevice(String), MaximumFPS(u32), CrosshairTransp(f32), CrosshairType(CrosshairType), @@ -2693,32 +2693,30 @@ impl<'a> Widget for SettingsWindow<'a> { events.push(Event::AdjustSfxVolume(new_val)); } - // Audio Device Selector - // -------------------------------------------- - // let device = &self.global_state.audio.device; - //let device_list = &self.global_state.audio.device_list; - //Text::new(&self.localized_strings.get("hud.settings.audio_device" - // )) .down_from(state.ids.sfx_volume_slider, 10.0) - // .font_size(self.fonts.cyri.scale(14)) - // .font_id(self.fonts.cyri.conrod_id) - // .color(TEXT_COLOR) - // .set(state.ids.audio_device_text, ui); + // Audio Device Selector -------------------------------------------- + let device = &self.global_state.audio.device; + let device_list = &self.global_state.audio.device_list; + Text::new(&self.localized_strings.get("hud.settings.audio_device")) + .down_from(state.ids.sfx_volume_slider, 10.0) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(state.ids.audio_device_text, ui); - //// Get which device is currently selected - //let selected = device_list.iter().position(|x| - // x.contains(device)); + // Get which device is currently selected + let selected = device_list.iter().position(|x| x.contains(device)); - //if let Some(clicked) = DropDownList::new(&device_list, selected) - // .w_h(400.0, 22.0) - // .color(MENU_BG) - // .label_color(TEXT_COLOR) - // .label_font_id(self.fonts.opensans.conrod_id) - // .down_from(state.ids.audio_device_text, 10.0) - // .set(state.ids.audio_device_list, ui) - //{ - // let new_val = device_list[clicked].clone(); - // events.push(Event::ChangeAudioDevice(new_val)); - //} + if let Some(clicked) = DropDownList::new(&device_list, selected) + .w_h(400.0, 22.0) + .color(MENU_BG) + .label_color(TEXT_COLOR) + .label_font_id(self.fonts.opensans.conrod_id) + .down_from(state.ids.audio_device_text, 10.0) + .set(state.ids.audio_device_list, ui) + { + let new_val = device_list[clicked].clone(); + events.push(Event::ChangeAudioDevice(new_val)); + } } // 5) Languages Tab ----------------------------------- diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 4d89a9dc79..8fe5867110 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -144,10 +144,10 @@ fn main() { // Setup audio let mut audio = match settings.audio.output { AudioOutput::Off => None, - AudioOutput::Automatic => audio::get_default_stream().ok(), - //AudioOutput::Device(ref dev) => Some(dev.clone()), + AudioOutput::Automatic => audio::get_default_device(), + AudioOutput::Device(ref dev) => Some(dev.clone()), } - .map(|dev| AudioFrontend::new(/* dev, */ settings.audio.max_sfx_channels)) + .map(|dev| AudioFrontend::new(dev, settings.audio.max_sfx_channels)) .unwrap_or_else(AudioFrontend::no_audio); audio.set_music_volume(settings.audio.music_volume); diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index 23989f305b..8645e14954 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -9,6 +9,7 @@ use vek::*; pub struct BlocksOfInterest { pub leaves: Vec>, pub grass: Vec>, + pub water: Vec>, pub embers: Vec>, pub beehives: Vec>, pub reeds: Vec>, @@ -23,6 +24,7 @@ impl BlocksOfInterest { span!(_guard, "from_chunk", "BlocksOfInterest::from_chunk"); let mut leaves = Vec::new(); let mut grass = Vec::new(); + let mut water = Vec::new(); let mut embers = Vec::new(); let mut beehives = Vec::new(); let mut reeds = Vec::new(); @@ -50,6 +52,11 @@ impl BlocksOfInterest { grass.push(pos) } }, + BlockKind::Water => { + if thread_rng().gen_range(0, 16) == 0 { + water.push(pos) + } + }, _ => match block.get_sprite() { Some(SpriteKind::Ember) => embers.push(pos), Some(SpriteKind::Beehive) => beehives.push(pos), @@ -71,6 +78,7 @@ impl BlocksOfInterest { Self { leaves, grass, + water, embers, beehives, reeds, diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 36b9914c14..2c15a6984b 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -901,12 +901,12 @@ impl PlayState for SessionState { global_state.settings.audio.sfx_volume = sfx_volume; global_state.settings.save_to_file_warn(); }, - //HudEvent::ChangeAudioDevice(name) => { - // global_state.audio.set_device(name.clone()); + HudEvent::ChangeAudioDevice(name) => { + global_state.audio.set_device(name.clone()); - // global_state.settings.audio.output = AudioOutput::Device(name); - // global_state.settings.save_to_file_warn(); - //}, + global_state.settings.audio.output = AudioOutput::Device(name); + global_state.settings.save_to_file_warn(); + }, HudEvent::ChangeMaxFPS(fps) => { global_state.settings.graphics.max_fps = fps; global_state.settings.save_to_file_warn();