Skip to repository content168 lines · 5.4 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T03:43:01.929Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
audio_input_output_setup.rs
1use audio::{AudioDeviceInfo, AvailableAudioDevices};
2use cpal::DeviceId;
3use gpui::{AnyElement, App, ElementId, ReadGlobal, SharedString, Window};
4use settings::{AudioInputDeviceName, AudioOutputDeviceName, SettingsStore};
5use std::str::FromStr;
6use ui::{ContextMenu, DropdownMenu, DropdownStyle, FluentBuilder, IconPosition, IntoElement};
7use util::ResultExt;
8
9use crate::{SettingField, SettingsFieldMetadata, SettingsUiFile, update_settings_file};
10
11pub(crate) const SYSTEM_DEFAULT: &str = "System Default";
12
13pub(crate) fn get_current_device(
14 current_id: Option<&DeviceId>,
15 is_input: bool,
16 devices: &[AudioDeviceInfo],
17) -> Option<AudioDeviceInfo> {
18 let Some(current_id) = current_id else {
19 return None;
20 };
21 devices
22 .iter()
23 .find(|d| d.matches(current_id, is_input))
24 .cloned()
25}
26
27pub(crate) fn render_audio_device_dropdown<F>(
28 dropdown_id: impl Into<ElementId>,
29 current_device_id: Option<DeviceId>,
30 is_input: bool,
31 on_select: F,
32 aria_label: Option<SharedString>,
33 aria_description: Option<SharedString>,
34 window: &mut Window,
35 cx: &mut App,
36) -> AnyElement
37where
38 F: Fn(Option<DeviceId>, &mut Window, &mut App) + Clone + 'static,
39{
40 audio::ensure_devices_initialized(cx);
41 let devices = cx.global::<AvailableAudioDevices>().0.clone();
42 let current_device = get_current_device(current_device_id.as_ref(), is_input, &devices);
43
44 let menu = ContextMenu::build(window, cx, {
45 let current_device = current_device.clone();
46 move |mut menu, _, _cx| {
47 let is_system_default = current_device.is_none();
48 menu = menu.toggleable_entry(
49 SYSTEM_DEFAULT,
50 is_system_default,
51 IconPosition::Start,
52 None,
53 {
54 let on_select = on_select.clone();
55 move |window, cx| {
56 on_select(None, window, cx);
57 }
58 },
59 );
60
61 for device in devices.iter().filter(|d| d.matches_input(is_input)) {
62 let is_current = current_device
63 .as_ref()
64 .map(|info| info.matches(&device.id, is_input))
65 .unwrap_or(false);
66 let device_id = device.id.clone();
67
68 menu = menu.toggleable_entry(
69 device.to_string(),
70 is_current,
71 IconPosition::Start,
72 None,
73 {
74 let on_select = on_select.clone();
75 move |window, cx| {
76 on_select(Some(device_id.clone()), window, cx);
77 }
78 },
79 );
80 }
81 menu
82 }
83 });
84
85 DropdownMenu::new(
86 dropdown_id,
87 current_device
88 .map(|info| info.desc.name().to_string())
89 .unwrap_or(SYSTEM_DEFAULT.to_string()),
90 menu,
91 )
92 .style(DropdownStyle::Outlined)
93 .full_width(true)
94 .when_some(aria_label, |this, label| this.aria_label(label))
95 .when_some(aria_description, |this, description| {
96 this.aria_description(description)
97 })
98 .into_any_element()
99}
100
101fn render_settings_audio_device_dropdown<T: AsRef<Option<String>> + From<Option<String>> + Send>(
102 field: SettingField<T>,
103 file: SettingsUiFile,
104 is_input: bool,
105 title: &'static str,
106 description: &'static str,
107 window: &mut Window,
108 cx: &mut App,
109) -> AnyElement {
110 let (_, current_value): (_, Option<&T>) =
111 SettingsStore::global(cx).get_value_from_file(file.to_settings(), field.pick);
112 let current_device_id =
113 current_value.and_then(|x| x.as_ref().clone().and_then(|x| DeviceId::from_str(&x).ok()));
114
115 let dropdown_id: SharedString = if is_input {
116 "input-audio-device-dropdown".into()
117 } else {
118 "output-audio-device-dropdown".into()
119 };
120
121 render_audio_device_dropdown(
122 dropdown_id,
123 current_device_id,
124 is_input,
125 move |device_id, window, cx| {
126 let value: Option<T> = device_id.map(|id| T::from(Some(id.to_string())));
127 update_settings_file(
128 file.clone(),
129 field.json_path,
130 window,
131 cx,
132 move |settings, app| {
133 (field.write)(settings, value, app);
134 },
135 )
136 .log_err();
137 },
138 Some(SharedString::new_static(title)),
139 (!description.is_empty()).then(|| SharedString::new_static(description)),
140 window,
141 cx,
142 )
143}
144
145pub fn render_input_audio_device_dropdown(
146 field: SettingField<AudioInputDeviceName>,
147 file: SettingsUiFile,
148 _metadata: Option<&SettingsFieldMetadata>,
149 title: &'static str,
150 description: &'static str,
151 window: &mut Window,
152 cx: &mut App,
153) -> AnyElement {
154 render_settings_audio_device_dropdown(field, file, true, title, description, window, cx)
155}
156
157pub fn render_output_audio_device_dropdown(
158 field: SettingField<AudioOutputDeviceName>,
159 file: SettingsUiFile,
160 _metadata: Option<&SettingsFieldMetadata>,
161 title: &'static str,
162 description: &'static str,
163 window: &mut Window,
164 cx: &mut App,
165) -> AnyElement {
166 render_settings_audio_device_dropdown(field, file, false, title, description, window, cx)
167}
168