radioxide/streamer/src/gui.rs

949 lines
36 KiB
Rust
Raw Normal View History

2024-07-23 04:11:10 +03:00
use std::{
cmp::max,
fs::File,
path::Path,
process::exit,
sync::{Arc, Mutex},
};
use iced::{
alignment,
2024-05-13 18:40:03 +03:00
widget::{column, container, row, scrollable, slider, text::LineHeight, Container, Rule},
2024-07-23 04:11:10 +03:00
window::{self},
Color, Length, Subscription, Task,
};
2024-07-23 04:11:10 +03:00
use tokio::sync::broadcast::{channel, Receiver, Sender};
use crate::{
gui_components::{button_with_centered_text, text_centered},
gui_utils::{self, change_audio_volume, change_microphone_volume},
utils::get_config,
Config, BUFFER_LENGTH,
};
2024-05-13 18:40:03 +03:00
const AUDIOS_PATH: &str = "audios";
const AUDIO_SCROLLABLE_BUTTON_SIZE: u16 = 35;
#[derive(Debug, Clone)]
pub enum Player {
Play,
Pause,
Stop,
}
#[derive(Debug, Clone)]
struct Features {
stream: bool,
record: bool,
play_audio: bool,
}
#[derive(Debug)]
2024-05-13 18:40:03 +03:00
struct AudioMiscellaneous {
file: Option<File>,
2024-05-13 18:40:03 +03:00
selected_file_name: String,
playing_file_name: String,
files: Option<Vec<String>>,
decoded_to_playing_sender: Option<Sender<f32>>,
}
#[derive(Debug, Clone)]
pub enum Event {
None,
Connect,
Disconnect,
Record,
StopRecord,
PlayAudio,
StopAudio,
PauseAudio,
ContinueAudio,
2024-05-13 18:40:03 +03:00
ChooseAudio(String),
ChangeMicrophoneVolume(f32),
ChangeAudioVolume(f32),
LoadConfig(Config),
2024-05-13 18:40:03 +03:00
ListFiles(Option<Vec<String>>),
IcedEvent(iced::Event),
CloseWindow(window::Id),
}
#[derive(Debug, Clone)]
pub enum State {
None,
Connected,
Disconnected,
Recording,
StopRecording,
PlayingAudio,
StopAudio,
PausedAudio,
ContinuedAudio,
MicrophoneVolumeChanged,
AudioVolumeChanged,
}
#[derive(Debug, Clone)]
pub enum Message {
Event(Event),
State(State),
}
#[derive(Debug)]
struct DataChannel {
microphone_stream_sender: Sender<f32>,
audio_stream_sender: Sender<f32>,
}
#[derive(Debug)]
struct CommunicationChannel {
base_to_streaming_sender: Sender<bool>,
streaming_to_base_sender: Sender<bool>,
streaming_to_base_is_finished: Sender<bool>,
base_to_recording_sender: Sender<bool>,
recording_to_base_sender: Sender<bool>,
base_to_playing_sender: Sender<Player>,
playing_to_base_sender: Sender<Player>,
}
#[derive(Debug, PartialEq)]
enum Condition {
Active,
Loading,
Passive,
}
#[derive(Debug)]
struct ChangeableValue {
value: Arc<Mutex<f32>>,
}
#[derive(Debug)]
struct GUIStatus {
are_we_connect: Condition,
are_we_record: Condition,
are_we_play_audio: Condition,
are_we_paused_audio: Condition,
microphone_volume: ChangeableValue,
audio_volume: ChangeableValue,
}
#[derive(Debug)]
pub struct Streamer {
config: Option<Config>,
data_channel: DataChannel,
communication_channel: CommunicationChannel,
2024-05-13 18:40:03 +03:00
audio_miscellaneous: AudioMiscellaneous,
gui_status: GUIStatus,
}
impl Default for Streamer {
fn default() -> Self {
Self::new()
}
}
impl Streamer {
2024-07-23 04:11:10 +03:00
pub fn new_with_load() -> (Self, Task<Message>) {
(
Self {
config: None,
data_channel: DataChannel {
microphone_stream_sender: channel(BUFFER_LENGTH).0,
audio_stream_sender: channel(BUFFER_LENGTH).0,
},
communication_channel: CommunicationChannel {
base_to_streaming_sender: channel(1).0,
streaming_to_base_sender: channel(1).0,
streaming_to_base_is_finished: channel(1).0,
base_to_recording_sender: channel(1).0,
recording_to_base_sender: channel(1).0,
base_to_playing_sender: channel(1).0,
playing_to_base_sender: channel(1).0,
},
audio_miscellaneous: AudioMiscellaneous {
file: None,
selected_file_name: String::new(),
playing_file_name: String::new(),
files: None,
decoded_to_playing_sender: None,
},
gui_status: GUIStatus {
are_we_connect: Condition::Passive,
are_we_record: Condition::Passive,
are_we_play_audio: Condition::Passive,
are_we_paused_audio: Condition::Passive,
microphone_volume: ChangeableValue {
value: Arc::new(1.0.into()),
},
audio_volume: ChangeableValue {
value: Arc::new(1.0.into()),
},
},
},
Task::perform(
async move {
let config = get_config();
Event::LoadConfig(config)
},
Message::Event,
),
)
}
fn new() -> Self {
Self {
config: None,
data_channel: DataChannel {
microphone_stream_sender: channel(BUFFER_LENGTH).0,
audio_stream_sender: channel(BUFFER_LENGTH).0,
},
communication_channel: CommunicationChannel {
base_to_streaming_sender: channel(1).0,
streaming_to_base_sender: channel(1).0,
streaming_to_base_is_finished: channel(1).0,
base_to_recording_sender: channel(1).0,
recording_to_base_sender: channel(1).0,
base_to_playing_sender: channel(1).0,
playing_to_base_sender: channel(1).0,
},
2024-05-13 18:40:03 +03:00
audio_miscellaneous: AudioMiscellaneous {
file: None,
2024-05-13 18:40:03 +03:00
selected_file_name: String::new(),
playing_file_name: String::new(),
files: None,
decoded_to_playing_sender: None,
},
gui_status: GUIStatus {
are_we_connect: Condition::Passive,
are_we_record: Condition::Passive,
are_we_play_audio: Condition::Passive,
are_we_paused_audio: Condition::Passive,
microphone_volume: ChangeableValue {
value: Arc::new(1.0.into()),
},
audio_volume: ChangeableValue {
value: Arc::new(1.0.into()),
},
},
}
}
2024-07-23 04:11:10 +03:00
pub fn update(&mut self, message: Message) -> Task<Message> {
match message {
Message::Event(event) => match event {
2024-07-23 04:11:10 +03:00
Event::None => Task::none(),
Event::Connect => {
println!("Connect");
self.gui_status.are_we_connect = Condition::Loading;
let microphone_stream_receiver =
self.data_channel.microphone_stream_sender.subscribe();
let audio_stream_receiver = self.data_channel.audio_stream_sender.subscribe();
let streamer_config = self.config.clone().unwrap();
let streaming_to_base_sender =
self.communication_channel.streaming_to_base_sender.clone();
let base_to_streaming_receiver = self
.communication_channel
.base_to_streaming_sender
.subscribe();
let microphone_stream_volume = self.gui_status.microphone_volume.value.clone();
let audio_stream_volume = self.gui_status.audio_volume.value.clone();
let streaming_to_base_sender_is_finished = self
.communication_channel
.streaming_to_base_is_finished
.clone();
let streaming_to_base_receiver_is_streaming_finished = self
.communication_channel
.streaming_to_base_is_finished
.subscribe();
let streaming_to_base_receiver_is_streaming_stopped = self
.communication_channel
.streaming_to_base_sender
.subscribe();
2024-07-23 04:11:10 +03:00
let connect_command = Task::perform(
async move {
gui_utils::connect(
microphone_stream_receiver,
audio_stream_receiver,
streamer_config,
streaming_to_base_sender,
base_to_streaming_receiver,
streaming_to_base_sender_is_finished,
microphone_stream_volume,
audio_stream_volume,
)
.await
},
Message::State,
);
2024-07-23 04:11:10 +03:00
let is_streaming_finished_command = Task::perform(
async move {
gui_utils::is_streaming_finished(
streaming_to_base_receiver_is_streaming_finished,
streaming_to_base_receiver_is_streaming_stopped,
)
.await
},
Message::State,
);
let commands = vec![connect_command, is_streaming_finished_command];
2024-07-23 04:11:10 +03:00
Task::batch(commands)
}
Event::Disconnect => {
println!("Disconnect");
self.gui_status.are_we_connect = Condition::Loading;
let streaming_to_base_receiver = self
.communication_channel
.streaming_to_base_sender
.subscribe();
let base_to_streaming_sender =
self.communication_channel.base_to_streaming_sender.clone();
2024-07-23 04:11:10 +03:00
Task::perform(
async move {
gui_utils::disconnect(
streaming_to_base_receiver,
base_to_streaming_sender,
)
.await
},
Message::State,
)
}
Event::Record => {
println!("Record");
self.gui_status.are_we_record = Condition::Loading;
let microphone_stream_sender =
self.data_channel.microphone_stream_sender.clone();
let recording_to_base_sender =
self.communication_channel.recording_to_base_sender.clone();
let base_to_recording_receiver = self
.communication_channel
.base_to_recording_sender
.subscribe();
2024-07-23 04:11:10 +03:00
Task::perform(
async move {
gui_utils::start_recording(
microphone_stream_sender,
recording_to_base_sender,
base_to_recording_receiver,
)
.await
},
Message::State,
)
}
Event::StopRecord => {
println!("Stop Record");
self.gui_status.are_we_record = Condition::Loading;
let recording_to_base_receiver = self
.communication_channel
.recording_to_base_sender
.subscribe();
let base_to_recording_sender =
self.communication_channel.base_to_recording_sender.clone();
2024-07-23 04:11:10 +03:00
Task::perform(
async move {
gui_utils::stop_recording(
recording_to_base_receiver,
base_to_recording_sender,
)
.await
},
Message::State,
)
}
Event::PlayAudio => {
println!("Play Audio");
self.gui_status.are_we_play_audio = Condition::Loading;
let path = format!(
"{}/{}",
AUDIOS_PATH, self.audio_miscellaneous.selected_file_name
);
match File::open(path) {
Ok(file) => {
self.audio_miscellaneous.file = Some(file);
}
Err(err_val) => {
eprintln!("Error: Open File | {}", err_val);
self.audio_miscellaneous.file = None;
self.gui_status.are_we_play_audio = Condition::Passive;
2024-07-23 04:11:10 +03:00
return Task::none();
}
}
2024-05-13 18:40:03 +03:00
self.audio_miscellaneous.decoded_to_playing_sender = Some(
channel(max(
2024-05-13 18:40:03 +03:00
self.audio_miscellaneous
.file
.as_ref()
.unwrap()
.metadata()
.unwrap()
.len() as usize
* 10,
1,
))
.0,
);
let audio_stream_sender = self.data_channel.audio_stream_sender.clone();
let playing_to_base_sender =
self.communication_channel.playing_to_base_sender.clone();
let base_to_playing_receiver = self
.communication_channel
.base_to_playing_sender
.subscribe();
let playing_to_base_receiver_is_audio_finished = self
.communication_channel
.playing_to_base_sender
.subscribe();
let playing_to_base_receiver_is_audio_stopped = self
.communication_channel
.playing_to_base_sender
.subscribe();
let base_to_playing_sender =
self.communication_channel.base_to_playing_sender.clone();
2024-05-13 18:40:03 +03:00
let file = self
.audio_miscellaneous
.file
.as_ref()
.unwrap()
.try_clone()
.unwrap();
let decoded_to_playing_sender_for_playing = self
.audio_miscellaneous
.decoded_to_playing_sender
.clone()
.unwrap();
let decoded_to_playing_sender_for_is_finished = self
.audio_miscellaneous
.decoded_to_playing_sender
.clone()
.unwrap();
let audio_volume = self.gui_status.audio_volume.value.clone();
2024-07-23 04:11:10 +03:00
let playing_command = Task::perform(
async move {
gui_utils::start_playing(
audio_stream_sender,
decoded_to_playing_sender_for_playing,
file,
playing_to_base_sender,
base_to_playing_receiver,
audio_volume,
)
.await
},
Message::State,
);
2024-07-23 04:11:10 +03:00
let is_finished_command = Task::perform(
async move {
gui_utils::is_playing_finished(
playing_to_base_receiver_is_audio_finished,
playing_to_base_receiver_is_audio_stopped,
base_to_playing_sender,
decoded_to_playing_sender_for_is_finished,
)
.await
},
Message::State,
);
let commands = vec![playing_command, is_finished_command];
2024-07-23 04:11:10 +03:00
Task::batch(commands)
}
Event::StopAudio => {
println!("Stop Audio");
self.gui_status.are_we_play_audio = Condition::Loading;
let playing_to_base_receiver = self
.communication_channel
.playing_to_base_sender
.subscribe();
let base_to_playing_sender =
self.communication_channel.base_to_playing_sender.clone();
2024-07-23 04:11:10 +03:00
Task::perform(
async move {
gui_utils::stop_playing(
playing_to_base_receiver,
base_to_playing_sender,
)
.await
},
Message::State,
)
}
Event::PauseAudio => {
println!("Pause Audio");
self.gui_status.are_we_paused_audio = Condition::Loading;
let playing_to_base_receiver = self
.communication_channel
.playing_to_base_sender
.subscribe();
let base_to_playing_sender =
self.communication_channel.base_to_playing_sender.clone();
2024-07-23 04:11:10 +03:00
Task::perform(
async move {
gui_utils::pause_playing(
playing_to_base_receiver,
base_to_playing_sender,
)
.await
},
Message::State,
)
}
Event::ContinueAudio => {
println!("Continue Audio");
self.gui_status.are_we_paused_audio = Condition::Loading;
let playing_to_base_receiver = self
.communication_channel
.playing_to_base_sender
.subscribe();
let base_to_playing_sender =
self.communication_channel.base_to_playing_sender.clone();
2024-07-23 04:11:10 +03:00
Task::perform(
async move {
gui_utils::continue_playing(
playing_to_base_receiver,
base_to_playing_sender,
)
.await
},
Message::State,
)
}
2024-05-13 18:40:03 +03:00
Event::ChooseAudio(chosen_audio) => {
let path = format!("{}/{}", AUDIOS_PATH, chosen_audio);
match File::open(path) {
Ok(file) => {
self.audio_miscellaneous.file = Some(file);
self.audio_miscellaneous.selected_file_name = chosen_audio;
}
Err(err_val) => {
eprintln!("Error: Select Open | {}", err_val);
self.audio_miscellaneous.file = None;
}
}
2024-07-23 04:11:10 +03:00
Task::none()
2024-05-13 18:40:03 +03:00
}
Event::ChangeMicrophoneVolume(value) => {
2024-07-23 04:11:10 +03:00
// let microphone_volume = self.gui_status.microphone_volume.value.clone();
//*self.gui_status.microphone_volume.value.blocking_lock() = value;
let microphone_volume = self.gui_status.microphone_volume.value.clone();
2024-07-23 04:11:10 +03:00
Task::perform(
async move { change_microphone_volume(value, microphone_volume).await },
Message::State,
)
}
Event::ChangeAudioVolume(value) => {
2024-07-23 04:11:10 +03:00
// *self.gui_status.audio_volume.value.blocking_lock() = value;
let audio_volume = self.gui_status.audio_volume.value.clone();
2024-07-23 04:11:10 +03:00
Task::perform(
async move { change_audio_volume(value, audio_volume).await },
Message::State,
)
}
Event::LoadConfig(config) => {
self.config = Some(config);
2024-07-23 04:11:10 +03:00
Task::none()
}
2024-05-13 18:40:03 +03:00
Event::ListFiles(files) => {
self.audio_miscellaneous.files = files;
2024-07-23 04:11:10 +03:00
Task::none()
2024-05-13 18:40:03 +03:00
}
Event::IcedEvent(iced_event) => match iced_event {
2024-07-23 04:11:10 +03:00
iced::Event::Keyboard(_) => Task::perform(
2024-05-13 18:40:03 +03:00
async move {
let files = gui_utils::list_files(Path::new(AUDIOS_PATH)).await;
Event::ListFiles(files)
},
Message::Event,
),
2024-07-23 04:11:10 +03:00
iced::Event::Mouse(_) => Task::perform(
2024-05-13 18:40:03 +03:00
async move {
let files = gui_utils::list_files(Path::new(AUDIOS_PATH)).await;
Event::ListFiles(files)
},
Message::Event,
),
2024-07-23 04:11:10 +03:00
iced::Event::Touch(_) => Task::perform(
2024-05-13 18:40:03 +03:00
async move {
let files = gui_utils::list_files(Path::new(AUDIOS_PATH)).await;
Event::ListFiles(files)
},
Message::Event,
),
2024-07-23 04:11:10 +03:00
iced::Event::Window(windows_event) => Task::perform(
{
if let window::Event::CloseRequested = windows_event {
self.exit();
}
async move {
let files = gui_utils::list_files(Path::new(AUDIOS_PATH)).await;
Event::ListFiles(files)
}
2024-05-13 18:40:03 +03:00
},
Message::Event,
),
},
2024-07-23 04:11:10 +03:00
Event::CloseWindow(_) => self.exit(),
},
Message::State(state) => match state {
2024-07-23 04:11:10 +03:00
State::None => Task::none(),
State::Connected => {
self.gui_status.are_we_connect = Condition::Active;
2024-07-23 04:11:10 +03:00
Task::none()
}
State::Disconnected => {
self.gui_status.are_we_connect = Condition::Passive;
2024-07-23 04:11:10 +03:00
Task::none()
}
State::Recording => {
self.gui_status.are_we_record = Condition::Active;
2024-07-23 04:11:10 +03:00
Task::none()
}
State::StopRecording => {
self.gui_status.are_we_record = Condition::Passive;
2024-07-23 04:11:10 +03:00
Task::none()
}
State::PlayingAudio => {
2024-05-13 18:40:03 +03:00
self.audio_miscellaneous.playing_file_name =
self.audio_miscellaneous.selected_file_name.clone();
self.gui_status.are_we_play_audio = Condition::Active;
self.gui_status.are_we_paused_audio = Condition::Passive;
2024-07-23 04:11:10 +03:00
Task::none()
}
State::StopAudio => {
2024-05-13 18:40:03 +03:00
self.audio_miscellaneous.playing_file_name = String::new();
self.gui_status.are_we_play_audio = Condition::Passive;
2024-07-23 04:11:10 +03:00
Task::none()
}
State::PausedAudio => {
self.gui_status.are_we_paused_audio = Condition::Active;
2024-07-23 04:11:10 +03:00
Task::none()
}
State::ContinuedAudio => {
self.gui_status.are_we_paused_audio = Condition::Passive;
2024-07-23 04:11:10 +03:00
Task::none()
}
2024-07-23 04:11:10 +03:00
State::MicrophoneVolumeChanged => Task::none(),
State::AudioVolumeChanged => Task::none(),
},
}
}
pub fn view(&self) -> Container<Message> {
//let color_red = Color::from_rgb8(255, 0, 0);
let color_green = Color::from_rgb8(0, 255, 0);
let color_blue = Color::from_rgb8(0, 0, 255);
let color_yellow = Color::from_rgb8(255, 255, 0);
//let color_white = Color::from_rgb8(255, 255, 255);
let color_grey = Color::from_rgb8(128, 128, 128);
//let color_black = Color::from_rgb8(0, 0, 0);
let color_pink = Color::from_rgb8(255, 150, 150);
let header = text_centered("Radioxide")
.size(35)
.line_height(LineHeight::Relative(1.0));
let connection_text = text_centered("Connection");
let recording_text = text_centered("Microphone");
let play_audio_text = text_centered("Play Audio");
let pause_audio_text = text_centered("Pause Audio");
let connection_status_text;
let recording_status_text;
let play_audio_status_text;
let paused_audio_status_text;
let connect_button = match self.gui_status.are_we_connect {
Condition::Active => {
connection_status_text = text_centered("Active").color(color_green);
button_with_centered_text("Disconnect").on_press(Message::Event(Event::Disconnect))
}
Condition::Loading => {
connection_status_text = text_centered("Loading").color(color_yellow);
button_with_centered_text("Processing")
}
Condition::Passive => {
connection_status_text = text_centered("Passive").color(color_pink);
button_with_centered_text("Connect").on_press(Message::Event(Event::Connect))
}
};
let record_button = match self.gui_status.are_we_record {
Condition::Active => {
recording_status_text = text_centered("Active").color(color_green);
button_with_centered_text("Stop Mic").on_press(Message::Event(Event::StopRecord))
}
Condition::Loading => {
recording_status_text = text_centered("Loading").color(color_yellow);
button_with_centered_text("Processing")
}
Condition::Passive => {
recording_status_text = text_centered("Passive").color(color_pink);
button_with_centered_text("Start Mic").on_press(Message::Event(Event::Record))
}
};
let play_audio_button = match self.gui_status.are_we_play_audio {
Condition::Active => {
play_audio_status_text = text_centered("Active").color(color_green);
button_with_centered_text("Stop Audio").on_press(Message::Event(Event::StopAudio))
}
Condition::Loading => {
play_audio_status_text = text_centered("Loading").color(color_yellow);
button_with_centered_text("Processing")
}
2024-05-13 18:40:03 +03:00
Condition::Passive => match self.audio_miscellaneous.file {
Some(_) => {
play_audio_status_text = text_centered("Passive").color(color_pink);
button_with_centered_text("Play Audio")
.on_press(Message::Event(Event::PlayAudio))
}
None => {
play_audio_status_text = text_centered("No Audio").color(color_pink);
button_with_centered_text("No Audio")
}
},
};
let pause_audio_button = if let Condition::Active = self.gui_status.are_we_play_audio {
match self.gui_status.are_we_paused_audio {
Condition::Active => {
paused_audio_status_text = text_centered("Paused").color(color_blue);
button_with_centered_text("Continue Audio")
.on_press(Message::Event(Event::ContinueAudio))
}
Condition::Loading => {
paused_audio_status_text = text_centered("Loading").color(color_yellow);
button_with_centered_text("Processing")
}
Condition::Passive => {
paused_audio_status_text = text_centered("Playing").color(color_yellow);
button_with_centered_text("Pause Audio")
.on_press(Message::Event(Event::PauseAudio))
}
}
} else {
paused_audio_status_text = text_centered("Waiting").color(color_grey);
button_with_centered_text("No Purpose")
};
let microphone_volume_slider = slider(
0.0..=1.0,
2024-07-23 04:11:10 +03:00
*self.gui_status.microphone_volume.value.lock().unwrap(),
|value| Message::Event(Event::ChangeMicrophoneVolume(value)),
)
.step(0.01);
let audio_volume_slider = slider(
0.0..=1.0,
2024-07-23 04:11:10 +03:00
*self.gui_status.audio_volume.value.lock().unwrap(),
|value| Message::Event(Event::ChangeAudioVolume(value)),
)
.step(0.01);
let audio_file_size_for_scrollable = match self.audio_miscellaneous.files.as_ref() {
Some(audio_files) => audio_files.len() as u16 * (AUDIO_SCROLLABLE_BUTTON_SIZE + 1),
None => 0,
};
2024-07-23 04:11:10 +03:00
let longest_audio_name = match self.audio_miscellaneous.files.as_ref() {
Some(audio_files) => {
let mut longest = 0;
for audio_file in audio_files {
if longest < audio_file.len() {
longest = audio_file.len();
}
}
longest as u16 * 10
}
None => 0,
};
2024-05-13 18:40:03 +03:00
let mut audio_scrollable_content = column![]
.spacing(1)
.height(audio_file_size_for_scrollable)
2024-07-23 04:11:10 +03:00
.width(longest_audio_name);
2024-05-13 18:40:03 +03:00
let audio_selected = text_centered(format!(
"Selected: {}",
self.audio_miscellaneous.selected_file_name.clone()
));
let audio_playing = text_centered(format!(
"Playing: {}",
self.audio_miscellaneous.playing_file_name.clone()
));
if self.audio_miscellaneous.files.is_some() {
for file in self.audio_miscellaneous.files.as_ref().clone().unwrap() {
let button = button_with_centered_text(file)
.on_press(Message::Event(Event::ChooseAudio(file.to_string())));
audio_scrollable_content =
audio_scrollable_content.push(button.height(AUDIO_SCROLLABLE_BUTTON_SIZE));
2024-05-13 18:40:03 +03:00
}
}
2024-07-23 04:11:10 +03:00
let audios_scrollable = scrollable(audio_scrollable_content).height(200).width(350);
let audio_info_content = column![audio_selected, audio_playing,]
.height(100)
.width(longest_audio_name);
let header_content = row![header].width(350).height(50);
let text_content = row![
connection_text,
Rule::vertical(1),
recording_text,
Rule::vertical(1),
play_audio_text,
Rule::vertical(1),
pause_audio_text,
]
.spacing(5)
.width(350)
.height(35);
let status_content = row![
connection_status_text,
Rule::vertical(1),
recording_status_text,
Rule::vertical(1),
play_audio_status_text,
Rule::vertical(1),
paused_audio_status_text,
]
.spacing(5)
.width(350)
.height(35);
let button_content = row![
connect_button,
record_button,
play_audio_button,
pause_audio_button,
]
.spacing(5)
.width(350)
.height(35);
let volume_content = row![microphone_volume_slider, audio_volume_slider,]
.spacing(5)
.width(350)
.height(35);
let content = column![
header_content,
Rule::horizontal(1),
text_content,
button_content,
status_content,
Rule::horizontal(1),
volume_content,
2024-05-13 18:40:03 +03:00
audios_scrollable,
audio_info_content,
]
.spacing(20)
2024-05-13 18:40:03 +03:00
.width(Length::Fill)
.height(Length::Fill);
container(content)
2024-05-13 18:40:03 +03:00
.height(Length::Fill)
2024-05-16 02:04:11 +03:00
.center_x(Length::Fill)
.align_y(alignment::Vertical::Top)
}
pub fn subscription(&self) -> Subscription<Message> {
iced::event::listen()
.map(Event::IcedEvent)
.map(Message::Event)
}
2024-07-23 04:11:10 +03:00
pub fn load_config() -> Task<Message> {
Task::perform(
async move {
2024-07-23 04:11:10 +03:00
let config = get_config();
Event::LoadConfig(config)
},
Message::Event,
)
}
2024-07-23 04:11:10 +03:00
pub fn list_files() -> Task<Message> {
Task::perform(
2024-05-13 18:40:03 +03:00
async move {
let files = gui_utils::list_files(Path::new(AUDIOS_PATH)).await;
Event::ListFiles(files)
},
Message::Event,
)
}
fn call_closer(
streaming_to_base_receiver: Receiver<bool>,
base_to_streaming_sender: Sender<bool>,
recording_to_base_receiver: Receiver<bool>,
base_to_recording_sender: Sender<bool>,
playing_to_base_receiver: Receiver<Player>,
base_to_playing_sender: Sender<Player>,
features_in_need: Features,
2024-07-23 04:11:10 +03:00
) -> Task<Message> {
tokio::spawn(async move {
if features_in_need.stream {
gui_utils::disconnect(streaming_to_base_receiver, base_to_streaming_sender).await;
}
if features_in_need.record {
gui_utils::stop_recording(recording_to_base_receiver, base_to_recording_sender)
.await;
}
if features_in_need.play_audio {
gui_utils::stop_playing(playing_to_base_receiver, base_to_playing_sender).await;
}
});
exit(1);
}
2024-07-23 04:11:10 +03:00
fn exit(&self) -> Task<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_receiver = self
.communication_channel
.streaming_to_base_sender
.subscribe();
let base_to_streaming_sender = self.communication_channel.base_to_streaming_sender.clone();
let recording_to_base_receiver = self
.communication_channel
.recording_to_base_sender
.subscribe();
let base_to_recording_sender = self.communication_channel.base_to_recording_sender.clone();
let playing_to_base_receiver = self
.communication_channel
.playing_to_base_sender
.subscribe();
let base_to_playing_sender = self.communication_channel.base_to_playing_sender.clone();
Self::call_closer(
streaming_to_base_receiver,
base_to_streaming_sender,
recording_to_base_receiver,
base_to_recording_sender,
playing_to_base_receiver,
base_to_playing_sender,
features_in_need,
)
}
}