main
reng 4 months ago
parent 0e9de7931d
commit 023e3aeb52
  1. 7
      public/cuelist.json
  2. 36
      src-tauri/Cargo.lock
  3. 4
      src-tauri/Cargo.toml
  4. 34
      src-tauri/src/lib.rs
  5. 30
      src/App.jsx

@ -6,7 +6,8 @@
"type": "bg", "type": "bg",
"description": "preset bg", "description": "preset bg",
"audioFile": "assets/bg-02.mp3", "audioFile": "assets/bg-02.mp3",
"loop": true "loop": true,
"clientCue":"Q1"
}, },
{ {
"id": 2, "id": 2,
@ -16,6 +17,7 @@
"audioFile": "assets/bg-01 (小束袋).mp3", "audioFile": "assets/bg-01 (小束袋).mp3",
"loop": true, "loop": true,
"status":"reset" "status":"reset"
}, },
{ {
"id": 3, "id": 3,
@ -23,7 +25,8 @@
"type": "bg", "type": "bg",
"description": "during bg", "description": "during bg",
"loop": true, "loop": true,
"audioFile": "assets/bg-04.mp3" "audioFile": "assets/bg-04.mp3",
"clientCue":"Q2"
}, },
{ {
"id": 3.1, "id": 3.1,

36
src-tauri/Cargo.lock generated

@ -509,11 +509,14 @@ dependencies = [
name = "control-panel" name = "control-panel"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"dotenv",
"rosc",
"serde", "serde",
"serde_json", "serde_json",
"tauri", "tauri",
"tauri-build", "tauri-build",
"tauri-plugin-opener", "tauri-plugin-opener",
"tokio",
] ]
[[package]] [[package]]
@ -791,6 +794,12 @@ dependencies = [
"syn 2.0.106", "syn 2.0.106",
] ]
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]] [[package]]
name = "dpi" name = "dpi"
version = "0.1.2" version = "0.1.2"
@ -2004,6 +2013,12 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.8.9" version = "0.8.9"
@ -2101,6 +2116,16 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]] [[package]]
name = "num-conv" name = "num-conv"
version = "0.1.0" version = "0.1.0"
@ -2999,6 +3024,17 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "rosc"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd37602e1513794e952274082d074e8d31aa7f64d047e3acb746c91db40600a5"
dependencies = [
"byteorder",
"nom",
"time",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.26" version = "0.1.26"

@ -22,4 +22,6 @@ tauri = { version = "2", features = [] }
tauri-plugin-opener = "2" tauri-plugin-opener = "2"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
rosc = "0.11.4"
tokio = { version = "1.45.1", features = ["net"] }
dotenv = "0.15.0"

@ -1,4 +1,9 @@
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
use tokio::net::UdpSocket;
use std::{net::SocketAddrV4, str::FromStr};
use rosc::{encoder, OscMessage, OscPacket, OscType};
#[tauri::command] #[tauri::command]
fn greet(name: &str) -> String { fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name) format!("Hello, {}! You've been greeted from Rust!", name)
@ -8,7 +13,34 @@ fn greet(name: &str) -> String {
pub fn run() { pub fn run() {
tauri::Builder::default() tauri::Builder::default()
.plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_opener::init())
.invoke_handler(tauri::generate_handler![greet]) .invoke_handler(tauri::generate_handler![
send_osc_message,
])
.run(tauri::generate_context!()) .run(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application");
} }
#[tauri::command]
async fn send_osc_message(
key: &str,
message: &str,
host: &str,
target: &str,
) -> Result<(), String> {
// print
println!("Sending OSC message: {}", message);
let sock = UdpSocket::bind(host).await.unwrap();
let remote = SocketAddrV4::from_str(target).unwrap();
let msg_buf = encoder::encode(&OscPacket::Message(OscMessage {
addr: key.to_string(),
args: vec![OscType::String(message.parse().unwrap())],
}))
.unwrap();
sock.send_to(&msg_buf, remote).await.unwrap();
Ok(())
}

@ -1,5 +1,6 @@
import { useState, useEffect, useRef } from "react"; import { useState, useEffect, useRef } from "react";
import {Howl, Howler} from 'howler'; import {Howl, Howler} from 'howler';
import { invoke } from "@tauri-apps/api/core";
import "./App.css"; import "./App.css";
@ -29,6 +30,17 @@ function App() {
const refCue = useRef(null); const refCue = useRef(null);
const refNextCue = useRef(null); const refNextCue = useRef(null);
function sendOsc(addr, message){
invoke('send_osc_message', {
key: addr,
message,
host:'0.0.0.0:0',
target:'192.168.234.255:8000',
});
}
function onfade(e){ function onfade(e){
console.log('onfade', e); console.log('onfade', e);
@ -37,6 +49,11 @@ function App() {
refNextCue.current = null; refNextCue.current = null;
} }
if(refAudioBg.current.volume() === 0) {
refAudioBg.current.stop();
// refAudioBg.current = null;
}
} }
function onAnounceFade(e){ function onAnounceFade(e){
console.log('onAnounceFade', e); console.log('onAnounceFade', e);
@ -116,6 +133,12 @@ function App() {
console.warn('Unknown cue type:', type); console.warn('Unknown cue type:', type);
} }
if(props.clientCue){
sendOsc('/playcue', props.clientCue);
}
} }
function stop() { function stop() {
console.log('Stop all audio'); console.log('Stop all audio');
@ -125,6 +148,9 @@ function App() {
if(refAudioAnnounce.current) { if(refAudioAnnounce.current) {
refAudioAnnounce.current.fade(1,0, fadeDuration*1000); refAudioAnnounce.current.fade(1,0, fadeDuration*1000);
} }
sendOsc('/stopcue','');
} }
function secondToTime(seconds) { function secondToTime(seconds) {
const minutes = Math.floor(seconds / 60); const minutes = Math.floor(seconds / 60);
@ -203,7 +229,7 @@ function App() {
<th>Type</th> <th>Type</th>
<th>Auto</th> <th>Auto</th>
<th>Audio / Due</th> <th>Audio / Due</th>
<th>clientCue</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -226,7 +252,7 @@ function App() {
<td>{EmojiType[type]}</td> <td>{EmojiType[type]}</td>
<td>{auto ? '⤵' : ''}</td> <td>{auto ? '⤵' : ''}</td>
<td>{audioFile || props.duration} {props.callback && `<${props.callback}>`}</td> <td>{audioFile || props.duration} {props.callback && `<${props.callback}>`}</td>
<td className={`${props.clientCue&& 'bg-green-300 rounded-full text-center font-[900]'}`}>{props.clientCue || ''}</td>
</tr> </tr>
))} ))}
</tbody> </tbody>

Loading…
Cancel
Save