use std::sync::Arc;
use sim_kernel::{Error, Result, Symbol};
use sim_lib_stream_core::{
PushResult, StreamInspectorSnapshot, StreamItem, StreamMedia, StreamPacket, StreamStats,
StreamValue, TransportProfile,
};
#[derive(Clone)]
pub struct HostCallbackQueue {
media: StreamMedia,
stream: Arc<StreamValue>,
}
impl HostCallbackQueue {
pub fn new(stream: Arc<StreamValue>) -> Self {
Self {
media: stream.metadata().media(),
stream,
}
}
pub fn stream(&self) -> Arc<StreamValue> {
Arc::clone(&self.stream)
}
pub fn callback_packet(&self, packet: StreamPacket) -> Result<PushResult> {
self.ensure_media(&packet)?;
self.stream.push_packet(StreamItem::new(packet))
}
pub fn callback_item(&self, item: StreamItem) -> Result<PushResult> {
self.ensure_media(item.packet())?;
self.stream.push_packet(item)
}
pub fn drain(&self, limit: usize) -> Result<Vec<StreamItem>> {
self.stream.take_packets(limit)
}
pub fn close(&self) -> Result<()> {
self.stream.close_push()
}
pub fn cancel(&self) -> Result<()> {
self.stream.cancel()
}
pub fn stats(&self) -> Result<StreamStats> {
self.stream.stats()
}
pub fn inspector(
&self,
route: Symbol,
profile: &TransportProfile,
recent_diagnostics: Vec<Symbol>,
) -> Result<StreamInspectorSnapshot> {
StreamInspectorSnapshot::from_stream_value(&self.stream, route, profile, recent_diagnostics)
}
fn ensure_media(&self, packet: &StreamPacket) -> Result<()> {
let packet_media = match packet {
StreamPacket::Pcm(_) => StreamMedia::Pcm,
StreamPacket::Midi(_) => StreamMedia::Midi,
StreamPacket::Diagnostic(_) => StreamMedia::Diagnostic,
StreamPacket::Data(_) => StreamMedia::Data,
};
if packet_media == self.media {
Ok(())
} else {
Err(Error::TypeMismatch {
expected: "host callback packet matching device media",
found: "host callback packet for another media",
})
}
}
}