fission_shell_winit/
volume.rs1use fission_core::{
2 VolumeAdjustDirection, VolumeAdjustRequest, VolumeError, VolumeLevel, VolumeSetRequest,
3 VolumeStream, ADJUST_VOLUME_LEVEL, GET_VOLUME_LEVEL, SET_VOLUME_LEVEL,
4};
5use fission_shell::async_host::AsyncRegistry;
6use std::sync::{Arc, Mutex};
7
8pub trait VolumeHost: Send + Sync + 'static {
10 fn get_level(&self, stream: VolumeStream) -> Result<VolumeLevel, VolumeError>;
12 fn set_level(&self, request: VolumeSetRequest) -> Result<VolumeLevel, VolumeError>;
14 fn adjust_level(&self, request: VolumeAdjustRequest) -> Result<VolumeLevel, VolumeError>;
16}
17
18#[derive(Debug, Default)]
19pub struct UnsupportedVolumeHost;
20
21impl VolumeHost for UnsupportedVolumeHost {
22 fn get_level(&self, _stream: VolumeStream) -> Result<VolumeLevel, VolumeError> {
23 Err(VolumeError::unsupported("get_level"))
24 }
25
26 fn set_level(&self, _request: VolumeSetRequest) -> Result<VolumeLevel, VolumeError> {
27 Err(VolumeError::unsupported("set_level"))
28 }
29
30 fn adjust_level(&self, _request: VolumeAdjustRequest) -> Result<VolumeLevel, VolumeError> {
31 Err(VolumeError::unsupported("adjust_level"))
32 }
33}
34
35#[derive(Debug)]
36pub struct MemoryVolumeHost {
37 level: Arc<Mutex<VolumeLevel>>,
38}
39
40impl Default for MemoryVolumeHost {
41 fn default() -> Self {
42 Self {
43 level: Arc::new(Mutex::new(VolumeLevel {
44 stream: VolumeStream::Media,
45 level: 50,
46 muted: false,
47 })),
48 }
49 }
50}
51
52impl MemoryVolumeHost {
53 pub fn current(&self) -> VolumeLevel {
54 self.level.lock().unwrap().clone()
55 }
56}
57
58impl VolumeHost for MemoryVolumeHost {
59 fn get_level(&self, stream: VolumeStream) -> Result<VolumeLevel, VolumeError> {
60 let mut level = self.level.lock().unwrap().clone();
61 level.stream = stream;
62 Ok(level)
63 }
64
65 fn set_level(&self, request: VolumeSetRequest) -> Result<VolumeLevel, VolumeError> {
66 let mut level = self.level.lock().unwrap();
67 level.stream = request.stream;
68 level.level = request.level.min(100);
69 if let Some(muted) = request.muted {
70 level.muted = muted;
71 }
72 Ok(level.clone())
73 }
74
75 fn adjust_level(&self, request: VolumeAdjustRequest) -> Result<VolumeLevel, VolumeError> {
76 let mut level = self.level.lock().unwrap();
77 level.stream = request.stream;
78 level.level = match request.direction {
79 VolumeAdjustDirection::Up => level.level.saturating_add(request.step).min(100),
80 VolumeAdjustDirection::Down => level.level.saturating_sub(request.step),
81 };
82 Ok(level.clone())
83 }
84}
85
86pub(crate) fn register_volume_capabilities(
87 async_registry: &mut AsyncRegistry,
88 host: Arc<dyn VolumeHost>,
89) {
90 let get_host = host.clone();
91 async_registry.register_operation_capability(GET_VOLUME_LEVEL, move |request, _| {
92 let host = get_host.clone();
93 async move { host.get_level(request) }
94 });
95
96 let set_host = host.clone();
97 async_registry.register_operation_capability(SET_VOLUME_LEVEL, move |request, _| {
98 let host = set_host.clone();
99 async move { host.set_level(request) }
100 });
101
102 async_registry.register_operation_capability(ADJUST_VOLUME_LEVEL, move |request, _| {
103 let host = host.clone();
104 async move { host.adjust_level(request) }
105 });
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn unsupported_host_reports_errors() {
114 let host = UnsupportedVolumeHost;
115 assert!(host.get_level(VolumeStream::Media).is_err());
116 }
117
118 #[test]
119 fn memory_host_sets_and_adjusts_volume() {
120 let host = MemoryVolumeHost::default();
121 let set = host
122 .set_level(VolumeSetRequest {
123 stream: VolumeStream::Media,
124 level: 80,
125 muted: Some(false),
126 })
127 .unwrap();
128 assert_eq!(set.level, 80);
129
130 let adjusted = host
131 .adjust_level(VolumeAdjustRequest {
132 stream: VolumeStream::Media,
133 direction: VolumeAdjustDirection::Down,
134 step: 15,
135 })
136 .unwrap();
137 assert_eq!(adjusted.level, 65);
138 }
139}