audio.rs

 1use assets::SoundRegistry;
 2use gpui::{AppContext, AssetSource, Global};
 3use rodio::{OutputStream, OutputStreamHandle};
 4use util::ResultExt;
 5
 6mod assets;
 7
 8pub fn init(source: impl AssetSource, cx: &mut AppContext) {
 9    SoundRegistry::set_global(source, cx);
10    cx.set_global(Audio::new());
11}
12
13pub enum Sound {
14    Joined,
15    Leave,
16    Mute,
17    Unmute,
18    StartScreenshare,
19    StopScreenshare,
20}
21
22impl Sound {
23    fn file(&self) -> &'static str {
24        match self {
25            Self::Joined => "joined_call",
26            Self::Leave => "leave_call",
27            Self::Mute => "mute",
28            Self::Unmute => "unmute",
29            Self::StartScreenshare => "start_screenshare",
30            Self::StopScreenshare => "stop_screenshare",
31        }
32    }
33}
34
35pub struct Audio {
36    _output_stream: Option<OutputStream>,
37    output_handle: Option<OutputStreamHandle>,
38}
39
40impl Global for Audio {}
41
42impl Audio {
43    pub fn new() -> Self {
44        Self {
45            _output_stream: None,
46            output_handle: None,
47        }
48    }
49
50    fn ensure_output_exists(&mut self) -> Option<&OutputStreamHandle> {
51        if self.output_handle.is_none() {
52            let (_output_stream, output_handle) = OutputStream::try_default().log_err().unzip();
53            self.output_handle = output_handle;
54            self._output_stream = _output_stream;
55        }
56
57        self.output_handle.as_ref()
58    }
59
60    pub fn play_sound(sound: Sound, cx: &mut AppContext) {
61        if !cx.has_global::<Self>() {
62            return;
63        }
64
65        cx.update_global::<Self, _>(|this, cx| {
66            let output_handle = this.ensure_output_exists()?;
67            let source = SoundRegistry::global(cx).get(sound.file()).log_err()?;
68            output_handle.play_raw(source).log_err()?;
69            Some(())
70        });
71    }
72
73    pub fn end_call(cx: &mut AppContext) {
74        if !cx.has_global::<Self>() {
75            return;
76        }
77
78        cx.update_global::<Self, _>(|this, _| {
79            this._output_stream.take();
80            this.output_handle.take();
81        });
82    }
83}