assets.rs

 1use std::{io::Cursor, sync::Arc};
 2
 3use anyhow::Result;
 4use collections::HashMap;
 5use gpui::{AppContext, AssetSource};
 6use rodio::{
 7    source::{Buffered, SamplesConverter},
 8    Decoder, Source,
 9};
10
11type Sound = Buffered<SamplesConverter<Decoder<Cursor<Vec<u8>>>, f32>>;
12
13pub struct SoundRegistry {
14    cache: Arc<parking_lot::Mutex<HashMap<String, Sound>>>,
15    assets: Box<dyn AssetSource>,
16}
17
18impl SoundRegistry {
19    pub fn new(source: impl AssetSource) -> Arc<Self> {
20        Arc::new(Self {
21            cache: Default::default(),
22            assets: Box::new(source),
23        })
24    }
25
26    pub fn global(cx: &AppContext) -> Arc<Self> {
27        cx.global::<Arc<Self>>().clone()
28    }
29
30    pub fn get(&self, name: &str) -> Result<impl Source<Item = f32>> {
31        if let Some(wav) = self.cache.lock().get(name) {
32            return Ok(wav.clone());
33        }
34
35        let path = format!("sounds/{}.wav", name);
36        let bytes = self.assets.load(&path)?.into_owned();
37        let cursor = Cursor::new(bytes);
38        let source = Decoder::new(cursor)?.convert_samples::<f32>().buffered();
39
40        self.cache.lock().insert(name.to_string(), source.clone());
41
42        Ok(source)
43    }
44}