From 5cb65f8bad5d218648c4d0d0492da9fd5360c997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20Kaan=20G=C3=9CM=C3=9C=C5=9E?= <96421894+Tahinli@users.noreply.github.com> Date: Wed, 27 Mar 2024 03:34:35 +0300 Subject: [PATCH] refactor: :recycle: front --- front/src/components.rs | 117 ++++++++++++++++ front/src/lib.rs | 3 + front/src/main.rs | 294 ++-------------------------------------- front/src/status.rs | 83 ++++++++++++ front/src/streaming.rs | 109 +++++++++++++++ 5 files changed, 321 insertions(+), 285 deletions(-) create mode 100644 front/src/components.rs create mode 100644 front/src/lib.rs create mode 100644 front/src/status.rs create mode 100644 front/src/streaming.rs diff --git a/front/src/components.rs b/front/src/components.rs new file mode 100644 index 0000000..ba15400 --- /dev/null +++ b/front/src/components.rs @@ -0,0 +1,117 @@ +use crate::status::{ + coin_status_check, server_status_check, Coin, CoinStatus, Server, ServerStatus, +}; +use dioxus::prelude::*; +use std::time::Duration; + +#[component] +pub fn server_status_renderer(server_address: String) -> Element { + let server_check_time = 1_u64; + let mut server_status = use_signal(move || ServerStatus { + status: Server::Unstable, + }); + let mut server_status_watchdog = use_signal(move || false); + let mut server_status_unstable = use_signal(move || false); + let _server_status_task: Coroutine<()> = use_coroutine(|_| async move { + loop { + tokio_with_wasm::tokio::time::sleep(Duration::from_secs(server_check_time)).await; + *server_status_watchdog.write() = true; + *server_status.write() = server_status_check(server_status, &server_address).await; + *server_status_watchdog.write() = false; + } + }); + let _server_status_watchdog_timer: Coroutine<()> = use_coroutine(|_| async move { + let mut watchdog_counter = 0_i8; + loop { + tokio_with_wasm::tokio::time::sleep(Duration::from_secs(2 * server_check_time + 1)) + .await; + if !server_status_watchdog() { + *server_status_unstable.write() = false; + } + if server_status_watchdog() { + for _i in 0..5 { + tokio_with_wasm::tokio::time::sleep(Duration::from_secs(1)).await; + if server_status_watchdog() { + watchdog_counter += 1; + } + } + } + if watchdog_counter > 4 { + *server_status_unstable.write() = true; + } + watchdog_counter = 0; + } + }); + rsx! { + if server_status_unstable() && server_status_watchdog() { + ShowServerStatus {server_status:ServerStatus{status:Server::Dead,}} + } + else { + ShowServerStatus {server_status:server_status()} + } + } +} + +#[component] +pub fn coin_status_renderer(server_address: String) -> Element { + let is_loading = use_signal(|| false); + let coin_result = use_signal(|| CoinStatus { status: Coin::Head }); + let call_coin = move |_| { + spawn({ + to_owned![is_loading]; + to_owned![coin_result]; + to_owned![server_address]; + is_loading.set(true); + async move { + match coin_status_check(&server_address).await { + Ok(coin_status) => { + is_loading.set(false); + coin_result.set(coin_status); + } + Err(_) => { + is_loading.set(false); + } + } + } + }); + }; + rsx! { + div { + button { + disabled: is_loading(), + onclick: call_coin, + "style":"width: 80px; height: 50px;", + if is_loading() { + "Loading" + }else { + "Coin Flip" + } + } + div { + ShowCoinStatus{ coin_status: coin_result().clone() } + } + } + } +} +#[component] +fn ShowServerStatus(server_status: ServerStatus) -> Element { + rsx! { + div { + div { class: "flex items-center", + span { "Server Status: " } + span { { server_status.status.to_string() } } + } + } + } +} +#[component] +fn ShowCoinStatus(coin_status: CoinStatus) -> Element { + rsx! { + div { + div { class: "flex items-center", + span { "Coin Status: " } + span { { coin_status.status.to_string() } } + } + } + } +} diff --git a/front/src/lib.rs b/front/src/lib.rs new file mode 100644 index 0000000..c59829e --- /dev/null +++ b/front/src/lib.rs @@ -0,0 +1,3 @@ +pub mod components; +pub mod status; +pub mod streaming; diff --git a/front/src/main.rs b/front/src/main.rs index 7872c74..cb147c7 100644 --- a/front/src/main.rs +++ b/front/src/main.rs @@ -1,53 +1,8 @@ -use std::mem::MaybeUninit; -use std::sync::Arc; -use std::time::Duration; -use ringbuf::{Consumer, HeapRb, Producer, SharedRb}; -use tokio_with_wasm::tokio; -use tokio_tungstenite_wasm::*; -use futures_util::*; use dioxus::prelude::*; -use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; -use serde::Deserialize; -use tokio_with_wasm::tokio::time::sleep; - -const SERVER_ADDRESS: &str = "https://tahinli.com.tr:2323"; - -#[derive(Debug, Clone, PartialEq, Deserialize)] -enum Server{ - Alive, - Unstable, - Dead, -} -impl Server { - fn to_string(&mut self) -> String{ - match self { - Self::Alive => {String::from("Alive")}, - Self::Unstable => {String::from("Unstable")}, - Self::Dead => {String::from("Dead")}, - } - } -} -#[derive(Debug, Clone, PartialEq, Deserialize)] -enum Coin{ - Tail, - Head, -} -impl Coin { - fn to_string(&mut self) -> String { - match self { - Self::Head => {String::from("Head")}, - Self::Tail => {String::from("Tail")}, - } - } -} -#[derive(Debug, Clone, PartialEq, Deserialize)] -struct ServerStatus { - status:Server, -} -#[derive(Debug, Clone, PartialEq, Deserialize)] -struct CoinStatus { - status:Coin, -} +use front::{ + components::{coin_status_renderer, server_status_renderer}, + streaming::start_listening, +}; fn main() { println!("Hello, world!"); @@ -55,60 +10,8 @@ fn main() { launch(app); } -async fn server_status_check(mut server_status:Signal) ->ServerStatus { - match reqwest::get(SERVER_ADDRESS).await { - Ok(response) => { - match response.json::().await { - Ok(_) => { - *server_status.write() = ServerStatus{status:Server::Alive,}; - ServerStatus{status:Server::Alive,} - } - Err(err_val) => { - *server_status.write() = ServerStatus{status:Server::Dead,}; - log::info!("{}", err_val); - ServerStatus{status:Server::Dead,} - } - } - } - Err(err_val) => { - *server_status.write() = ServerStatus{status:Server::Dead,}; - log::info!("{}", err_val); - ServerStatus{status:Server::Dead,} - } - } -} -async fn coin_status_check() -> Result { - Ok(reqwest::get(format!("{}{}", SERVER_ADDRESS, "/coin")).await.unwrap().json::().await.unwrap()) -} -async fn sound_stream(mut stream:WebSocketStream, mut producer: Producer>>>>) { - while let Some(msg) = stream.next().await { - match msg.unwrap().to_string().parse::() { - Ok(sound_data) => { - match producer.push(sound_data) { - Ok(_) => {}, - Err(_) => {}, - } - } - Err(_) =>{} - }; - } - log::info!("Connection Lost Sir"); -} -async fn start_listening() { - log::info!("Trying Sir"); - let connect_addr = "ws://127.0.0.1:2424"; - let stream = tokio_tungstenite_wasm::connect(connect_addr).await.unwrap(); - let ring = HeapRb::::new(1000000); - let (producer, consumer) = ring.split(); - let _sound_stream:Coroutine<()> = use_coroutine(|_| async move { - sound_stream(stream, producer).await; - }); - tokio_with_wasm::tokio::time::sleep(Duration::from_secs(1)).await; - let _listen:Coroutine<()> = use_coroutine(|_| async move { - listen(consumer).await; - }); -} fn app() -> Element { + let server_address = "https://tahinli.com.tr:2323".to_string(); rsx! { page_base {} div { @@ -118,12 +21,12 @@ fn app() -> Element { "Listen" } } - coin_status_renderer {} - server_status_renderer {} + coin_status_renderer {server_address:server_address.clone()} + server_status_renderer {server_address:server_address.clone()} } } -fn page_base() ->Element { +fn page_base() -> Element { rsx! { h1 { "Radioxide" @@ -134,186 +37,7 @@ fn page_base() ->Element { span { } } - + } } } - -fn err_fn(err: cpal::StreamError) { - eprintln!("Something Happened: {}", err); -} -pub async fn listen(mut consumer: Consumer>>>>) { - - log::info!("Hi"); - let host = cpal::default_host(); - let output_device = host.default_output_device().unwrap(); - let config:cpal::StreamConfig = output_device.default_output_config().unwrap().into(); - - let output_data_fn = move |data: &mut [f32], _:&cpal::OutputCallbackInfo| { - for sample in data { - *sample = match consumer.pop() { - Some(s) => s, - None => {0.0}, - }; - } - }; - - - let output_stream = output_device.build_output_stream(&config, output_data_fn, err_fn, None).unwrap(); - - output_stream.play().unwrap(); - sleep(Duration::from_secs(100)).await; - output_stream.pause().unwrap(); - // let host = cpal::default_host(); - // let devices = host.devices().unwrap(); - // for (_derive_index, device) in devices.enumerate() { - // log::info!("{:?}", device.name()); - // } - // let device = host.default_output_device().unwrap(); - - // let mut supported_config = device.supported_output_configs().unwrap(); - // let config = supported_config.next().unwrap().with_max_sample_rate(); - // log::info!("{:?}", config); - // match config.sample_format() { - // cpal::SampleFormat::I8 => {log::info!("i8")}, - // cpal::SampleFormat::I16 => {log::info!("i16")}, - // //cpal::SampleFormat::I24 => {log::info!("i24")}, - // cpal::SampleFormat::I32 => {log::info!("i32")}, - // //cpal::SampleFormat::I48 => {log::info!("i48")}, - // cpal::SampleFormat::I64 => {log::info!("i64")}, - // cpal::SampleFormat::U8 => {log::info!("u8")}, - // cpal::SampleFormat::U16 => {log::info!("u16")}, - // //cpal::SampleFormat::U24 => {log::info!("u24")}, - // cpal::SampleFormat::U32 => {log::info!("u32")}, - // //cpal::SampleFormat::U48 => {log::info!("u48")}, - // cpal::SampleFormat::U64 => {log::info!("u64")}, - // cpal::SampleFormat::F32 => {log::info!("f32"); - // run::(consumer, &device, &config.clone().into()).await.unwrap();}, - // cpal::SampleFormat::F64 => {log::info!("f64")}, - // sample_format => panic!("Unsupported sample format '{sample_format}'"), - // } - // let config:StreamConfig = config.into(); - // let stream = device.build_output_stream( - // &config, - // move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { - - // log::info!("{:?}", data); - // //I need to do something here, I think - // }, - // move |_err| { - - // }, - // None).unwrap(); - - // stream.play().unwrap(); - // tokio::time::sleep(Duration::from_secs(10)).await; - // stream.pause().unwrap(); - - -} -fn server_status_renderer() -> Element { - let server_check_time = 1_u64; - let mut server_status = use_signal(move || ServerStatus{status:Server::Unstable,}); - let mut server_status_watchdog = use_signal(move|| false); - let mut server_status_unstable = use_signal(move|| false); - let _server_status_task:Coroutine<()> = use_coroutine(|_| async move { - loop { - tokio::time::sleep(Duration::from_secs(server_check_time)).await; - *server_status_watchdog.write() = true; - *server_status.write() = server_status_check(server_status).await; - *server_status_watchdog.write() = false; - }; - }); - let _server_status_watchdog_timer:Coroutine<()> = use_coroutine(|_| async move { - let mut watchdog_counter = 0_i8; - loop { - tokio::time::sleep(Duration::from_secs(2*server_check_time+1)).await; - if !server_status_watchdog() { - *server_status_unstable.write() = false; - } - if server_status_watchdog() { - for _i in 0..5 { - tokio::time::sleep(Duration::from_secs(1)).await; - if server_status_watchdog() { - watchdog_counter += 1; - } - } - - } - if watchdog_counter > 4 { - *server_status_unstable.write() = true; - } - watchdog_counter = 0; - } - }); - rsx! { - if server_status_unstable() && server_status_watchdog() { - ShowServerStatus {server_status:ServerStatus{status:Server::Dead,}} - } - else { - ShowServerStatus {server_status:server_status()} - } - } - -} -fn coin_status_renderer() -> Element { - let is_loading = use_signal(|| false); - let coin_result = use_signal(|| CoinStatus{status:Coin::Head,}); - let call_coin = move |_| { - spawn({ - to_owned![is_loading]; - to_owned![coin_result]; - is_loading.set(true); - async move { - match coin_status_check().await { - Ok(coin_status) => { - is_loading.set(false); - coin_result.set(coin_status); - } - Err(_) => { - is_loading.set(false); - } - } - } - }); - }; - rsx! { - div { - button { - disabled: is_loading(), - onclick: call_coin, - "style":"width: 80px; height: 50px;", - if is_loading() { - "Loading" - }else { - "Coin Flip" - } - } - div { - ShowCoinStatus{ coin_status: coin_result().clone() } - } - } - } -} -#[component] -fn ShowServerStatus(server_status: ServerStatus) -> Element { - rsx! { - div { - div { class: "flex items-center", - span { "Server Status: " } - span { { server_status.status.to_string() } } - } - } - } -} -#[component] -fn ShowCoinStatus(coin_status: CoinStatus) -> Element { - rsx! { - div { - div { class: "flex items-center", - span { "Coin Status: " } - span { { coin_status.status.to_string() } } - } - } - } -} \ No newline at end of file diff --git a/front/src/status.rs b/front/src/status.rs new file mode 100644 index 0000000..029ecd1 --- /dev/null +++ b/front/src/status.rs @@ -0,0 +1,83 @@ +use dioxus::signals::{Signal, Writable}; +use serde::Deserialize; + +#[derive(Debug, Clone, PartialEq, Deserialize)] +pub enum Server { + Alive, + Unstable, + Dead, +} +impl Server { + pub fn to_string(&mut self) -> String { + match self { + Self::Alive => String::from("Alive"), + Self::Unstable => String::from("Unstable"), + Self::Dead => String::from("Dead"), + } + } +} +#[derive(Debug, Clone, PartialEq, Deserialize)] +pub enum Coin { + Tail, + Head, +} +impl Coin { + pub fn to_string(&mut self) -> String { + match self { + Self::Head => String::from("Head"), + Self::Tail => String::from("Tail"), + } + } +} +#[derive(Debug, Clone, PartialEq, Deserialize)] +pub struct ServerStatus { + pub status: Server, +} +#[derive(Debug, Clone, PartialEq, Deserialize)] +pub struct CoinStatus { + pub status: Coin, +} + +pub async fn server_status_check( + mut server_status: Signal, + server_address: &String, +) -> ServerStatus { + match reqwest::get(server_address).await { + Ok(response) => match response.json::().await { + Ok(_) => { + *server_status.write() = ServerStatus { + status: Server::Alive, + }; + ServerStatus { + status: Server::Alive, + } + } + Err(err_val) => { + *server_status.write() = ServerStatus { + status: Server::Dead, + }; + log::info!("{}", err_val); + ServerStatus { + status: Server::Dead, + } + } + }, + Err(err_val) => { + *server_status.write() = ServerStatus { + status: Server::Dead, + }; + log::info!("{}", err_val); + ServerStatus { + status: Server::Dead, + } + } + } +} +pub async fn coin_status_check(server_address: &String) -> Result { + Ok(reqwest::get(format!("{}{}", server_address, "/coin")) + .await + .unwrap() + .json::() + .await + .unwrap()) +} diff --git a/front/src/streaming.rs b/front/src/streaming.rs new file mode 100644 index 0000000..b8cd734 --- /dev/null +++ b/front/src/streaming.rs @@ -0,0 +1,109 @@ +use std::{mem::MaybeUninit, sync::Arc, time::Duration}; + +use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; +use dioxus::hooks::{use_coroutine, Coroutine}; +use futures_util::StreamExt; +use ringbuf::{Consumer, HeapRb, Producer, SharedRb}; +use tokio_tungstenite_wasm::WebSocketStream; +use tokio_with_wasm::tokio::time::sleep; + +pub async fn start_listening() { + log::info!("Trying Sir"); + let connect_addr = "ws://127.0.0.1:2424"; + let stream = tokio_tungstenite_wasm::connect(connect_addr).await.unwrap(); + let ring = HeapRb::::new(1000000); + let (producer, consumer) = ring.split(); + let _sound_stream: Coroutine<()> = use_coroutine(|_| async move { + sound_stream(stream, producer).await; + }); + tokio_with_wasm::tokio::time::sleep(Duration::from_secs(1)).await; + let _listen: Coroutine<()> = use_coroutine(|_| async move { + listen(consumer).await; + }); +} + +async fn sound_stream( + mut stream: WebSocketStream, + mut producer: Producer>>>>, +) { + while let Some(msg) = stream.next().await { + match msg.unwrap().to_string().parse::() { + Ok(sound_data) => match producer.push(sound_data) { + Ok(_) => {} + Err(_) => {} + }, + Err(_) => {} + }; + } + log::info!("Connection Lost Sir"); +} +async fn listen(mut consumer: Consumer>>>>) { + log::info!("Hi"); + let host = cpal::default_host(); + let output_device = host.default_output_device().unwrap(); + let config: cpal::StreamConfig = output_device.default_output_config().unwrap().into(); + + let output_data_fn = move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { + for sample in data { + *sample = match consumer.pop() { + Some(s) => s, + None => 0.0, + }; + } + }; + + let output_stream = output_device + .build_output_stream(&config, output_data_fn, err_fn, None) + .unwrap(); + + output_stream.play().unwrap(); + sleep(Duration::from_secs(100)).await; + output_stream.pause().unwrap(); + // let host = cpal::default_host(); + // let devices = host.devices().unwrap(); + // for (_derive_index, device) in devices.enumerate() { + // log::info!("{:?}", device.name()); + // } + // let device = host.default_output_device().unwrap(); + + // let mut supported_config = device.supported_output_configs().unwrap(); + // let config = supported_config.next().unwrap().with_max_sample_rate(); + // log::info!("{:?}", config); + // match config.sample_format() { + // cpal::SampleFormat::I8 => {log::info!("i8")}, + // cpal::SampleFormat::I16 => {log::info!("i16")}, + // //cpal::SampleFormat::I24 => {log::info!("i24")}, + // cpal::SampleFormat::I32 => {log::info!("i32")}, + // //cpal::SampleFormat::I48 => {log::info!("i48")}, + // cpal::SampleFormat::I64 => {log::info!("i64")}, + // cpal::SampleFormat::U8 => {log::info!("u8")}, + // cpal::SampleFormat::U16 => {log::info!("u16")}, + // //cpal::SampleFormat::U24 => {log::info!("u24")}, + // cpal::SampleFormat::U32 => {log::info!("u32")}, + // //cpal::SampleFormat::U48 => {log::info!("u48")}, + // cpal::SampleFormat::U64 => {log::info!("u64")}, + // cpal::SampleFormat::F32 => {log::info!("f32"); + // run::(consumer, &device, &config.clone().into()).await.unwrap();}, + // cpal::SampleFormat::F64 => {log::info!("f64")}, + // sample_format => panic!("Unsupported sample format '{sample_format}'"), + // } + // let config:StreamConfig = config.into(); + // let stream = device.build_output_stream( + // &config, + // move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { + + // log::info!("{:?}", data); + // //I need to do something here, I think + // }, + // move |_err| { + + // }, + // None).unwrap(); + + // stream.play().unwrap(); + // tokio::time::sleep(Duration::from_secs(10)).await; + // stream.pause().unwrap(); +} +fn err_fn(err: cpal::StreamError) { + eprintln!("Something Happened: {}", err); +}