Refactor everything
This commit is contained in:
parent
81ed297b2e
commit
d5a1897699
12 changed files with 144 additions and 181 deletions
BIN
audios/augh.mp3
Normal file
BIN
audios/augh.mp3
Normal file
Binary file not shown.
|
|
@ -1,31 +0,0 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
network_dispatcher::NetworkDispatcher, network_handler::NetworkHandler,
|
||||
sound_engine::SoundEngine,
|
||||
};
|
||||
|
||||
pub struct AppService {
|
||||
network_handler: NetworkHandler,
|
||||
network_dispatcher: NetworkDispatcher,
|
||||
}
|
||||
|
||||
impl AppService {
|
||||
pub fn new() -> Self {
|
||||
let sound_engine = Arc::new(SoundEngine::new());
|
||||
Self {
|
||||
network_handler: NetworkHandler::new(sound_engine.clone()),
|
||||
network_dispatcher: NetworkDispatcher::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dispatch_sample(&self) {
|
||||
self.network_dispatcher
|
||||
.dispatch_sound("localhost:3000".to_owned(), 1, "sound".to_owned())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn listen(&self) {
|
||||
self.network_handler.listen();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
37
src/client_handler.rs
Normal file
37
src/client_handler.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
use crate::protocol::Message;
|
||||
use crate::sound_scheduler::SoundScheduler;
|
||||
use std::io::Read;
|
||||
use std::net::{TcpListener, TcpStream};
|
||||
|
||||
pub struct ClientHandler;
|
||||
|
||||
impl ClientHandler {
|
||||
fn handle_client(mut stream: TcpStream) {
|
||||
println!("Handling client: {:?}", stream);
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
stream
|
||||
.read_to_end(buf.as_mut())
|
||||
.expect("Could not read from stream");
|
||||
let message = bincode::deserialize::<Message>(&buf).expect("Could not deserialize message");
|
||||
match message {
|
||||
Message::PlaySound(play_sound) => {
|
||||
SoundScheduler::handle_scheduled_sound(play_sound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn listen() {
|
||||
let listener = TcpListener::bind("127.0.0.1:3000").expect("Could not bind to address");
|
||||
|
||||
for stream in listener.incoming() {
|
||||
match stream {
|
||||
Ok(stream) => {
|
||||
ClientHandler::handle_client(stream);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/dispatcher.rs
Normal file
25
src/dispatcher.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
use std::io::Write;
|
||||
use std::net::TcpStream;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use crate::protocol::{Message, PlaySound};
|
||||
|
||||
pub struct Dispatcher;
|
||||
|
||||
impl Dispatcher {
|
||||
pub fn handle_dispatch_sample() {
|
||||
let now = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_micros();
|
||||
let timestamp = now + 10000000;
|
||||
let addr = "localhost:3000".to_owned();
|
||||
let msg = Message::PlaySound(PlaySound {
|
||||
timestamp: timestamp,
|
||||
sound_source: "augh.mp3".to_owned(),
|
||||
});
|
||||
let mut sock = TcpStream::connect(addr).expect("Failed to connect");
|
||||
let buf = bincode::serialize(&msg).expect("Failed to serialize");
|
||||
sock.write_all(&buf).unwrap();
|
||||
}
|
||||
}
|
||||
49
src/main.rs
49
src/main.rs
|
|
@ -1,21 +1,28 @@
|
|||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
|
||||
use client_handler::ClientHandler;
|
||||
use std::thread;
|
||||
use ui_app::UIApp;
|
||||
|
||||
use eframe::egui;
|
||||
use std::{sync::Arc, thread};
|
||||
|
||||
mod app_service;
|
||||
mod network_dispatcher;
|
||||
mod network_handler;
|
||||
mod client_handler;
|
||||
mod dispatcher;
|
||||
mod protocol;
|
||||
mod sound_engine;
|
||||
|
||||
use crate::app_service::AppService;
|
||||
mod sound_player;
|
||||
mod sound_scheduler;
|
||||
mod ui_app;
|
||||
|
||||
fn main() -> eframe::Result {
|
||||
let options = eframe::NativeOptions {
|
||||
viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
thread::spawn(move || {
|
||||
ClientHandler::listen();
|
||||
});
|
||||
|
||||
eframe::run_native(
|
||||
"My egui App",
|
||||
options,
|
||||
|
|
@ -27,31 +34,3 @@ fn main() -> eframe::Result {
|
|||
}),
|
||||
)
|
||||
}
|
||||
|
||||
struct UIApp {
|
||||
app_service: Arc<AppService>,
|
||||
}
|
||||
|
||||
impl Default for UIApp {
|
||||
fn default() -> Self {
|
||||
let app_service = Arc::new(AppService::new());
|
||||
|
||||
let app_service_listener = Arc::clone(&app_service);
|
||||
thread::spawn(move || {
|
||||
app_service_listener.listen();
|
||||
});
|
||||
|
||||
Self {
|
||||
app_service: app_service,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for UIApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.heading("My egui Application");
|
||||
ui.label("Hello");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
use std::{io::Write, net::TcpStream};
|
||||
|
||||
use crate::protocol::{Message, PlaySound};
|
||||
|
||||
pub struct NetworkDispatcher {}
|
||||
|
||||
impl NetworkDispatcher {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
pub fn dispatch_sound(&self, addr: String, timestamp: u128, sound_source: String) -> std::io::Result<()> {
|
||||
let msg = Message::PlaySound(PlaySound {
|
||||
timestamp: timestamp,
|
||||
sound_source: sound_source,
|
||||
});
|
||||
let mut sock = TcpStream::connect(addr).expect("Failed to connect");
|
||||
let buf = bincode::serialize(&msg).expect("Failed to serialize");
|
||||
sock.write_all(&buf)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
use std::{
|
||||
io::Read,
|
||||
net::{TcpListener, TcpStream},
|
||||
sync::Arc,
|
||||
thread::sleep,
|
||||
time::{Duration, SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
protocol::{Message, PlaySound},
|
||||
sound_engine::SoundEngine,
|
||||
};
|
||||
|
||||
pub struct NetworkHandler {
|
||||
sound_engine: Arc<SoundEngine>,
|
||||
}
|
||||
|
||||
impl NetworkHandler {
|
||||
pub fn new(sound_engine: Arc<SoundEngine>) -> Self {
|
||||
Self { sound_engine }
|
||||
}
|
||||
|
||||
fn handle_scheduled_sound(&self, play_msg: PlaySound) {
|
||||
let PlaySound {
|
||||
sound_source,
|
||||
timestamp,
|
||||
} = play_msg;
|
||||
println!("Scheduled sound: {:?} at {:?}", sound_source, timestamp);
|
||||
let now_micros = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("Could not get time")
|
||||
.as_micros();
|
||||
let wait = timestamp as i128 - now_micros as i128;
|
||||
if wait <= 0 {
|
||||
println!("Too late to play sound");
|
||||
return;
|
||||
}
|
||||
sleep(Duration::from_micros(wait as u64));
|
||||
println!("Playing sound: {:?}", sound_source);
|
||||
self.sound_engine.play_sound(sound_source);
|
||||
}
|
||||
|
||||
fn handle_client(&self, mut stream: TcpStream) {
|
||||
println!("Handling client: {:?}", stream);
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
stream
|
||||
.read_to_end(buf.as_mut())
|
||||
.expect("Could not read from stream");
|
||||
let message = bincode::deserialize::<Message>(&buf).expect("Could not deserialize message");
|
||||
match message {
|
||||
Message::PlaySound(play_sound) => {
|
||||
self.handle_scheduled_sound(play_sound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn listen(&self) {
|
||||
let listener = TcpListener::bind("127.0.0.1:3000").expect("Could not bind to address");
|
||||
|
||||
for stream in listener.incoming() {
|
||||
match stream {
|
||||
Ok(stream) => {
|
||||
self.handle_client(stream);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
use std::{fs::File, io::BufReader};
|
||||
|
||||
use rodio::{Decoder, OutputStream, OutputStreamHandle, Source};
|
||||
|
||||
pub struct SoundEngine {
|
||||
stream_handle: OutputStreamHandle,
|
||||
}
|
||||
|
||||
impl SoundEngine {
|
||||
pub fn new() -> Self {
|
||||
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
|
||||
Self { stream_handle }
|
||||
}
|
||||
|
||||
pub fn play_sound(&self, sound_source: String) {
|
||||
let path = format!("./audios/{}", sound_source);
|
||||
let file = BufReader::new(File::open(path).unwrap());
|
||||
let source = Decoder::new(file).unwrap();
|
||||
self.stream_handle
|
||||
.play_raw(source.convert_samples())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
17
src/sound_player.rs
Normal file
17
src/sound_player.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
use rodio::{Decoder, OutputStream, Sink};
|
||||
use std::{fs::File, io::BufReader};
|
||||
|
||||
pub struct SoundPlayer;
|
||||
|
||||
impl SoundPlayer {
|
||||
pub fn play_sound(sound_source: String) {
|
||||
let path = format!("./audios/{}", sound_source);
|
||||
let file = BufReader::new(File::open(path).unwrap());
|
||||
let source = Decoder::new(file).unwrap();
|
||||
|
||||
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
|
||||
let sink = Sink::try_new(&stream_handle).unwrap();
|
||||
sink.append(source);
|
||||
sink.sleep_until_end();
|
||||
}
|
||||
}
|
||||
28
src/sound_scheduler.rs
Normal file
28
src/sound_scheduler.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
use crate::protocol::PlaySound;
|
||||
use crate::sound_player::SoundPlayer;
|
||||
use std::thread::sleep;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
pub struct SoundScheduler;
|
||||
|
||||
impl SoundScheduler {
|
||||
pub fn handle_scheduled_sound(play_msg: PlaySound) {
|
||||
let PlaySound {
|
||||
sound_source,
|
||||
timestamp,
|
||||
} = play_msg;
|
||||
println!("Scheduled sound: {:?} at {:?}", sound_source, timestamp);
|
||||
let now_micros = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("Could not get time")
|
||||
.as_micros();
|
||||
let wait = timestamp as i128 - now_micros as i128;
|
||||
if wait <= 0 {
|
||||
println!("Too late to play sound");
|
||||
return;
|
||||
}
|
||||
sleep(Duration::from_micros(wait as u64));
|
||||
println!("Playing sound: {:?}", sound_source);
|
||||
SoundPlayer::play_sound(sound_source);
|
||||
}
|
||||
}
|
||||
23
src/ui_app.rs
Normal file
23
src/ui_app.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
use eframe::egui;
|
||||
|
||||
use crate::dispatcher::Dispatcher;
|
||||
|
||||
pub struct UIApp {}
|
||||
|
||||
impl Default for UIApp {
|
||||
fn default() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for UIApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.heading("My egui Application");
|
||||
ui.label("Hello");
|
||||
if ui.button("Dispatch sample").clicked() {
|
||||
Dispatcher::handle_dispatch_sample();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue