1use std::{
2 str::FromStr,
3 sync::atomic::{AtomicBool, Ordering},
4};
5
6use cpal::DeviceId;
7use gpui::App;
8use settings::{RegisterSetting, Settings, SettingsStore};
9
10#[derive(Clone, Debug, RegisterSetting)]
11pub struct AudioSettings {
12 /// Automatically increase or decrease you microphone's volume. This affects how
13 /// loud you sound to others.
14 ///
15 /// Recommended: off (default)
16 /// Microphones are too quite in zed, until everyone is on experimental
17 /// audio and has auto speaker volume on this will make you very loud
18 /// compared to other speakers.
19 pub auto_microphone_volume: bool,
20 /// Select specific output audio device.
21 pub output_audio_device: Option<DeviceId>,
22 /// Select specific input audio device.
23 pub input_audio_device: Option<DeviceId>,
24}
25
26/// Configuration of audio in Zed
27impl Settings for AudioSettings {
28 fn from_settings(content: &settings::SettingsContent) -> Self {
29 let audio = &content.audio.as_ref().unwrap();
30 AudioSettings {
31 auto_microphone_volume: audio.auto_microphone_volume.unwrap(),
32 output_audio_device: audio
33 .output_audio_device
34 .as_ref()
35 .and_then(|x| x.0.as_ref().and_then(|id| DeviceId::from_str(&id).ok())),
36 input_audio_device: audio
37 .input_audio_device
38 .as_ref()
39 .and_then(|x| x.0.as_ref().and_then(|id| DeviceId::from_str(&id).ok())),
40 }
41 }
42}
43
44/// See docs on [LIVE_SETTINGS]
45pub struct LiveSettings {
46 pub auto_microphone_volume: AtomicBool,
47}
48
49impl LiveSettings {
50 pub(crate) fn initialize(&self, cx: &mut App) {
51 cx.observe_global::<SettingsStore>(move |cx| {
52 LIVE_SETTINGS.auto_microphone_volume.store(
53 AudioSettings::get_global(cx).auto_microphone_volume,
54 Ordering::Relaxed,
55 );
56 })
57 .detach();
58
59 let init_settings = AudioSettings::get_global(cx);
60 LIVE_SETTINGS
61 .auto_microphone_volume
62 .store(init_settings.auto_microphone_volume, Ordering::Relaxed);
63 }
64}
65
66/// Allows access to settings from the audio thread. Updated by
67/// observer of SettingsStore. Needed because audio playback and recording are
68/// real time and must each run in a dedicated OS thread, therefore we can not
69/// use the background executor.
70pub static LIVE_SETTINGS: LiveSettings = LiveSettings {
71 auto_microphone_volume: AtomicBool::new(true),
72};