feat: The rest of the owl
This commit is contained in:
parent
8cce21193a
commit
be96c86f74
4
build.rs
4
build.rs
|
@ -44,6 +44,10 @@ fn main() {
|
|||
panic!("Running `trunk build` failed, reason {err}");
|
||||
}
|
||||
|
||||
if let Ok(trunk_output_string) = String::from_utf8(trunk_build_output.stdout) {
|
||||
println!("{trunk_output_string}");
|
||||
}
|
||||
|
||||
let dist_paths = fs::read_dir("./frontend/dist").expect("Could not read dist directory");
|
||||
let paths: Vec<Result<DirEntry, Error>> = dist_paths.collect();
|
||||
let paths: Vec<(String, PathBuf)> = paths
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
use std::{
|
||||
collections::VecDeque,
|
||||
fmt::Display,
|
||||
collections::{HashMap, VecDeque},
|
||||
mem,
|
||||
net::{IpAddr, Ipv4Addr},
|
||||
};
|
||||
|
||||
use egui::{Button, Color32, RichText, Sense, Stroke, Vec2};
|
||||
use egui::{Button, Color32, RichText, Rounding, Sense, Stroke, Vec2};
|
||||
use ewebsock::{Options, WsReceiver, WsSender};
|
||||
use wasm_timer::Instant;
|
||||
|
||||
use crate::websocket::{
|
||||
AddHyperdeckRequest, ClientRequest, HyperdeckConnectionState, RemoveHyperdeckRequest,
|
||||
ServerEvent,
|
||||
AddHyperdeckRequest, ClientRequest, HyperdeckConnectionState, HyperdeckRecordBay,
|
||||
RecordingState, RemoveHyperdeckRequest, ServerEvent,
|
||||
};
|
||||
|
||||
pub struct HyperdeckMonitorApp {
|
||||
|
@ -37,28 +36,69 @@ impl Default for HyperdeckMonitorApp {
|
|||
new_hyperdeck_name: "".to_owned(),
|
||||
new_hyperdeck_port: 9993.to_string(),
|
||||
hyperdecks: vec![
|
||||
// Hyperdeck {
|
||||
// id: "test-1".to_string(),
|
||||
// name: "Test Hyperdeck 1".to_string(),
|
||||
// ip: IpAddr::V4(Ipv4Addr::new(192, 168, 10, 1)),
|
||||
// status: HyperdeckStatus::Connected,
|
||||
// recording_bays: vec![HyperdeckRecordBay {
|
||||
// status: RecordingStatus::NotRecording,
|
||||
// storage_capacity_mb: 500_000,
|
||||
// recording_time_remaining: TimeRemaining(60),
|
||||
// }],
|
||||
// },
|
||||
// Hyperdeck {
|
||||
// id: "test-2".to_string(),
|
||||
// name: "Test Hyperdeck 2".to_string(),
|
||||
// ip: IpAddr::V4(Ipv4Addr::new(192, 168, 10, 2)),
|
||||
// status: HyperdeckStatus::Disconnected,
|
||||
// recording_bays: vec![HyperdeckRecordBay {
|
||||
// status: RecordingStatus::NotRecording,
|
||||
// storage_capacity_mb: 500_000,
|
||||
// recording_time_remaining: TimeRemaining(3600 * 5), // 5 Hours
|
||||
// }],
|
||||
// },
|
||||
Hyperdeck {
|
||||
id: "test-1".to_string(),
|
||||
name: "Description: Connected Hyperdeck - Not Recording - Not Much Time"
|
||||
.to_string(),
|
||||
ip: IpAddr::V4(Ipv4Addr::new(192, 168, 10, 1)),
|
||||
status: HyperdeckStatus::Connected,
|
||||
recording_status: RecordingState::NotRecording,
|
||||
slots: vec![(
|
||||
0usize,
|
||||
HyperdeckRecordBay {
|
||||
recording_time_remaining: 60,
|
||||
},
|
||||
)]
|
||||
.into_iter()
|
||||
.collect::<HashMap<usize, HyperdeckRecordBay>>(),
|
||||
},
|
||||
Hyperdeck {
|
||||
id: "test-2".to_string(),
|
||||
name: "Description: Connected Hyperdeck - Recording - Not Much Time"
|
||||
.to_string(),
|
||||
ip: IpAddr::V4(Ipv4Addr::new(192, 168, 10, 2)),
|
||||
status: HyperdeckStatus::Connected,
|
||||
recording_status: RecordingState::Recording,
|
||||
slots: vec![(
|
||||
0usize,
|
||||
HyperdeckRecordBay {
|
||||
recording_time_remaining: 60,
|
||||
},
|
||||
)]
|
||||
.into_iter()
|
||||
.collect::<HashMap<usize, HyperdeckRecordBay>>(),
|
||||
},
|
||||
Hyperdeck {
|
||||
id: "test-3".to_string(),
|
||||
name: "Description: Connected Hyperdeck - Recording - Plenty of Time"
|
||||
.to_string(),
|
||||
ip: IpAddr::V4(Ipv4Addr::new(192, 168, 10, 3)),
|
||||
status: HyperdeckStatus::Connected,
|
||||
recording_status: RecordingState::Recording,
|
||||
slots: vec![(
|
||||
0usize,
|
||||
HyperdeckRecordBay {
|
||||
recording_time_remaining: 60 * 30,
|
||||
},
|
||||
)]
|
||||
.into_iter()
|
||||
.collect::<HashMap<usize, HyperdeckRecordBay>>(),
|
||||
},
|
||||
Hyperdeck {
|
||||
id: "test-4".to_string(),
|
||||
name: "Description: Disconnected Hyperdeck".to_string(),
|
||||
ip: IpAddr::V4(Ipv4Addr::new(192, 168, 10, 4)),
|
||||
status: HyperdeckStatus::Disconnected,
|
||||
recording_status: RecordingState::NotRecording,
|
||||
slots: vec![(
|
||||
0usize,
|
||||
HyperdeckRecordBay {
|
||||
recording_time_remaining: 3600 * 5, // 5 Hours
|
||||
},
|
||||
)]
|
||||
.into_iter()
|
||||
.collect::<HashMap<usize, HyperdeckRecordBay>>(),
|
||||
},
|
||||
],
|
||||
websocket_message_queue: VecDeque::new(),
|
||||
ws_sender,
|
||||
|
@ -87,18 +127,14 @@ impl eframe::App for HyperdeckMonitorApp {
|
|||
name: hyperdeck.name,
|
||||
ip: hyperdeck.ip.parse().unwrap(),
|
||||
status: hyperdeck.connection_state.into(),
|
||||
recording_bays: vec![],
|
||||
recording_status: hyperdeck.recording_status,
|
||||
slots: hyperdeck.slots,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||
egui::menu::bar(ui, |ui| {
|
||||
egui::widgets::global_dark_light_mode_buttons(ui);
|
||||
});
|
||||
});
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
add_hyperdeck_panel(
|
||||
|
@ -118,11 +154,6 @@ impl eframe::App for HyperdeckMonitorApp {
|
|||
&mut self.websocket_message_queue,
|
||||
);
|
||||
});
|
||||
|
||||
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
||||
connection_status(ui);
|
||||
egui::warn_if_debug_build(ui);
|
||||
});
|
||||
});
|
||||
|
||||
if self.last_blink_change.elapsed().as_secs() >= 1 {
|
||||
|
@ -195,27 +226,41 @@ fn hyperdeck_list(
|
|||
));
|
||||
}
|
||||
});
|
||||
if !hyperdeck.recording_bays.is_empty()
|
||||
&& matches!(hyperdeck.status, HyperdeckStatus::Connected)
|
||||
{
|
||||
let recording_bays_text: RichText = "Recording Bays".into();
|
||||
ui.label(recording_bays_text.size(16.0).strong());
|
||||
for (index, bay) in hyperdeck.recording_bays.iter().enumerate() {
|
||||
ui.horizontal(|ui| {
|
||||
let bay_label: RichText = format!("Bay {}", index + 1).into();
|
||||
ui.label(bay_label.strong());
|
||||
match bay.status {
|
||||
RecordingStatus::Recording => ui.label("Recording"),
|
||||
RecordingStatus::NotRecording => ui.label("Not Recording"),
|
||||
};
|
||||
ui.label(format!(
|
||||
"Total Storage Capacity: {}GB",
|
||||
bay.storage_capacity_mb / 1000,
|
||||
));
|
||||
let time_remaining_text: RichText =
|
||||
format!("Time remaining: {}", bay.recording_time_remaining).into();
|
||||
if matches!(hyperdeck.status, HyperdeckStatus::Connected) {
|
||||
ui.horizontal(|ui| {
|
||||
match hyperdeck.recording_status {
|
||||
RecordingState::Recording => {
|
||||
let (response, painter) =
|
||||
ui.allocate_painter(Vec2 { x: 16.0, y: 16.0 }, Sense::hover());
|
||||
let rect = response.rect;
|
||||
painter.rect(
|
||||
rect,
|
||||
Rounding::ZERO,
|
||||
Color32::from_rgb(255, 255, 255),
|
||||
Stroke::NONE,
|
||||
);
|
||||
let recording_text: RichText = "[Recording]".into();
|
||||
ui.label(
|
||||
recording_text
|
||||
.color(Color32::from_rgb(255, 255, 255))
|
||||
.strong(),
|
||||
);
|
||||
}
|
||||
RecordingState::NotRecording => {
|
||||
ui.label("[Not Recording]");
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
if bay.recording_time_remaining.0 > 15 * 60 || !blink {
|
||||
for (index, slot) in hyperdeck.slots.iter() {
|
||||
ui.horizontal(|ui| {
|
||||
let slot_label: RichText = format!("Slot {}", index + 1).into();
|
||||
ui.label(slot_label.strong());
|
||||
|
||||
let time_remaining_text: RichText =
|
||||
format!("Time remaining: {}", slot.recording_time_remaining).into();
|
||||
|
||||
if slot.recording_time_remaining > 15 * 60 || !blink {
|
||||
ui.label(time_remaining_text);
|
||||
} else {
|
||||
ui.label(time_remaining_text.color(Color32::RED));
|
||||
|
@ -228,20 +273,14 @@ fn hyperdeck_list(
|
|||
}
|
||||
}
|
||||
|
||||
fn connection_status(ui: &mut egui::Ui) {
|
||||
ui.horizontal(|ui| {
|
||||
// TODO: Make it real
|
||||
ui.label("Connected");
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
struct Hyperdeck {
|
||||
id: String,
|
||||
name: String,
|
||||
ip: IpAddr,
|
||||
status: HyperdeckStatus,
|
||||
recording_bays: Vec<HyperdeckRecordBay>,
|
||||
recording_status: RecordingState,
|
||||
slots: HashMap<usize, HyperdeckRecordBay>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
|
@ -258,28 +297,3 @@ impl From<HyperdeckConnectionState> for HyperdeckStatus {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
struct HyperdeckRecordBay {
|
||||
status: RecordingStatus,
|
||||
/// Storage capacity in MB.
|
||||
storage_capacity_mb: u64,
|
||||
/// Recording time available in seconds.
|
||||
recording_time_remaining: TimeRemaining,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
struct TimeRemaining(u64);
|
||||
|
||||
impl Display for TimeRemaining {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let time = hrtime::from_sec_padded(self.0);
|
||||
write!(f, "{time}")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
enum RecordingStatus {
|
||||
Recording,
|
||||
NotRecording,
|
||||
}
|
||||
|
|
73
index.ts
73
index.ts
|
@ -1,5 +1,6 @@
|
|||
import { Hyperdeck, Commands } from 'hyperdeck-connection';
|
||||
import WebSocket from 'ws';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
interface WrappedHyperdeck {
|
||||
ip: String,
|
||||
|
@ -26,8 +27,11 @@ type WebSocketMessage = {
|
|||
|
||||
const wss = new WebSocket.Server({ port: 7867 });
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.on('message', function message(data) {
|
||||
const connected_clients: Map<string, WebSocket> = new Map();
|
||||
|
||||
wss.on('connection', (ws) => {
|
||||
const clientId = uuidv4();
|
||||
ws.on('message', (data) => {
|
||||
try {
|
||||
const message = JSON.parse(data.toString()) as Partial<WebSocketMessage>;
|
||||
handle_message(message)
|
||||
|
@ -35,11 +39,16 @@ wss.on('connection', function connection(ws) {
|
|||
return;
|
||||
}
|
||||
});
|
||||
ws.on('close', () => {
|
||||
connected_clients.delete(clientId)
|
||||
})
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
event: "log",
|
||||
message: "Hello"
|
||||
}));
|
||||
|
||||
connected_clients.set(clientId, ws);
|
||||
});
|
||||
|
||||
function exhaustiveMatch(_never: never) {
|
||||
|
@ -68,24 +77,64 @@ function handle_message(message: Partial<WebSocketMessage>) {
|
|||
hyperdeck: newHyperdeck
|
||||
});
|
||||
|
||||
newHyperdeck.on('connected', (info) => {
|
||||
console.log(JSON.stringify(info))
|
||||
newHyperdeck.on('connected', (_info) => {
|
||||
notifyClients({
|
||||
event: "hyperdeck_connected",
|
||||
id: message.id
|
||||
})
|
||||
|
||||
newHyperdeck.sendCommand(new Commands.TransportInfoCommand()).then((transportInfo) => {
|
||||
console.log(JSON.stringify(transportInfo))
|
||||
setInterval(() => {
|
||||
newHyperdeck.sendCommand(new Commands.TransportInfoCommand()).then((transportInfo) => {
|
||||
notifyClients({
|
||||
event: "record_state",
|
||||
hyperdeckId: message.id,
|
||||
state: transportInfo.status,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
newHyperdeck.sendCommand(new Commands.DeviceInfoCommand()).then((info) => {
|
||||
for (let index = 0; index < info.slots; index++) {
|
||||
setInterval(() => {
|
||||
newHyperdeck.sendCommand(new Commands.SlotInfoCommand(index)).then((slot) => {
|
||||
notifyClients({
|
||||
event: "record_time_remaining",
|
||||
hyperdeckId: message.id,
|
||||
slotId: slot.slotId,
|
||||
remaining: slot.recordingTime
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
newHyperdeck.on('notify.slot', function (state) {
|
||||
console.log(JSON.stringify(state)) // catch the slot state change.
|
||||
newHyperdeck.on('notify.slot', function (slot) {
|
||||
notifyClients({
|
||||
event: "record_time_remaining",
|
||||
hyperdeckId: message.id,
|
||||
slotId: slot.slotId,
|
||||
remaining: slot.recordingTime
|
||||
})
|
||||
})
|
||||
newHyperdeck.on('notify.transport', function (state) {
|
||||
console.log(JSON.stringify(state)) // catch the transport state change.
|
||||
notifyClients({
|
||||
event: "record_state",
|
||||
hyperdeckId: message.id,
|
||||
state: state.status
|
||||
})
|
||||
})
|
||||
newHyperdeck.on('error', (err) => {
|
||||
console.log('Hyperdeck error', JSON.stringify(err))
|
||||
})
|
||||
|
||||
newHyperdeck.on('disconnected', () => {
|
||||
notifyClients({
|
||||
event: "hyperdeck_disconnected",
|
||||
id: message.id
|
||||
})
|
||||
})
|
||||
|
||||
newHyperdeck.connect(message.ip, message.port)
|
||||
|
||||
break;
|
||||
|
@ -105,3 +154,9 @@ function handle_message(message: Partial<WebSocketMessage>) {
|
|||
exhaustiveMatch(message)
|
||||
}
|
||||
}
|
||||
|
||||
function notifyClients(message: object) {
|
||||
connected_clients.forEach((client) => {
|
||||
client.send(JSON.stringify(message))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"hyperdeck-connection": "^2.0.1",
|
||||
"uuid": "^9.0.1",
|
||||
"ws": "^8.17.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -75,6 +76,18 @@
|
|||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.17.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz",
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"hyperdeck-connection": "^2.0.1",
|
||||
"uuid": "^9.0.1",
|
||||
"ws": "^8.17.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -4,7 +4,6 @@ use axum::response::Html;
|
|||
use axum::Json;
|
||||
use axum::{
|
||||
body::Bytes,
|
||||
extract::Path,
|
||||
http::{header, HeaderValue, Method},
|
||||
response::IntoResponse,
|
||||
routing::get,
|
||||
|
@ -66,7 +65,7 @@ pub async fn initialize_api(
|
|||
|
||||
let clients = state_clients.lock().await;
|
||||
let state_json = serde_json::to_string(&ServerEvent::HyperdeckMonitorState(
|
||||
hyperdeck_monitor_state.into(),
|
||||
hyperdeck_monitor_state,
|
||||
))
|
||||
.unwrap();
|
||||
for (_, client) in clients.iter() {
|
||||
|
|
|
@ -40,6 +40,9 @@ pub struct HyperdeckState {
|
|||
pub ip: String,
|
||||
pub port: u16,
|
||||
pub connection_state: HyperdeckConnectionState,
|
||||
pub recording_status: RecordingState,
|
||||
// HashMap to allow for sparse entries.
|
||||
pub slots: HashMap<usize, HyperdeckRecordBay>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
@ -47,3 +50,15 @@ pub enum HyperdeckConnectionState {
|
|||
Connected,
|
||||
Disconnected,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum RecordingState {
|
||||
Recording,
|
||||
NotRecording,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HyperdeckRecordBay {
|
||||
/// Recording time available in seconds.
|
||||
pub recording_time_remaining: u64,
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ pub async fn client_connection(
|
|||
|
||||
let current_state = state.read().await.clone();
|
||||
let state_json =
|
||||
serde_json::to_string(&ServerEvent::HyperdeckMonitorState(current_state.into())).unwrap();
|
||||
serde_json::to_string(&ServerEvent::HyperdeckMonitorState(current_state)).unwrap();
|
||||
client_sender.send(Message::Text(state_json.clone())).ok();
|
||||
|
||||
client.sender = Some(client_sender);
|
||||
|
|
85
src/main.rs
85
src/main.rs
|
@ -1,8 +1,8 @@
|
|||
use std::{process::Stdio, time::Duration};
|
||||
use std::{collections::HashMap, process::Stdio, time::Duration};
|
||||
|
||||
use api::message::{
|
||||
AddHyperdeckRequest, ClientRequest, HyperdeckConnectionState, HyperdeckMonitorState,
|
||||
HyperdeckState, RemoveHyperdeckRequest,
|
||||
HyperdeckRecordBay, HyperdeckState, RecordingState, RemoveHyperdeckRequest,
|
||||
};
|
||||
use color_eyre::Report;
|
||||
use futures_util::{
|
||||
|
@ -31,9 +31,8 @@ async fn main() {
|
|||
|
||||
let (node_ws_message_tx, node_ws_message_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let (node_commands_tx, node_commands_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let state = AppState::default();
|
||||
let node_ws_communication =
|
||||
talk_to_node_ws(state, node_ws_message_tx, node_commands_rx, cancel.clone()).fuse();
|
||||
talk_to_node_ws(node_ws_message_tx, node_commands_rx, cancel.clone()).fuse();
|
||||
|
||||
let (state_tx, state_rx) = tokio::sync::broadcast::channel(1);
|
||||
let (client_request_tx, client_request_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
|
@ -67,7 +66,7 @@ async fn main() {
|
|||
async fn run(
|
||||
mut node_commands_tx: tokio::sync::mpsc::UnboundedSender<NodeWsCommand>,
|
||||
mut node_ws_message_rx: tokio::sync::mpsc::UnboundedReceiver<NodeWsMessageReceived>,
|
||||
mut state_tx: tokio::sync::broadcast::Sender<HyperdeckMonitorState>,
|
||||
state_tx: tokio::sync::broadcast::Sender<HyperdeckMonitorState>,
|
||||
mut client_request_rx: tokio::sync::mpsc::UnboundedReceiver<ClientRequest>,
|
||||
cancel: CancellationToken,
|
||||
) {
|
||||
|
@ -100,7 +99,7 @@ async fn run(
|
|||
|
||||
async fn handle_message_from_node(
|
||||
msg: NodeWsMessageReceived,
|
||||
node_commands_tx: &mut tokio::sync::mpsc::UnboundedSender<NodeWsCommand>,
|
||||
_node_commands_tx: &mut tokio::sync::mpsc::UnboundedSender<NodeWsCommand>,
|
||||
state: &mut HyperdeckMonitorState,
|
||||
) -> bool {
|
||||
match msg {
|
||||
|
@ -120,6 +119,38 @@ async fn handle_message_from_node(
|
|||
});
|
||||
true
|
||||
}
|
||||
NodeWsMessageReceived::RecordState {
|
||||
hyperdeck_id,
|
||||
status,
|
||||
} => {
|
||||
if let Some(hyperdeck) = state.hyperdecks.get_mut(&hyperdeck_id) {
|
||||
hyperdeck.recording_status = if matches!(status, TransportStatus::Record) {
|
||||
RecordingState::Recording
|
||||
} else {
|
||||
RecordingState::NotRecording
|
||||
};
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
NodeWsMessageReceived::RecordTimeRemaining {
|
||||
hyperdeck_id,
|
||||
slot_id,
|
||||
remaining,
|
||||
} => {
|
||||
if let Some(hyperdeck) = state.hyperdecks.get_mut(&hyperdeck_id) {
|
||||
hyperdeck
|
||||
.slots
|
||||
.entry(slot_id)
|
||||
.or_insert(HyperdeckRecordBay {
|
||||
recording_time_remaining: remaining,
|
||||
});
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,6 +170,8 @@ async fn handle_message_from_client(
|
|||
ip: ip.clone(),
|
||||
port,
|
||||
connection_state: api::message::HyperdeckConnectionState::Disconnected,
|
||||
recording_status: api::message::RecordingState::NotRecording,
|
||||
slots: HashMap::new(),
|
||||
},
|
||||
);
|
||||
let _ = node_commands_tx.send(NodeWsCommand::AddHyperdeck(AddHyperdeckCommand {
|
||||
|
@ -210,9 +243,6 @@ async fn run_node_process(cancel: CancellationToken) {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct AppState {}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
enum NodeWsCommand {
|
||||
|
@ -223,12 +253,40 @@ enum NodeWsCommand {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[serde(tag = "event")]
|
||||
enum NodeWsMessageReceived {
|
||||
Log { message: String },
|
||||
HyperdeckConnected { id: String },
|
||||
HypderdeckDisconnected { id: String },
|
||||
Log {
|
||||
message: String,
|
||||
},
|
||||
HyperdeckConnected {
|
||||
id: String,
|
||||
},
|
||||
HypderdeckDisconnected {
|
||||
id: String,
|
||||
},
|
||||
RecordState {
|
||||
hyperdeck_id: String,
|
||||
status: TransportStatus,
|
||||
},
|
||||
RecordTimeRemaining {
|
||||
hyperdeck_id: String,
|
||||
slot_id: usize,
|
||||
remaining: u64,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
enum TransportStatus {
|
||||
Preview,
|
||||
Stopped,
|
||||
Play,
|
||||
Forward,
|
||||
Rewind,
|
||||
Jog,
|
||||
Shuttle,
|
||||
Record,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
@ -246,7 +304,6 @@ struct RemoveHyperdeckCommand {
|
|||
}
|
||||
|
||||
async fn talk_to_node_ws(
|
||||
state: AppState,
|
||||
ws_message_tx: tokio::sync::mpsc::UnboundedSender<NodeWsMessageReceived>,
|
||||
commands_rx: tokio::sync::mpsc::UnboundedReceiver<NodeWsCommand>,
|
||||
cancel: CancellationToken,
|
||||
|
|
Loading…
Reference in New Issue