#![windows_subsystem = "windows"] use std::{ collections::HashMap, io::{BufRead, BufReader, Write}, net::{TcpListener, TcpStream}, }; use quad_snd::*; fn main() { let ctx = AudioContext::new(); let sounds = std::fs::read_dir("sounds") .expect("cant read sounds") .flat_map(|f| { let p = f.ok()?.path(); let n = p.file_stem()?.to_string_lossy().into_owned(); Some(( n, Sound::load(&ctx, &std::fs::read(p).expect("can't load sound")), )) }) .collect::>(); let handle_request = |mut stream: TcpStream| { let mut lines = BufReader::new(&stream) .lines() .flatten() .take_while(|line| !line.is_empty()); let request_line = lines.next()?; let query = parse_query_from_request(request_line.as_str()); let kind = query.get("kind").cloned().unwrap_or("sound"); if let Some(sound) = sounds.get(kind) { sound.play(&ctx, PlaySoundParams::default()); } // exhaust connection to not get "connection reset by peer" lines.for_each(drop); // this never "fails" let response = "HTTP/1.1 200 OK\r\n\r\n"; let _ = stream.write_all(response.as_bytes()); Some(()) }; let port = std::env::var("PORT") .ok() .and_then(|p| p.parse::().ok()) .unwrap_or(8668); let listener = TcpListener::bind(("0.0.0.0", port)).expect("cant bind"); for stream in listener.incoming() { let Ok(stream) = stream else { continue; }; handle_request(stream); } } fn parse_query_from_request(request_line: &str) -> HashMap<&str, &str> { request_line .split_whitespace() .nth(1) .and_then(|path| path.split_once('?')) .map(|(_, query)| { query .split('&') .filter_map(|param| { if let Some((key, value)) = param.split_once('=') { Some((key, value)) } else if !param.is_empty() { Some((param, "")) } else { None } }) .collect() }) .unwrap_or_default() }