initial commit

This commit is contained in:
Franz Heinzmann (Frando) 2021-02-19 14:40:58 +01:00
commit 091e6319cd
9 changed files with 700 additions and 0 deletions

280
src/switcher.rs Normal file
View file

@ -0,0 +1,280 @@
use async_channel::{self, Receiver, Sender};
use async_std::prelude::*;
use async_std::task::{self, JoinHandle};
use rosc::{OscMessage, OscType};
use std::collections::{VecDeque};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum SwitcherError {
#[error("Channel for switcher events full")]
CannotSendEvent(#[from] async_channel::SendError<SwitcherEvent>),
#[error("Channel for OSC messages full")]
CannotSendMessage(#[from] async_channel::SendError<OscMessage>),
#[error("Decode OSC packet failed")]
Osc(rosc::OscError),
#[error("IO error")]
Io(#[from] std::io::Error),
}
impl From<rosc::OscError> for SwitcherError {
fn from(error: rosc::OscError) -> Self {
Self::Osc(error)
}
}
pub type Result<T> = std::result::Result<T, SwitcherError>;
pub type ChannelId = usize;
#[derive(Debug)]
pub enum SwitcherEvent {
Enable(ChannelId),
Disable(ChannelId),
}
#[derive(Default)]
pub struct SwitcherState {
// osc_tx: Sender<OscMessage>,
channels: Vec<ChannelState>,
active_channel: usize,
messages: Messages,
}
#[derive(Default)]
pub struct ChannelState {
id: ChannelId,
pub name: String,
pub locked: bool,
pub enabled: bool,
}
impl ChannelState {
pub fn new(id: ChannelId) -> Self {
Self {
id,
..Default::default()
}
}
}
pub struct SwitcherHandle {
events_tx: Sender<SwitcherEvent>,
osc_rx: Option<Receiver<OscMessage>>,
task: JoinHandle<Result<()>>,
}
impl SwitcherHandle {
pub fn run() -> Self {
let (osc_tx, osc_rx) = async_channel::unbounded();
let (events_tx, events_rx) = async_channel::unbounded();
let state = SwitcherState::new();
let task = task::spawn(run_loop(state, events_rx, osc_tx));
SwitcherHandle {
events_tx,
osc_rx: Some(osc_rx),
task,
}
}
pub async fn join(self) -> Result<()> {
self.task.await
}
pub async fn send(&self, event: SwitcherEvent) -> Result<()> {
log::debug!("switcher got event: {:?}", event);
self.events_tx.send(event).await?;
Ok(())
}
pub fn sender(&self) -> Sender<SwitcherEvent> {
self.events_tx.clone()
}
pub fn take_receiver(&mut self) -> Option<Receiver<OscMessage>> {
self.osc_rx.take()
}
}
pub async fn run_loop(
mut state: SwitcherState,
mut events_rx: Receiver<SwitcherEvent>,
osc_tx: Sender<OscMessage>,
) -> Result<()> {
state.init();
loop {
while let Some(message) = state.pop_message() {
osc_tx.send(message).await?;
}
if let Some(event) = events_rx.next().await {
state.on_event(event);
}
}
}
impl SwitcherState {
pub fn new() -> Self {
Default::default()
}
pub fn init(&mut self) {
let num_channels = 4;
for i in 0..num_channels {
let channel = ChannelState::new(i);
self.channels.push(channel);
}
// self.messages.push("/*", ("xmit", 1));
self.messages.push("/mixer/out/0/bus/0/on", (1.0,));
self.messages.push("/mixer/bus/0/ch/0/on", (1.0,));
self.update_state();
}
pub fn on_event(&mut self, event: SwitcherEvent) {
match event {
SwitcherEvent::Enable(channel) => self.enable_channel(channel),
SwitcherEvent::Disable(channel) => self.disable_channel(channel),
}
self.update_state();
}
pub fn enable_channel(&mut self, channel_id: ChannelId) {
if let Some(channel) = self.channels.iter_mut().find(|c| c.id == channel_id) {
if !channel.locked {
channel.enabled = true;
}
}
}
pub fn disable_channel(&mut self, channel_id: ChannelId) {
if let Some(channel) = self.channels.iter_mut().find(|c| c.id == channel_id) {
if !channel.locked {
channel.enabled = false;
}
}
}
fn update_state(&mut self) {
let next_active_channel = self
.channels
.iter()
.rev()
.find(|c| c.enabled)
.or(self.channels.get(0))
.unwrap()
.id;
if next_active_channel != self.active_channel {
self.active_channel = next_active_channel;
self.on_channel_change();
}
}
fn on_channel_change(&mut self) {
for channel in self.channels.iter() {
if channel.id == self.active_channel {
self.messages
.push(format!("/mixer/bus/0/ch/{}/on", channel.id), (1.0,));
} else {
self.messages
.push(format!("/mixer/bus/0/ch/{}/on", channel.id), (0.0,));
}
}
}
fn pop_message(&mut self) -> Option<OscMessage> {
self.messages.pop()
}
}
pub struct Messages {
inner: VecDeque<OscMessage>,
}
impl Default for Messages {
fn default() -> Self {
Self::new()
}
}
impl Messages {
pub fn new() -> Self {
Self {
inner: VecDeque::new(),
}
}
fn push<T>(&mut self, addr: impl ToString, args: T)
where
T: IntoOscArgs,
{
self.inner.push_back(osc_message(addr, args));
}
fn pop(&mut self) -> Option<OscMessage> {
self.inner.pop_front()
}
}
fn osc_message<T>(addr: impl ToString, args: T) -> OscMessage
where
T: IntoOscArgs,
{
// let args: Vec<OscType> = args.into_iter().map(|a| a.into()).collect();
let args = args.into_osc_args();
let addr = addr.to_string();
OscMessage { addr, args }
}
pub trait IntoOscArgs {
fn into_osc_args(self) -> Vec<OscType>;
}
impl<T> IntoOscArgs for Vec<T>
where
T: Into<OscType>,
{
fn into_osc_args(self) -> Vec<OscType> {
let args: Vec<OscType> = self.into_iter().map(|a| a.into()).collect();
args
}
}
impl<T1> IntoOscArgs for (T1,)
where
T1: Into<OscType>,
{
fn into_osc_args(self) -> Vec<OscType> {
vec![self.0.into()]
}
}
impl<T1, T2> IntoOscArgs for (T1, T2)
where
T1: Into<OscType>,
T2: Into<OscType>,
{
fn into_osc_args(self) -> Vec<OscType> {
vec![self.0.into(), self.1.into()]
}
}
impl<T1, T2, T3> IntoOscArgs for (T1, T2, T3)
where
T1: Into<OscType>,
T2: Into<OscType>,
T3: Into<OscType>,
{
fn into_osc_args(self) -> Vec<OscType> {
vec![self.0.into(), self.1.into(), self.2.into()]
}
}
impl IntoOscArgs for OscType {
fn into_osc_args(self) -> Vec<OscType> {
vec![self]
}
}
// impl IntoOscArgs for Vec<OscType> {
// fn into_osc_args(self) -> Vec<OscType> {
// self
// }
// }