use std::sync::Arc;
use crate::frame::{FrameLineage, SampleSpec, SourceId};
use crate::graph::{EdgeContract, MediaCaps, PrepareContext, SignalEnvelope, SignalSpec};
use crate::runtime::{
PlanEdgeFrame, PlanEdgeObservationHandle, PlanEdgeReceiver, TypedEdgeReceiver,
};
use crate::endpoint::{
EndpointFailure, EndpointPreparationGroup, EndpointPrepareContext, PreparedEndpointDriver,
};
pub struct EndpointAudioFrame {
frame: PlanEdgeFrame,
}
impl EndpointAudioFrame {
pub(crate) fn into_inner(self) -> PlanEdgeFrame {
self.frame
}
pub fn source_id(&self) -> SourceId {
self.frame.source_id()
}
pub fn sequence_number(&self) -> u64 {
self.frame.sequence_number()
}
pub fn timestamp_ns(&self) -> u64 {
self.frame.timestamp_ns()
}
pub fn sample_rate_hz(&self) -> u32 {
self.frame.sample_rate_hz()
}
pub fn channels(&self) -> u8 {
self.frame.channels()
}
pub fn samples(&self) -> &[f32] {
self.frame.samples()
}
pub fn lineage(&self) -> FrameLineage {
self.frame.lineage()
}
}
pub struct EndpointAudioReceiver {
receiver: PlanEdgeReceiver,
}
impl EndpointAudioReceiver {
pub(crate) const fn new(receiver: PlanEdgeReceiver) -> Self {
Self { receiver }
}
pub(crate) fn into_inner(self) -> PlanEdgeReceiver {
self.receiver
}
#[cfg(feature = "internal-testing")]
pub fn into_plan_edge_receiver(self) -> PlanEdgeReceiver {
self.receiver
}
pub fn try_recv(&mut self) -> Option<EndpointAudioFrame> {
self.receiver
.try_recv()
.map(|frame| EndpointAudioFrame { frame })
}
pub fn is_abandoned(&self) -> bool {
self.receiver.is_abandoned()
}
pub fn mark_discontinuity(&self) {
self.receiver.mark_discontinuity();
}
pub fn mark_worker_failure(&self) {
self.receiver.mark_worker_failure();
}
pub fn observations(&self) -> crate::runtime::EdgeObservations {
self.receiver.observations()
}
pub(crate) fn observation_handle(&self) -> PlanEdgeObservationHandle {
self.receiver.observation_handle()
}
#[cfg(feature = "internal-testing")]
pub fn plan_edge_observation_handle(&self) -> PlanEdgeObservationHandle {
self.receiver.observation_handle()
}
}
pub struct EndpointSignalReceiver {
receiver: TypedEdgeReceiver,
}
impl EndpointSignalReceiver {
pub(crate) const fn new(receiver: TypedEdgeReceiver) -> Self {
Self { receiver }
}
pub fn try_recv(&mut self) -> Option<Arc<SignalEnvelope>> {
self.receiver.recv()
}
pub fn recv(&mut self) -> Option<Arc<SignalEnvelope>> {
self.try_recv()
}
pub fn is_abandoned(&self) -> bool {
self.receiver.is_abandoned()
}
}
pub enum EndpointReceiver {
Audio {
receiver: EndpointAudioReceiver,
sample_spec: SampleSpec,
},
Signal(EndpointSignalReceiver),
}
pub struct EndpointPortInput {
port_name: String,
signal: SignalSpec,
media: MediaCaps,
edge_contract: EdgeContract,
receiver: EndpointReceiver,
context: EndpointPrepareContext,
}
impl EndpointPortInput {
pub(crate) fn audio(
port_name: impl Into<String>,
signal: SignalSpec,
media: MediaCaps,
edge_contract: EdgeContract,
receiver: PlanEdgeReceiver,
prepare_context: PrepareContext,
context: EndpointPrepareContext,
) -> Self {
Self {
port_name: port_name.into(),
signal,
media,
edge_contract,
receiver: EndpointReceiver::Audio {
receiver: EndpointAudioReceiver::new(receiver),
sample_spec: prepare_context.sample_spec,
},
context,
}
}
pub(crate) fn signal(
port_name: impl Into<String>,
signal: SignalSpec,
media: MediaCaps,
edge_contract: EdgeContract,
receiver: TypedEdgeReceiver,
context: EndpointPrepareContext,
) -> Self {
Self {
port_name: port_name.into(),
signal,
media,
edge_contract,
receiver: EndpointReceiver::Signal(EndpointSignalReceiver::new(receiver)),
context,
}
}
pub fn port_name(&self) -> &str {
&self.port_name
}
pub const fn signal_spec(&self) -> &SignalSpec {
&self.signal
}
pub const fn media(&self) -> &MediaCaps {
&self.media
}
pub const fn edge_contract(&self) -> &EdgeContract {
&self.edge_contract
}
pub const fn context(&self) -> &EndpointPrepareContext {
&self.context
}
pub const fn receiver(&self) -> &EndpointReceiver {
&self.receiver
}
pub fn into_parts(self) -> (EndpointReceiver, EndpointPrepareContext) {
(self.receiver, self.context)
}
}
pub trait EndpointDriverFactory: Send + Sync {
fn preparation_group(
&self,
route_id: crate::frame::RouteId,
_configuration: &crate::graph::NodeConfig,
) -> Result<EndpointPreparationGroup, EndpointFailure> {
Ok(EndpointPreparationGroup::Route(route_id))
}
fn prepare(
&self,
inputs: Vec<EndpointPortInput>,
) -> Result<Box<dyn PreparedEndpointDriver>, EndpointFailure>;
}