Implement chunking
This commit is contained in:
parent
29c4cacbbb
commit
3b61210761
5 changed files with 60 additions and 34 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::protocol::Message;
|
use crate::protocol::Message;
|
||||||
use crate::sound_scheduler::SoundScheduler;
|
use crate::sound_scheduler::SoundScheduler;
|
||||||
use std::io::Read;
|
|
||||||
use std::net::{TcpListener, TcpStream};
|
use std::net::{TcpListener, TcpStream};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
|
|
@ -9,14 +8,19 @@ pub struct ClientHandler;
|
||||||
impl ClientHandler {
|
impl ClientHandler {
|
||||||
fn handle_client(mut stream: TcpStream) {
|
fn handle_client(mut stream: TcpStream) {
|
||||||
println!("Handling client: {:?}", stream);
|
println!("Handling client: {:?}", stream);
|
||||||
let mut buf: Vec<u8> = Vec::new();
|
loop {
|
||||||
stream
|
match bincode::deserialize_from::<&mut TcpStream, Message>(&mut stream) {
|
||||||
.read_to_end(buf.as_mut())
|
Ok(message) => {
|
||||||
.expect("Could not read from stream");
|
match message {
|
||||||
let message = bincode::deserialize::<Message>(&buf).expect("Could not deserialize message");
|
Message::PlaySound(play_sound) => {
|
||||||
match message {
|
SoundScheduler::handle_scheduled_sound(play_sound);
|
||||||
Message::PlaySound(play_sound) => {
|
}
|
||||||
SoundScheduler::handle_scheduled_sound(play_sound);
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error deserializing message: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,41 +1,60 @@
|
||||||
use std::io::{BufReader, Read};
|
use std::io::BufReader;
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use std::time::SystemTime;
|
use std::time::{Duration, SystemTime};
|
||||||
use std::{fs::File, io::Write};
|
use std::{fs::File, io::Write};
|
||||||
|
|
||||||
|
use rodio::{Decoder, Source};
|
||||||
|
|
||||||
use crate::protocol::{Message, PlaySound};
|
use crate::protocol::{Message, PlaySound};
|
||||||
|
|
||||||
pub struct Dispatcher;
|
pub struct Dispatcher;
|
||||||
|
|
||||||
impl Dispatcher {
|
impl Dispatcher {
|
||||||
fn load_sound(path: String) -> Vec<u8> {
|
fn load_sound(path: String) -> Decoder<BufReader<File>> {
|
||||||
let file = BufReader::new(File::open(path).unwrap());
|
let file = BufReader::new(File::open(path).unwrap());
|
||||||
let data: Vec<u8> = file.bytes().map(|byte| byte.unwrap()).collect();
|
Decoder::new(file).unwrap()
|
||||||
data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_dispatch_sample(addrs: Vec<String>, sound_path: String) {
|
pub fn handle_dispatch_sample(addrs: Vec<String>, sound_path: String) {
|
||||||
let now = SystemTime::now()
|
let now = SystemTime::now()
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
.unwrap()
|
.unwrap();
|
||||||
.as_micros();
|
|
||||||
let timestamp = now + 10000000;
|
let source = Dispatcher::load_sound(sound_path).buffered();
|
||||||
let sound_data = Dispatcher::load_sound(sound_path);
|
|
||||||
let msg = Message::PlaySound(PlaySound {
|
let channels = source.channels();
|
||||||
timestamp: timestamp,
|
let sample_rate = source.sample_rate();
|
||||||
sound_data: sound_data,
|
let duration = source.total_duration().unwrap();
|
||||||
});
|
let chunk_len = Duration::from_secs(1);
|
||||||
|
|
||||||
|
let mut offset = Duration::from_secs(0);
|
||||||
|
|
||||||
for addr in addrs {
|
for addr in addrs {
|
||||||
if addr.is_empty() {
|
if addr.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
} else {
|
|
||||||
let mut sock = TcpStream::connect(addr).expect("Failed to connect");
|
let mut sock = TcpStream::connect(addr).expect("Failed to connect");
|
||||||
|
|
||||||
|
while offset < duration {
|
||||||
|
let sound_data = source
|
||||||
|
.clone()
|
||||||
|
.skip_duration(offset)
|
||||||
|
.take_duration(chunk_len)
|
||||||
|
.collect::<Vec<i16>>();
|
||||||
|
|
||||||
|
offset += chunk_len;
|
||||||
|
|
||||||
|
let msg = Message::PlaySound(PlaySound {
|
||||||
|
timestamp: (now + offset).as_micros(),
|
||||||
|
channels: channels,
|
||||||
|
sample_rate: sample_rate,
|
||||||
|
sound_data: sound_data,
|
||||||
|
});
|
||||||
|
|
||||||
let buf = bincode::serialize(&msg).expect("Failed to serialize");
|
let buf = bincode::serialize(&msg).expect("Failed to serialize");
|
||||||
sock.write_all(&buf).unwrap();
|
sock.write_all(&buf).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,7 @@ pub enum Message {
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct PlaySound {
|
pub struct PlaySound {
|
||||||
pub timestamp: u128,
|
pub timestamp: u128,
|
||||||
pub sound_data: Vec<u8>,
|
pub channels: u16,
|
||||||
|
pub sample_rate: u32,
|
||||||
|
pub sound_data: Vec<i16>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
use rodio::{Decoder, OutputStream, Sink};
|
use rodio::{buffer::SamplesBuffer, OutputStream, Sink};
|
||||||
use std::io::Cursor;
|
|
||||||
|
|
||||||
pub struct SoundPlayer;
|
pub struct SoundPlayer;
|
||||||
|
|
||||||
impl SoundPlayer {
|
impl SoundPlayer {
|
||||||
pub fn play_sound(sound_data: Vec<u8>) {
|
pub fn play_sound(channels: u16, sample_rate: u32, sound_data: Vec<i16>) {
|
||||||
let data = Cursor::new(sound_data);
|
// let data = Cursor::new(sound_data);
|
||||||
let source = Decoder::new(data).unwrap();
|
let source = SamplesBuffer::new(channels, sample_rate, sound_data);
|
||||||
|
|
||||||
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
|
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
|
||||||
let sink = Sink::try_new(&stream_handle).unwrap();
|
let sink = Sink::try_new(&stream_handle).unwrap();
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ impl SoundScheduler {
|
||||||
pub fn handle_scheduled_sound(play_msg: PlaySound) {
|
pub fn handle_scheduled_sound(play_msg: PlaySound) {
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let PlaySound {
|
let PlaySound {
|
||||||
|
channels,
|
||||||
|
sample_rate,
|
||||||
sound_data,
|
sound_data,
|
||||||
timestamp,
|
timestamp,
|
||||||
} = play_msg;
|
} = play_msg;
|
||||||
|
|
@ -28,7 +30,7 @@ impl SoundScheduler {
|
||||||
}
|
}
|
||||||
sleep(Duration::from_micros(wait as u64));
|
sleep(Duration::from_micros(wait as u64));
|
||||||
println!("Playing sound...");
|
println!("Playing sound...");
|
||||||
SoundPlayer::play_sound(sound_data);
|
SoundPlayer::play_sound(channels, sample_rate, sound_data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue