sim_lib_stream_host/
router.rs1use std::collections::HashMap;
4use std::sync::Arc;
5
6use sim_kernel::{Error, Result};
7
8use crate::HostOpenStream;
9use crate::placement::{AudioPlacementRequest, AudioSiteKey};
10use crate::site::AudioSite;
11
12pub struct AudioRouter {
14 sites: HashMap<AudioSiteKey, Arc<dyn AudioSite>>,
15}
16
17impl Default for AudioRouter {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl AudioRouter {
24 pub fn new() -> Self {
26 Self {
27 sites: HashMap::new(),
28 }
29 }
30
31 pub fn register(&mut self, site: Arc<dyn AudioSite>) {
33 self.sites.insert(site.key().clone(), site);
34 }
35
36 pub fn site(&self, key: &AudioSiteKey) -> Option<&Arc<dyn AudioSite>> {
38 self.sites.get(key)
39 }
40
41 pub fn site_keys(&self) -> impl Iterator<Item = &AudioSiteKey> {
43 self.sites.keys()
44 }
45
46 pub fn sites_by_capability(
48 &self,
49 min_channels_out: u16,
50 preferred_rates: &[u32],
51 ) -> Vec<AudioSiteKey> {
52 let mut keys = self
53 .sites
54 .values()
55 .filter(|site| {
56 let card = site.card();
57 card.channels_out >= min_channels_out
58 && preferred_rates
59 .iter()
60 .any(|rate| card.sample_rates.contains(rate))
61 })
62 .map(|site| site.key().clone())
63 .collect::<Vec<_>>();
64 keys.sort_by_key(|key| key.0.to_string());
65 keys
66 }
67
68 pub fn resolve_or_modeled(
73 &self,
74 key: &AudioSiteKey,
75 modeled: &AudioSiteKey,
76 ) -> Result<AudioSiteKey> {
77 if self.sites.contains_key(key) {
78 Ok(key.clone())
79 } else if self.sites.contains_key(modeled) {
80 Ok(modeled.clone())
81 } else {
82 Err(Error::Eval(format!(
83 "no audio site registered for {:?} and no modeled fallback {:?}",
84 key, modeled
85 )))
86 }
87 }
88
89 pub fn open_placement(&self, request: AudioPlacementRequest) -> Result<HostOpenStream> {
91 self.sites
92 .get(&request.site_key)
93 .ok_or_else(|| {
94 Error::Eval(format!(
95 "no audio site registered for {:?}",
96 request.site_key
97 ))
98 })?
99 .open(request.stream_request)
100 }
101}