diff --git a/Cargo.toml b/Cargo.toml
index 5b046eb..23d486b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,9 +12,9 @@ yew = "0.17"
#yew = { path = "/home/rob/dev/yew/yew" }
yewtil = "0.3.1"
wasm-bindgen = "0.2"
-gloo-events = "0.1.0"
js-sys = "0.3.44"
futures = "0.3.5"
+cpal = { version = "0.12.1", features = ["wasm-bindgen"] }
wasm-bindgen-futures = "0.4"
console_error_panic_hook = "0.1.6"
@@ -27,3 +27,8 @@ features = [
"HtmlCanvasElement",
"CanvasRenderingContext2d",
]
+
+[profile.release]
+lto = true
+
+# TODO: add wee_alloc
diff --git a/Makefile b/Makefile
index fb16d85..96d9ed5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,5 @@
# Based on https://raw.githubusercontent.com/saschagrunert/webapp.rs/master/Makefile
-GENERAL_ARGS = --release
-FRONTEND_ARGS = $(GENERAL_ARGS)
-
.PHONY: \
build \
run
diff --git a/src/controls.rs b/src/controls.rs
index d493d70..9f684f7 100644
--- a/src/controls.rs
+++ b/src/controls.rs
@@ -1,3 +1,4 @@
+use super::player::Player;
use crate::agents::audio_agent::{self, AudioAgent};
use web_sys::HtmlInputElement;
use yew::agent::Dispatched;
@@ -52,6 +53,7 @@ impl Component for Controls {
+
}
}
diff --git a/src/lib.rs b/src/lib.rs
index a2d70af..829180d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,10 +10,13 @@ mod app;
mod canvas;
mod controls;
mod home;
+mod player;
mod utils;
#[wasm_bindgen(start)]
pub fn run_app() {
+ #[cfg(debug_assertions)]
panic::set_hook(Box::new(console_error_panic_hook::hook));
+
App::::new().mount_to_body();
}
diff --git a/src/player.rs b/src/player.rs
new file mode 100644
index 0000000..a0a405e
--- /dev/null
+++ b/src/player.rs
@@ -0,0 +1,114 @@
+use crate::agents::audio_agent::{self, AudioAgent};
+use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
+use cpal::{Device, SampleFormat, SampleRate, Stream, StreamConfig};
+use yew::agent::Dispatcher;
+use yew::prelude::*;
+use yew::services::ConsoleService;
+
+pub enum Status {
+ Stopped,
+ Playing,
+}
+
+pub struct Player {
+ link: ComponentLink,
+ status: Status,
+ stream: Option,
+ audio_agent: Dispatcher,
+}
+
+pub enum Msg {
+ Play,
+}
+
+impl Component for Player {
+ type Message = Msg;
+ type Properties = ();
+
+ fn create(_: Self::Properties, link: ComponentLink) -> Self {
+ Self {
+ link,
+ status: Status::Stopped,
+ stream: None,
+ audio_agent: AudioAgent::dispatcher(),
+ }
+ }
+
+ fn rendered(&mut self, first_render: bool) {}
+
+ fn update(&mut self, msg: Self::Message) -> ShouldRender {
+ match msg {
+ Msg::Play => self.handle_play_button_clicked(),
+ }
+ }
+
+ fn change(&mut self, _: Self::Properties) -> ShouldRender {
+ false
+ }
+
+ fn view(&self) -> Html {
+ html! {
+
+
+
+ }
+ }
+}
+
+impl Player {
+ fn play(&mut self) {
+ let host = cpal::default_host();
+ let device = host.default_output_device().unwrap();
+
+ // TODO: improve
+ let config = device
+ .supported_output_configs()
+ .unwrap()
+ .nth(1)
+ .unwrap()
+ .with_sample_rate(SampleRate(44100));
+
+ ConsoleService::log(&format!("Using output config: {:?}", config));
+
+ let stream = match config.sample_format() {
+ SampleFormat::F32 => Player::run::(&device, &config.into()),
+ SampleFormat::I16 => Player::run::(&device, &config.into()),
+ SampleFormat::U16 => Player::run::(&device, &config.into()),
+ };
+
+ self.stream = Some(stream);
+ }
+
+ fn run(device: &Device, config: &StreamConfig) -> Stream
+ where
+ T: cpal::Sample,
+ {
+ let err_fn = |err| ConsoleService::warn(&format!("an error occurred on stream: {}", err));
+
+ let stream = device
+ .build_output_stream(config, move |data: &mut [T], _| {}, err_fn)
+ .unwrap();
+
+ stream.play().unwrap();
+ stream
+ }
+
+ fn handle_play_button_clicked(&mut self) -> ShouldRender {
+ match self.status {
+ Status::Stopped => {
+ self.status = Status::Playing;
+ self.play();
+ }
+ Status::Playing => self.status = Status::Stopped,
+ }
+ true
+ }
+
+ fn button_text(&self) -> &str {
+ if let Status::Stopped = self.status {
+ "Play"
+ } else {
+ "Pause"
+ }
+ }
+}