Skip to main content

fission_shell_winit/
volume.rs

1use 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
8/// Host-side volume-control provider.
9pub trait VolumeHost: Send + Sync + 'static {
10    /// Reads the current level and mute state for one logical volume stream.
11    fn get_level(&self, stream: VolumeStream) -> Result<VolumeLevel, VolumeError>;
12    /// Sets the level and optional mute state for one logical volume stream.
13    fn set_level(&self, request: VolumeSetRequest) -> Result<VolumeLevel, VolumeError>;
14    /// Adjusts one logical volume stream relative to its current state.
15    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}