Testing voice chat UDP
This commit is contained in:
@@ -66,10 +66,9 @@ pub fn connect_to_vc(
|
|||||||
|
|
||||||
let socket = UdpSocket::bind("0.0.0.0:0").map_err(|e| e.to_string())?;
|
let socket = UdpSocket::bind("0.0.0.0:0").map_err(|e| e.to_string())?;
|
||||||
socket.connect(&hostname).map_err(|e| e.to_string())?;
|
socket.connect(&hostname).map_err(|e| e.to_string())?;
|
||||||
socket.set_nonblocking(true).map_err(|e| e.to_string())?;
|
|
||||||
let socket = Arc::new(socket);
|
let socket = Arc::new(socket);
|
||||||
|
|
||||||
// Send the pin as the very first packet — this is your UDP "initialize"
|
// Send the pin as the very first packet — authenticates this UDP session
|
||||||
socket
|
socket
|
||||||
.send(&pin.to_be_bytes())
|
.send(&pin.to_be_bytes())
|
||||||
.map_err(|e| format!("Failed to send pincode: {e}"))?;
|
.map_err(|e| format!("Failed to send pincode: {e}"))?;
|
||||||
@@ -118,16 +117,17 @@ pub fn connect_to_vc(
|
|||||||
.build_input_stream(
|
.build_input_stream(
|
||||||
input_config,
|
input_config,
|
||||||
move |data: &[f32], _| {
|
move |data: &[f32], _| {
|
||||||
// convert f32 -> i16 PCM, prefix with pin, send over UDP
|
|
||||||
let pcm: Vec<i16> = data
|
let pcm: Vec<i16> = data
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| (s.clamp(-1.0, 1.0) * i16::MAX as f32) as i16)
|
.map(|s| (s.clamp(-1.0, 1.0) * i16::MAX as f32) as i16)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut packet = pin.to_be_bytes().to_vec();
|
let mut packet = Vec::with_capacity(pcm.len() * 2);
|
||||||
packet.extend(pcm.iter().flat_map(|s| s.to_be_bytes()));
|
for sample in &pcm {
|
||||||
|
packet.extend_from_slice(&sample.to_be_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
let _ = input_socket.send(&packet); // non-blocking, drop on failure
|
let _ = input_socket.send(&packet);
|
||||||
},
|
},
|
||||||
|err| eprintln!("Input stream error: {err}"),
|
|err| eprintln!("Input stream error: {err}"),
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub fn run() {
|
|||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_opener::init())
|
.plugin(tauri_plugin_opener::init())
|
||||||
.manage(ConfigState(Mutex::new(commands::config::Config::default())))
|
.manage(ConfigState(Mutex::new(commands::config::Config::default())))
|
||||||
|
.manage(commands::audio::VoiceState::default())
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
commands::server_list::save_server_list,
|
commands::server_list::save_server_list,
|
||||||
commands::server_list::get_server_list,
|
commands::server_list::get_server_list,
|
||||||
|
|||||||
@@ -206,6 +206,10 @@ export default class Enclave<P = Page> {
|
|||||||
server.messages[msg.channel_id][msg.message.id] = msg.message;
|
server.messages[msg.channel_id][msg.message.id] = msg.message;
|
||||||
this.forceRender();
|
this.forceRender();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case "JoinVoice":
|
||||||
|
server.voiceJoin && server.voiceJoin(msg.pin, msg.channel_id);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ export type ClientMethod =
|
|||||||
method: "MessageDeleted";
|
method: "MessageDeleted";
|
||||||
channel_id: string;
|
channel_id: string;
|
||||||
message_id: string;
|
message_id: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
method: "JoinVoice";
|
||||||
|
channel_id: string;
|
||||||
|
pin: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ServerMethod =
|
export type ServerMethod =
|
||||||
@@ -71,4 +76,8 @@ export type ServerMethod =
|
|||||||
method: "DeleteMessage";
|
method: "DeleteMessage";
|
||||||
channel_id: string;
|
channel_id: string;
|
||||||
message_id: string;
|
message_id: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
method: "JoinVoice";
|
||||||
|
channel_id: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export default class EnclaveServer {
|
|||||||
public meta?: ServerMeta;
|
public meta?: ServerMeta;
|
||||||
public messages: Record<string, Record<string, StoredMessage>>;
|
public messages: Record<string, Record<string, StoredMessage>>;
|
||||||
public users: Record<string, ClientMeta | null>;
|
public users: Record<string, ClientMeta | null>;
|
||||||
|
public voiceJoin?: (pin: number, channelId: string) => void;
|
||||||
|
|
||||||
public constructor(hostname: string, isSecure: boolean) {
|
public constructor(hostname: string, isSecure: boolean) {
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
|
|||||||
@@ -20,7 +20,19 @@ export default function VoiceChannel({
|
|||||||
lastChannelId.current = channel.id;
|
lastChannelId.current = channel.id;
|
||||||
|
|
||||||
invoke("disconnect_from_vc");
|
invoke("disconnect_from_vc");
|
||||||
invoke("connect_to_vc", { hostname });
|
|
||||||
|
if (channel.kind !== "voice" || !appRef.current?.server) return;
|
||||||
|
|
||||||
|
appRef.current.server.voiceJoin = (pin, channelId) => {
|
||||||
|
invoke("connect_to_vc", { hostname, pin, channelId }).catch(
|
||||||
|
console.error,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
appRef.current.server.websocket?.send({
|
||||||
|
method: "JoinVoice",
|
||||||
|
channel_id: channel.id,
|
||||||
|
});
|
||||||
}, [channel.id]);
|
}, [channel.id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { User, Palette, Mic, Volume2 } from "lucide-react";
|
import { User, Palette, Volume2 } from "lucide-react";
|
||||||
import { ProfileSettings } from "./ProfileSettings";
|
import { ProfileSettings } from "./ProfileSettings";
|
||||||
import { AppearanceSettings } from "./AppearanceSettings";
|
import { AppearanceSettings } from "./AppearanceSettings";
|
||||||
import { AudioVideoSettings } from "./AudioVideoSettings";
|
import { AudioVideoSettings } from "./AudioVideoSettings";
|
||||||
|
|||||||
Reference in New Issue
Block a user