pocketstation 1.0.1

Source-aware desktop audio Session SDK
Documentation
use crate::graph::NodeTypeId;
use crate::session::{
    ApplicationSelector, ConnectionTarget, EndpointDescriptor, Operator, OperatorConfiguration,
    OperatorId, Session, SessionError, Source, StreamOrigin,
};

fn operator(id: &str) -> Operator {
    Operator::new(OperatorId::new(id), OperatorConfiguration::new())
}

fn endpoint(session: &Session, suffix: &str) -> crate::session::EndpointHandle {
    let node_type_id = format!("endpoint.named.{suffix}");
    session
        .endpoint(EndpointDescriptor::new(
            NodeTypeId::from(node_type_id.as_str()),
            OperatorId::new(format!("example.endpoint.named.{suffix}.v1")),
        ))
        .expect("endpoint declaration")
}

#[test]
fn given_one_declared_instance_when_named_ports_connected_then_one_instance_owns_all_connections() {
    let session = Session::new();
    let application = session
        .capture(Source::application(ApplicationSelector::name(
            "Meeting App",
        )))
        .expect("application");
    let microphone = session
        .capture(Source::microphone_default())
        .expect("microphone");
    let declared = session
        .operator(operator("example.operator.named-composition.v1"))
        .expect("one operator instance");

    application
        .connect(declared.input("application").expect("application input"))
        .expect("application connection");
    microphone
        .connect(declared.input("microphone").expect("microphone input"))
        .expect("microphone connection");
    declared
        .output("primary")
        .expect("primary output")
        .send(endpoint(&session, "primary"))
        .expect("primary route");
    declared
        .output("diagnostics")
        .expect("diagnostics output")
        .send(endpoint(&session, "diagnostics"))
        .expect("diagnostics route");

    let spec = session.freeze().expect("named Session specification");
    assert_eq!(spec.operators().len(), 1);
    let operator_inputs = spec
        .connections()
        .iter()
        .filter(|connection| matches!(connection.target(), ConnectionTarget::OperatorInput { .. }))
        .collect::<Vec<_>>();
    let endpoint_inputs = spec
        .connections()
        .iter()
        .filter(|connection| matches!(connection.target(), ConnectionTarget::EndpointInput { .. }))
        .collect::<Vec<_>>();
    assert_eq!(operator_inputs.len(), 2);
    assert_eq!(endpoint_inputs.len(), 2);
    assert_eq!(
        operator_inputs
            .iter()
            .map(|connection| match connection.target() {
                ConnectionTarget::OperatorInput {
                    input_port: Some(input_port),
                    ..
                } => input_port.as_str(),
                _ => panic!("named operator input"),
            })
            .collect::<Vec<_>>(),
        ["application", "microphone"]
    );
    assert!(matches!(operator_inputs[0].origin(), StreamOrigin::Stem(_)));
}

#[test]
fn given_through_sugar_when_frozen_then_canonical_instance_and_connection_records_are_used() {
    let session = Session::new();
    let microphone = session
        .capture(Source::microphone_default())
        .expect("microphone");
    let derived = microphone
        .through(operator("example.operator.sugar.v1"))
        .expect("through sugar");
    derived
        .send(endpoint(&session, "sugar"))
        .expect("derived route");

    let spec = session.freeze().expect("canonical specification");
    assert_eq!(spec.operators().len(), 1);
    let connection = spec
        .connections()
        .iter()
        .find(|connection| matches!(connection.target(), ConnectionTarget::OperatorInput { .. }))
        .expect("operator input connection");
    assert!(matches!(
        connection.target(),
        ConnectionTarget::OperatorInput {
            operator_instance_id,
            ..
        } if *operator_instance_id == spec.operators()[0].instance_id()
    ));
}

#[test]
fn given_duplicate_named_input_when_connected_then_declaration_fails_immediately() {
    let session = Session::new();
    let application = session
        .capture(Source::application(ApplicationSelector::name(
            "Meeting App",
        )))
        .expect("application");
    let microphone = session
        .capture(Source::microphone_default())
        .expect("microphone");
    let declared = session
        .operator(operator("example.operator.duplicate-input.v1"))
        .expect("operator");
    application
        .connect(declared.input("audio").expect("input"))
        .expect("first connection");

    let result = microphone.connect(declared.input("audio").expect("same input"));

    assert!(matches!(result, Err(SessionError::InvalidOperator { .. })));
}

#[test]
fn given_foreign_input_handle_when_connected_then_declaration_fails_before_freeze() {
    let first = Session::new();
    let second = Session::new();
    let microphone = first
        .capture(Source::microphone_default())
        .expect("microphone");
    let foreign = second
        .operator(operator("example.operator.foreign.v1"))
        .expect("foreign operator")
        .input("audio")
        .expect("foreign input");

    let result = microphone.connect(foreign);

    assert!(matches!(result, Err(SessionError::InvalidOperator { .. })));
}