1use std::sync::atomic::{AtomicBool, Ordering};
2
3use anyhow::Result;
4use gpui::App;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use settings::{Settings, SettingsKey, SettingsSources, SettingsStore, SettingsUi};
8
9#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug, SettingsUi)]
10pub struct AudioSettings {
11 /// Opt into the new audio system.
12 ///
13 /// You need to rejoin a call for this setting to apply
14 #[serde(rename = "experimental.rodio_audio", default)]
15 pub rodio_audio: bool, // default is false
16 /// Requires 'rodio_audio: true'
17 ///
18 /// Automatically increase or decrease you microphone's volume. This affects how
19 /// loud you sound to others.
20 ///
21 /// Recommended: off (default)
22 /// Microphones are too quite in zed, until everyone is on experimental
23 /// audio and has auto speaker volume on this will make you very loud
24 /// compared to other speakers.
25 #[serde(
26 rename = "experimental.auto_microphone_volume",
27 default = "default_false"
28 )]
29 pub auto_microphone_volume: bool,
30 /// Requires 'rodio_audio: true'
31 ///
32 /// Automatically increate or decrease the volume of other call members.
33 /// This only affects how things sound for you.
34 #[serde(rename = "experimental.auto_speaker_volume", default = "default_true")]
35 pub auto_speaker_volume: bool,
36 /// Requires 'rodio_audio: true'
37 ///
38 /// Remove background noises. Works great for typing, cars, dogs, AC. Does
39 /// not work well on music.
40 #[serde(rename = "experimental.denoise", default = "default_false")]
41 pub denoise: bool,
42 /// Requires 'rodio_audio: true'
43 ///
44 /// Use audio parameters compatible with the previous versions of
45 /// experimental audio and non-experimental audio. When this is false you
46 /// will sound strange to anyone not on the latest experimental audio. In
47 /// the future we will migrate by setting this to false
48 ///
49 /// You need to rejoin a call for this setting to apply
50 #[serde(
51 rename = "experimental.legacy_audio_compatible",
52 default = "default_true"
53 )]
54 pub legacy_audio_compatible: bool,
55}
56/// Configuration of audio in Zed.
57#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug, SettingsUi, SettingsKey)]
58#[serde(default)]
59#[settings_key(key = "audio")]
60pub struct AudioSettingsContent {
61 /// Opt into the new audio system.
62 ///
63 /// You need to rejoin a call for this setting to apply
64 #[serde(rename = "experimental.rodio_audio", default)]
65 pub rodio_audio: bool, // default is false
66 /// Requires 'rodio_audio: true'
67 ///
68 /// Automatically increase or decrease you microphone's volume. This affects how
69 /// loud you sound to others.
70 ///
71 /// Recommended: off (default)
72 /// Microphones are too quite in zed, until everyone is on experimental
73 /// audio and has auto speaker volume on this will make you very loud
74 /// compared to other speakers.
75 #[serde(
76 rename = "experimental.auto_microphone_volume",
77 default = "default_false"
78 )]
79 pub auto_microphone_volume: bool,
80 /// Requires 'rodio_audio: true'
81 ///
82 /// Automatically increate or decrease the volume of other call members.
83 /// This only affects how things sound for you.
84 #[serde(rename = "experimental.auto_speaker_volume", default = "default_true")]
85 pub auto_speaker_volume: bool,
86 /// Requires 'rodio_audio: true'
87 ///
88 /// Remove background noises. Works great for typing, cars, dogs, AC. Does
89 /// not work well on music.
90 #[serde(rename = "experimental.denoise", default = "default_false")]
91 pub denoise: bool,
92 /// Requires 'rodio_audio: true'
93 ///
94 /// Use audio parameters compatible with the previous versions of
95 /// experimental audio and non-experimental audio. When this is false you
96 /// will sound strange to anyone not on the latest experimental audio. In
97 /// the future we will migrate by setting this to false
98 ///
99 /// You need to rejoin a call for this setting to apply
100 #[serde(
101 rename = "experimental.legacy_audio_compatible",
102 default = "default_true"
103 )]
104 pub legacy_audio_compatible: bool,
105}
106
107fn default_true() -> bool {
108 true
109}
110
111fn default_false() -> bool {
112 false
113}
114
115impl Settings for AudioSettings {
116 type FileContent = AudioSettingsContent;
117
118 fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut App) -> Result<Self> {
119 sources.json_merge()
120 }
121
122 fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) {}
123}
124
125/// See docs on [LIVE_SETTINGS]
126pub(crate) struct LiveSettings {
127 pub(crate) auto_microphone_volume: AtomicBool,
128 pub(crate) auto_speaker_volume: AtomicBool,
129 pub(crate) denoise: AtomicBool,
130}
131
132impl LiveSettings {
133 pub(crate) fn initialize(&self, cx: &mut App) {
134 cx.observe_global::<SettingsStore>(move |cx| {
135 LIVE_SETTINGS.auto_microphone_volume.store(
136 AudioSettings::get_global(cx).auto_microphone_volume,
137 Ordering::Relaxed,
138 );
139 LIVE_SETTINGS.auto_speaker_volume.store(
140 AudioSettings::get_global(cx).auto_speaker_volume,
141 Ordering::Relaxed,
142 );
143
144 let denoise_enabled = AudioSettings::get_global(cx).denoise;
145 #[cfg(debug_assertions)]
146 {
147 static DENOISE_WARNING_SEND: AtomicBool = AtomicBool::new(false);
148 if denoise_enabled && !DENOISE_WARNING_SEND.load(Ordering::Relaxed) {
149 DENOISE_WARNING_SEND.store(true, Ordering::Relaxed);
150 log::warn!("Denoise does not work on debug builds, not enabling")
151 }
152 }
153 #[cfg(not(debug_assertions))]
154 LIVE_SETTINGS
155 .denoise
156 .store(denoise_enabled, Ordering::Relaxed);
157 })
158 .detach();
159
160 let init_settings = AudioSettings::get_global(cx);
161 LIVE_SETTINGS
162 .auto_microphone_volume
163 .store(init_settings.auto_microphone_volume, Ordering::Relaxed);
164 LIVE_SETTINGS
165 .auto_speaker_volume
166 .store(init_settings.auto_speaker_volume, Ordering::Relaxed);
167 let denoise_enabled = AudioSettings::get_global(cx).denoise;
168 #[cfg(debug_assertions)]
169 if denoise_enabled {
170 log::warn!("Denoise does not work on debug builds, not enabling")
171 }
172 #[cfg(not(debug_assertions))]
173 LIVE_SETTINGS
174 .denoise
175 .store(denoise_enabled, Ordering::Relaxed);
176 }
177}
178
179/// Allows access to settings from the audio thread. Updated by
180/// observer of SettingsStore. Needed because audio playback and recording are
181/// real time and must each run in a dedicated OS thread, therefore we can not
182/// use the background executor.
183pub(crate) static LIVE_SETTINGS: LiveSettings = LiveSettings {
184 auto_microphone_volume: AtomicBool::new(true),
185 auto_speaker_volume: AtomicBool::new(true),
186 denoise: AtomicBool::new(true),
187};