feat: ui now can close much safely

This commit is contained in:
Ahmet Kaan GÜMÜŞ 2024-05-01 03:27:34 +03:00
parent 38e71057d1
commit 83e0d40c0e
7 changed files with 174 additions and 59 deletions

View file

@ -195,12 +195,14 @@ async fn listener_handler(
}
Err(err_val) => {
eprintln!("Error: TCP WSS Listener | {}", err_val);
drop(listener_socket);
return;
}
}
}
Err(err_val) => {
eprintln!("Error: TCP TLS Listener | {}", err_val);
drop(listener_socket);
return;
}
}
@ -218,6 +220,7 @@ async fn listener_handler(
}
Err(err_val) => {
eprintln!("Error: TCP WS Listener | {}", err_val);
drop(listener_socket);
return;
}
}

View file

@ -1,14 +1,23 @@
use iced::{
widget::{container, row, Container},
Command,
window, Command, Subscription,
};
use tokio::sync::broadcast::{channel, Sender};
use tokio::sync::broadcast::{channel, Receiver, Sender};
use crate::{
gui_utils::button_with_centered_text, recording, streaming, utils::get_config, Config, BUFFER_LENGTH
gui_components::button_with_centered_text, gui_utils, recording, streaming, utils::get_config, Config, BUFFER_LENGTH
};
#[derive(Debug, Clone)]
struct Features {
stream: bool,
record: bool,
play_audio: bool,
}
#[derive(Debug, Clone)]
pub enum Event {
None,
Connect,
Disconnect,
Record,
@ -16,10 +25,13 @@ pub enum Event {
PlayAudio,
StopAudio,
LoadConfig(Config),
IcedEvent(iced::Event),
CloseWindow(window::Id)
}
#[derive(Debug, Clone)]
pub enum State {
None,
Connected,
Disconnected,
Recording,
@ -46,7 +58,7 @@ struct CommunicationChannel {
base_to_playing: Sender<bool>,
playing_to_base: Sender<bool>,
}
#[derive(Debug)]
#[derive(Debug, PartialEq)]
enum Condition {
Active,
Loading,
@ -97,6 +109,7 @@ impl Streamer {
pub fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::Event(event) => match event {
Event::None => Command::none(),
Event::Connect => {
println!("Connect");
self.gui_status.are_we_connect = Condition::Loading;
@ -124,21 +137,11 @@ impl Streamer {
Event::Disconnect => {
println!("Disconnect");
self.gui_status.are_we_connect = Condition::Loading;
let mut streaming_to_base_receiver =
self.communication_channel.streaming_to_base.subscribe();
let _ = self.communication_channel.base_to_streaming.send(false);
Command::perform(
async move {
match streaming_to_base_receiver.recv().await {
Ok(_) => State::Disconnected,
Err(err_val) => {
eprintln!("Error: Communication | {}", err_val);
State::Connected
}
}
},
Message::State,
)
let streaming_to_base = self.communication_channel.streaming_to_base.subscribe();
let base_to_streaming = self.communication_channel.base_to_streaming.clone();
Command::perform(async move {
gui_utils::disconnect(streaming_to_base, base_to_streaming).await
}, Message::State)
}
Event::Record => {
println!("Record");
@ -166,21 +169,11 @@ impl Streamer {
Event::StopRecord => {
println!("Stop Record");
self.gui_status.are_we_record = Condition::Loading;
let mut recording_to_base_receiver =
self.communication_channel.recording_to_base.subscribe();
let _ = self.communication_channel.base_to_recording.send(false);
Command::perform(
async move {
match recording_to_base_receiver.recv().await {
Ok(_) => State::StopRecording,
Err(err_val) => {
eprintln!("Error: Communication | Recording | {}", err_val);
State::Recording
}
}
},
Message::State,
)
let recording_to_base = self.communication_channel.recording_to_base.subscribe();
let base_to_recording = self.communication_channel.base_to_recording.clone();
Command::perform(async move {
gui_utils::stop_recording(recording_to_base, base_to_recording).await
}, Message::State)
}
Event::PlayAudio => {
println!("Play Audio");
@ -224,8 +217,25 @@ impl Streamer {
self.config = Some(config);
Command::none()
}
Event::IcedEvent(iced_event) => match iced_event {
iced::Event::Keyboard(_) => Command::none(),
iced::Event::Mouse(_) => Command::none(),
iced::Event::Window(id, window_event) => {
if let window::Event::CloseRequested = window_event {
self.exit(id)
} else {
Command::none()
}
}
iced::Event::Touch(_) => Command::none(),
iced::Event::PlatformSpecific(_) => Command::none(),
},
Event::CloseWindow(id) => {
window::close(id)
},
},
Message::State(state) => match state {
State::None => Command::none(),
State::Connected => {
self.gui_status.are_we_connect = Condition::Active;
Command::none()
@ -266,11 +276,11 @@ impl Streamer {
let record_button = match self.gui_status.are_we_record {
Condition::Active => {
button_with_centered_text("Stop Record").on_press(Message::Event(Event::StopRecord))
button_with_centered_text("Mute").on_press(Message::Event(Event::StopRecord))
}
Condition::Loading => button_with_centered_text("Processing"),
Condition::Passive => {
button_with_centered_text("Record").on_press(Message::Event(Event::Record))
button_with_centered_text("Unmute").on_press(Message::Event(Event::Record))
}
};
@ -289,6 +299,11 @@ impl Streamer {
.height(35);
container(content).height(300).center_x().center_y()
}
pub fn subscription(&self) -> Subscription<Message> {
iced::event::listen()
.map(Event::IcedEvent)
.map(Message::Event)
}
pub fn load_config() -> Command<Message> {
Command::perform(
async move {
@ -298,4 +313,54 @@ impl Streamer {
Message::Event,
)
}
}
fn call_closer(
streaming_to_base: Receiver<bool>,
base_to_streaming: Sender<bool>,
recording_to_base: Receiver<bool>,
base_to_recording: Sender<bool>,
playing_to_base: Receiver<bool>,
base_to_playing: Sender<bool>,
features_in_need: Features,
window_id: window::Id,
)-> Command<Message> {
Command::perform(async move {
if features_in_need.stream {
gui_utils::disconnect(streaming_to_base, base_to_streaming).await;
}
if features_in_need.record {
gui_utils::stop_recording(recording_to_base, base_to_recording).await;
}
if features_in_need.play_audio {
gui_utils::stop_playing_audio(playing_to_base, base_to_playing).await;
}
Event::CloseWindow(window_id)
}, Message::Event)
}
fn exit(&self, window_id: window::Id) -> Command<Message> {
let mut features_in_need = Features{
stream: false,
record: false,
play_audio: false,
};
if self.gui_status.are_we_connect == Condition::Active {
features_in_need.stream = true;
}
if self.gui_status.are_we_record == Condition::Active {
features_in_need.record = true;
}
if self.gui_status.are_we_play_audio == Condition::Active {
features_in_need.play_audio = true;
}
let streaming_to_base = self.communication_channel.streaming_to_base.subscribe();
let base_to_streaming = self.communication_channel.base_to_streaming.clone();
let recording_to_base = self.communication_channel.recording_to_base.subscribe();
let base_to_recording = self.communication_channel.base_to_recording.clone();
let playing_to_base = self.communication_channel.playing_to_base.subscribe();
let base_to_playing = self.communication_channel.base_to_playing.clone();
Self::call_closer(streaming_to_base, base_to_streaming, recording_to_base, base_to_recording, playing_to_base, base_to_playing, features_in_need, window_id)
}
}

View file

@ -0,0 +1,17 @@
use iced::{
alignment,
widget::{button, text, Button},
Length,
};
use crate::gui::Message;
pub fn button_with_centered_text(txt: &'static str) -> Button<'static, Message> {
button(
text(txt)
.width(Length::Fill)
.horizontal_alignment(alignment::Horizontal::Center),
)
.height(Length::Fill)
.width(Length::Fill)
}

View file

@ -1,17 +1,39 @@
use iced::{
alignment,
widget::{button, text, Button},
Length,
};
use tokio::sync::broadcast::{Receiver, Sender};
use crate::gui::Message;
use crate::gui::State;
pub async fn disconnect(mut streaming_to_base:Receiver<bool>, base_to_streaming:Sender<bool>) -> State {
let _ = base_to_streaming.send(false);
match streaming_to_base.recv().await {
Ok(_) => State::Disconnected,
Err(err_val) => {
eprintln!("Error: Communication | {}", err_val);
State::Connected
}
}
pub fn button_with_centered_text(txt: &'static str) -> Button<'static, Message> {
button(
text(txt)
.width(Length::Fill)
.horizontal_alignment(alignment::Horizontal::Center),
)
.height(Length::Fill)
.width(Length::Fill)
}
pub async fn stop_recording(mut recording_to_base:Receiver<bool>, base_to_recording:Sender<bool>) -> State {
let _ = base_to_recording.send(false);
match recording_to_base.recv().await {
Ok(_) => State::StopRecording,
Err(err_val) => {
eprintln!("Error: Communication | {}", err_val);
State::Recording
}
}
}
pub async fn stop_playing_audio(mut audio_to_base:Receiver<bool>, base_to_audio:Sender<bool>) -> State {
let _ = base_to_audio.send(false);
match audio_to_base.recv().await {
Ok(_) => State::StopRecording,
Err(err_val) => {
eprintln!("Error: Communication | {}", err_val);
State::Recording
}
}
}

View file

@ -1,4 +1,5 @@
pub mod gui;
pub mod gui_components;
pub mod gui_utils;
pub mod recording;
pub mod streaming;
@ -12,4 +13,4 @@ pub struct Config {
pub quality: u8,
pub latency: u16,
pub tls: bool,
}
}

View file

@ -1,11 +1,16 @@
use streamer::gui::Streamer;
#[tokio::main]
async fn main() -> iced::Result {
async fn main(){
println!("Hello, world!");
iced::program("Streamer GUI", Streamer::update, Streamer::view)
tokio::task::block_in_place(|| {
iced::program("Streamer GUI", Streamer::update, Streamer::view)
.centered()
.window_size((350.0, 400.0))
.load(Streamer::load_config)
.run()
.antialiasing(true)
.subscription(Streamer::subscription)
.exit_on_close_request(false)
.run().unwrap()
});
}

View file

@ -1,5 +1,5 @@
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use tokio::sync::broadcast::{Receiver, Sender};
use tokio::{sync::broadcast::{Receiver, Sender}, task};
pub async fn record(
sound_stream_sender: Sender<f32>,
@ -29,9 +29,11 @@ pub async fn record(
input_stream.play().unwrap();
println!("Recording Started");
tokio::spawn(let_the_base_know(recording_to_base.clone()));
while let Err(_) = base_to_recording.try_recv() {
std::thread::sleep(std::time::Duration::from_secs(1));
}
task::block_in_place(|| {
let _ = base_to_recording.blocking_recv();
});
input_stream.pause().unwrap();
tokio::spawn(let_the_base_know(recording_to_base.clone()));
println!("Recording Stopped");