2024-04-27 19:48:13 +03:00
|
|
|
use iced::{
|
2024-05-02 00:12:59 +03:00
|
|
|
alignment, widget::{column, container, row, text::LineHeight, Container, Rule}, window, Color, Command, Subscription
|
2024-04-27 19:48:13 +03:00
|
|
|
};
|
2024-05-01 03:27:34 +03:00
|
|
|
use tokio::sync::broadcast::{channel, Receiver, Sender};
|
2024-04-27 15:36:28 +03:00
|
|
|
|
2024-04-28 18:58:01 +03:00
|
|
|
use crate::{
|
2024-05-02 00:12:59 +03:00
|
|
|
gui_components::{button_with_centered_text, text_centered},
|
|
|
|
gui_utils,
|
|
|
|
utils::get_config,
|
|
|
|
Config, BUFFER_LENGTH,
|
2024-04-28 18:58:01 +03:00
|
|
|
};
|
2024-05-01 03:27:34 +03:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
struct Features {
|
|
|
|
stream: bool,
|
|
|
|
record: bool,
|
|
|
|
play_audio: bool,
|
|
|
|
}
|
|
|
|
|
2024-04-28 18:58:01 +03:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum Event {
|
2024-05-01 03:27:34 +03:00
|
|
|
None,
|
2024-04-28 18:58:01 +03:00
|
|
|
Connect,
|
|
|
|
Disconnect,
|
|
|
|
Record,
|
|
|
|
StopRecord,
|
|
|
|
PlayAudio,
|
|
|
|
StopAudio,
|
|
|
|
LoadConfig(Config),
|
2024-05-01 03:27:34 +03:00
|
|
|
IcedEvent(iced::Event),
|
2024-05-01 19:37:52 +03:00
|
|
|
CloseWindow(window::Id),
|
2024-04-28 18:58:01 +03:00
|
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
|
|
|
pub enum State {
|
2024-05-01 03:27:34 +03:00
|
|
|
None,
|
2024-04-28 18:58:01 +03:00
|
|
|
Connected,
|
|
|
|
Disconnected,
|
|
|
|
Recording,
|
|
|
|
StopRecording,
|
|
|
|
PlayingAudio,
|
|
|
|
StopAudio,
|
|
|
|
}
|
2024-04-27 15:36:28 +03:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum Message {
|
2024-04-28 18:58:01 +03:00
|
|
|
Event(Event),
|
|
|
|
State(State),
|
|
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct DataChannel {
|
|
|
|
sound_stream_sender: Sender<f32>,
|
|
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct CommunicationChannel {
|
|
|
|
base_to_streaming: Sender<bool>,
|
|
|
|
streaming_to_base: Sender<bool>,
|
|
|
|
base_to_recording: Sender<bool>,
|
|
|
|
recording_to_base: Sender<bool>,
|
2024-05-02 00:12:59 +03:00
|
|
|
base_to_playing_audio: Sender<bool>,
|
|
|
|
playing_audio_to_base: Sender<bool>,
|
2024-04-28 18:58:01 +03:00
|
|
|
}
|
2024-05-01 03:27:34 +03:00
|
|
|
#[derive(Debug, PartialEq)]
|
2024-04-28 18:58:01 +03:00
|
|
|
enum Condition {
|
|
|
|
Active,
|
|
|
|
Loading,
|
|
|
|
Passive,
|
2024-04-27 15:36:28 +03:00
|
|
|
}
|
|
|
|
|
2024-04-28 18:58:01 +03:00
|
|
|
#[derive(Debug)]
|
|
|
|
struct GUIStatus {
|
|
|
|
are_we_connect: Condition,
|
|
|
|
are_we_record: Condition,
|
|
|
|
are_we_play_audio: Condition,
|
|
|
|
}
|
2024-04-27 15:36:28 +03:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Streamer {
|
|
|
|
config: Option<Config>,
|
2024-04-28 18:58:01 +03:00
|
|
|
data_channel: DataChannel,
|
|
|
|
communication_channel: CommunicationChannel,
|
|
|
|
gui_status: GUIStatus,
|
2024-04-27 15:36:28 +03:00
|
|
|
}
|
|
|
|
impl Default for Streamer {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Streamer {
|
|
|
|
fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
config: None,
|
2024-04-28 18:58:01 +03:00
|
|
|
data_channel: DataChannel {
|
|
|
|
sound_stream_sender: channel(BUFFER_LENGTH).0,
|
|
|
|
},
|
|
|
|
communication_channel: CommunicationChannel {
|
|
|
|
base_to_streaming: channel(1).0,
|
|
|
|
streaming_to_base: channel(1).0,
|
|
|
|
base_to_recording: channel(1).0,
|
|
|
|
recording_to_base: channel(1).0,
|
2024-05-02 00:12:59 +03:00
|
|
|
base_to_playing_audio: channel(1).0,
|
|
|
|
playing_audio_to_base: channel(1).0,
|
2024-04-28 18:58:01 +03:00
|
|
|
},
|
|
|
|
gui_status: GUIStatus {
|
|
|
|
are_we_connect: Condition::Passive,
|
|
|
|
are_we_record: Condition::Passive,
|
|
|
|
are_we_play_audio: Condition::Passive,
|
|
|
|
},
|
2024-04-27 15:36:28 +03:00
|
|
|
}
|
|
|
|
}
|
2024-04-28 18:58:01 +03:00
|
|
|
pub fn update(&mut self, message: Message) -> Command<Message> {
|
2024-04-27 15:36:28 +03:00
|
|
|
match message {
|
2024-04-28 18:58:01 +03:00
|
|
|
Message::Event(event) => match event {
|
2024-05-01 03:27:34 +03:00
|
|
|
Event::None => Command::none(),
|
2024-04-28 18:58:01 +03:00
|
|
|
Event::Connect => {
|
|
|
|
println!("Connect");
|
|
|
|
self.gui_status.are_we_connect = Condition::Loading;
|
2024-05-01 19:37:52 +03:00
|
|
|
|
|
|
|
let sound_stream_receiver = self.data_channel.sound_stream_sender.subscribe();
|
|
|
|
let streamer_config = self.config.clone().unwrap();
|
|
|
|
let streaming_to_base = self.communication_channel.streaming_to_base.clone();
|
|
|
|
let base_to_streaming =
|
|
|
|
self.communication_channel.base_to_streaming.subscribe();
|
|
|
|
|
2024-04-28 18:58:01 +03:00
|
|
|
Command::perform(
|
|
|
|
async move {
|
2024-05-01 19:37:52 +03:00
|
|
|
gui_utils::connect(
|
|
|
|
sound_stream_receiver,
|
|
|
|
streamer_config,
|
|
|
|
streaming_to_base,
|
|
|
|
base_to_streaming,
|
|
|
|
)
|
|
|
|
.await
|
2024-04-28 18:58:01 +03:00
|
|
|
},
|
|
|
|
Message::State,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Event::Disconnect => {
|
|
|
|
println!("Disconnect");
|
|
|
|
self.gui_status.are_we_connect = Condition::Loading;
|
2024-05-01 19:37:52 +03:00
|
|
|
|
|
|
|
let streaming_to_base =
|
|
|
|
self.communication_channel.streaming_to_base.subscribe();
|
2024-05-01 03:27:34 +03:00
|
|
|
let base_to_streaming = self.communication_channel.base_to_streaming.clone();
|
2024-05-01 19:37:52 +03:00
|
|
|
|
|
|
|
Command::perform(
|
|
|
|
async move { gui_utils::disconnect(streaming_to_base, base_to_streaming).await },
|
|
|
|
Message::State,
|
|
|
|
)
|
2024-04-28 18:58:01 +03:00
|
|
|
}
|
|
|
|
Event::Record => {
|
|
|
|
println!("Record");
|
|
|
|
self.gui_status.are_we_record = Condition::Loading;
|
2024-05-01 19:37:52 +03:00
|
|
|
|
|
|
|
let sound_stream_sender = self.data_channel.sound_stream_sender.clone();
|
|
|
|
let recording_to_base = self.communication_channel.recording_to_base.clone();
|
|
|
|
let base_to_recording =
|
|
|
|
self.communication_channel.base_to_recording.subscribe();
|
|
|
|
|
2024-04-28 18:58:01 +03:00
|
|
|
Command::perform(
|
|
|
|
async move {
|
2024-05-02 00:12:59 +03:00
|
|
|
gui_utils::start_recording(
|
2024-05-01 19:37:52 +03:00
|
|
|
sound_stream_sender,
|
|
|
|
recording_to_base,
|
|
|
|
base_to_recording,
|
|
|
|
)
|
|
|
|
.await
|
2024-04-28 18:58:01 +03:00
|
|
|
},
|
|
|
|
Message::State,
|
|
|
|
)
|
2024-04-27 22:14:50 +03:00
|
|
|
}
|
2024-04-28 18:58:01 +03:00
|
|
|
Event::StopRecord => {
|
|
|
|
println!("Stop Record");
|
|
|
|
self.gui_status.are_we_record = Condition::Loading;
|
2024-05-01 19:37:52 +03:00
|
|
|
let recording_to_base =
|
|
|
|
self.communication_channel.recording_to_base.subscribe();
|
2024-05-01 03:27:34 +03:00
|
|
|
let base_to_recording = self.communication_channel.base_to_recording.clone();
|
2024-05-01 19:37:52 +03:00
|
|
|
Command::perform(
|
|
|
|
async move {
|
|
|
|
gui_utils::stop_recording(recording_to_base, base_to_recording).await
|
|
|
|
},
|
|
|
|
Message::State,
|
|
|
|
)
|
2024-04-27 22:14:50 +03:00
|
|
|
}
|
2024-04-28 18:58:01 +03:00
|
|
|
Event::PlayAudio => {
|
|
|
|
println!("Play Audio");
|
|
|
|
self.gui_status.are_we_play_audio = Condition::Loading;
|
2024-05-02 00:12:59 +03:00
|
|
|
|
|
|
|
let playing_audio_to_base =
|
|
|
|
self.communication_channel.playing_audio_to_base.clone();
|
|
|
|
let base_to_playing_audio =
|
|
|
|
self.communication_channel.base_to_playing_audio.subscribe();
|
|
|
|
|
2024-04-28 18:58:01 +03:00
|
|
|
Command::perform(
|
|
|
|
async move {
|
2024-05-02 00:12:59 +03:00
|
|
|
gui_utils::start_playing_audio(
|
|
|
|
playing_audio_to_base,
|
|
|
|
base_to_playing_audio,
|
|
|
|
)
|
|
|
|
.await
|
2024-04-28 18:58:01 +03:00
|
|
|
},
|
|
|
|
Message::State,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Event::StopAudio => {
|
|
|
|
println!("Stop Audio");
|
|
|
|
self.gui_status.are_we_play_audio = Condition::Loading;
|
|
|
|
let mut playing_to_base_receiver =
|
2024-05-02 00:12:59 +03:00
|
|
|
self.communication_channel.playing_audio_to_base.subscribe();
|
|
|
|
let _ = self.communication_channel.base_to_playing_audio.send(false);
|
2024-04-28 18:58:01 +03:00
|
|
|
Command::perform(
|
|
|
|
async move {
|
|
|
|
match playing_to_base_receiver.recv().await {
|
|
|
|
Ok(_) => State::StopAudio,
|
|
|
|
Err(err_val) => {
|
|
|
|
eprint!("Error: Communication | Playing | {}", err_val);
|
|
|
|
State::PlayingAudio
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Message::State,
|
|
|
|
)
|
2024-04-27 22:14:50 +03:00
|
|
|
}
|
2024-04-28 18:58:01 +03:00
|
|
|
Event::LoadConfig(config) => {
|
|
|
|
self.config = Some(config);
|
|
|
|
Command::none()
|
2024-04-27 22:14:50 +03:00
|
|
|
}
|
2024-05-01 03:27:34 +03:00
|
|
|
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(),
|
|
|
|
},
|
2024-05-01 19:37:52 +03:00
|
|
|
Event::CloseWindow(id) => window::close(id),
|
2024-04-27 22:14:50 +03:00
|
|
|
},
|
2024-04-28 18:58:01 +03:00
|
|
|
Message::State(state) => match state {
|
2024-05-01 03:27:34 +03:00
|
|
|
State::None => Command::none(),
|
2024-04-28 18:58:01 +03:00
|
|
|
State::Connected => {
|
|
|
|
self.gui_status.are_we_connect = Condition::Active;
|
|
|
|
Command::none()
|
|
|
|
}
|
|
|
|
State::Disconnected => {
|
|
|
|
self.gui_status.are_we_connect = Condition::Passive;
|
|
|
|
Command::none()
|
2024-04-27 22:14:50 +03:00
|
|
|
}
|
2024-04-28 18:58:01 +03:00
|
|
|
State::Recording => {
|
|
|
|
self.gui_status.are_we_record = Condition::Active;
|
|
|
|
Command::none()
|
|
|
|
}
|
|
|
|
State::StopRecording => {
|
|
|
|
self.gui_status.are_we_record = Condition::Passive;
|
|
|
|
Command::none()
|
|
|
|
}
|
|
|
|
State::PlayingAudio => {
|
|
|
|
self.gui_status.are_we_play_audio = Condition::Active;
|
|
|
|
Command::none()
|
|
|
|
}
|
|
|
|
State::StopAudio => {
|
|
|
|
self.gui_status.are_we_play_audio = Condition::Passive;
|
|
|
|
Command::none()
|
2024-04-27 22:14:50 +03:00
|
|
|
}
|
|
|
|
},
|
2024-04-28 18:58:01 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn view(&self) -> Container<Message> {
|
2024-05-02 00:12:59 +03:00
|
|
|
//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 connection_status_text;
|
|
|
|
let recording_status_text;
|
|
|
|
let play_audio_status_text;
|
|
|
|
|
2024-04-28 18:58:01 +03:00
|
|
|
let connect_button = match self.gui_status.are_we_connect {
|
|
|
|
Condition::Active => {
|
2024-05-02 00:12:59 +03:00
|
|
|
connection_status_text = text_centered("Active").color(color_green);
|
2024-04-28 18:58:01 +03:00
|
|
|
button_with_centered_text("Disconnect").on_press(Message::Event(Event::Disconnect))
|
|
|
|
}
|
2024-05-02 00:12:59 +03:00
|
|
|
Condition::Loading => {
|
|
|
|
connection_status_text = text_centered("Loading").color(color_yellow);
|
|
|
|
button_with_centered_text("Processing")
|
|
|
|
}
|
2024-04-28 18:58:01 +03:00
|
|
|
Condition::Passive => {
|
2024-05-02 00:12:59 +03:00
|
|
|
connection_status_text = text_centered("Passive").color(color_pink);
|
2024-04-28 18:58:01 +03:00
|
|
|
button_with_centered_text("Connect").on_press(Message::Event(Event::Connect))
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let record_button = match self.gui_status.are_we_record {
|
|
|
|
Condition::Active => {
|
2024-05-02 00:12:59 +03:00
|
|
|
recording_status_text = text_centered("Active").color(color_green);
|
|
|
|
button_with_centered_text("Start 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("Stop 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-04-28 18:58:01 +03:00
|
|
|
}
|
|
|
|
Condition::Passive => {
|
2024-05-02 00:12:59 +03:00
|
|
|
play_audio_status_text = text_centered("Passive").color(color_pink);
|
|
|
|
button_with_centered_text("Play Audio").on_press(Message::Event(Event::PlayAudio))
|
2024-04-28 18:58:01 +03:00
|
|
|
}
|
2024-04-27 22:14:50 +03:00
|
|
|
};
|
2024-04-28 18:58:01 +03:00
|
|
|
|
2024-05-02 00:12:59 +03:00
|
|
|
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,
|
|
|
|
]
|
|
|
|
.spacing(5)
|
|
|
|
.width(350)
|
|
|
|
.height(35);
|
2024-04-28 18:58:01 +03:00
|
|
|
|
2024-05-02 00:12:59 +03:00
|
|
|
let status_content = row![
|
|
|
|
connection_status_text,
|
|
|
|
Rule::vertical(1),
|
|
|
|
recording_status_text,
|
|
|
|
Rule::vertical(1),
|
|
|
|
play_audio_status_text
|
|
|
|
]
|
|
|
|
.spacing(5)
|
|
|
|
.width(350)
|
|
|
|
.height(35);
|
|
|
|
let button_content = row![connect_button, record_button, play_audio_button]
|
|
|
|
.spacing(5)
|
|
|
|
.width(350)
|
2024-04-28 18:58:01 +03:00
|
|
|
.height(35);
|
2024-05-02 00:12:59 +03:00
|
|
|
|
|
|
|
let content = column![
|
|
|
|
header_content,
|
|
|
|
Rule::horizontal(1),
|
|
|
|
text_content,
|
|
|
|
|
|
|
|
button_content,
|
|
|
|
|
|
|
|
status_content,
|
|
|
|
Rule::horizontal(1),
|
|
|
|
]
|
|
|
|
.spacing(20)
|
|
|
|
.width(350)
|
|
|
|
.height(300);
|
|
|
|
container(content).height(300).center_x().align_y(alignment::Vertical::Top)
|
2024-04-27 15:36:28 +03:00
|
|
|
}
|
2024-05-01 03:27:34 +03:00
|
|
|
pub fn subscription(&self) -> Subscription<Message> {
|
|
|
|
iced::event::listen()
|
|
|
|
.map(Event::IcedEvent)
|
|
|
|
.map(Message::Event)
|
|
|
|
}
|
2024-04-27 15:36:28 +03:00
|
|
|
pub fn load_config() -> Command<Message> {
|
2024-04-28 18:58:01 +03:00
|
|
|
Command::perform(
|
|
|
|
async move {
|
|
|
|
let config = get_config().await;
|
|
|
|
Event::LoadConfig(config)
|
|
|
|
},
|
|
|
|
Message::Event,
|
|
|
|
)
|
2024-04-27 15:36:28 +03:00
|
|
|
}
|
2024-05-01 03:27:34 +03:00
|
|
|
fn call_closer(
|
|
|
|
streaming_to_base: Receiver<bool>,
|
|
|
|
base_to_streaming: Sender<bool>,
|
2024-05-01 19:37:52 +03:00
|
|
|
recording_to_base: Receiver<bool>,
|
2024-05-01 03:27:34 +03:00
|
|
|
base_to_recording: Sender<bool>,
|
2024-05-02 00:12:59 +03:00
|
|
|
playing_audio_to_base: Receiver<bool>,
|
|
|
|
base_to_playing_audio: Sender<bool>,
|
2024-05-01 03:27:34 +03:00
|
|
|
features_in_need: Features,
|
|
|
|
window_id: window::Id,
|
2024-05-01 19:37:52 +03:00
|
|
|
) -> 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 {
|
2024-05-02 00:12:59 +03:00
|
|
|
gui_utils::stop_playing_audio(playing_audio_to_base, base_to_playing_audio)
|
|
|
|
.await;
|
2024-05-01 19:37:52 +03:00
|
|
|
}
|
|
|
|
Event::CloseWindow(window_id)
|
|
|
|
},
|
|
|
|
Message::Event,
|
|
|
|
)
|
2024-05-01 03:27:34 +03:00
|
|
|
}
|
|
|
|
fn exit(&self, window_id: window::Id) -> Command<Message> {
|
2024-05-01 19:37:52 +03:00
|
|
|
let mut features_in_need = Features {
|
2024-05-01 03:27:34 +03:00
|
|
|
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();
|
|
|
|
|
2024-05-02 00:12:59 +03:00
|
|
|
let playing_audio_to_base = self.communication_channel.playing_audio_to_base.subscribe();
|
|
|
|
let base_to_playing_audio = self.communication_channel.base_to_playing_audio.clone();
|
2024-05-01 03:27:34 +03:00
|
|
|
|
2024-05-01 19:37:52 +03:00
|
|
|
Self::call_closer(
|
|
|
|
streaming_to_base,
|
|
|
|
base_to_streaming,
|
|
|
|
recording_to_base,
|
|
|
|
base_to_recording,
|
2024-05-02 00:12:59 +03:00
|
|
|
playing_audio_to_base,
|
|
|
|
base_to_playing_audio,
|
2024-05-01 19:37:52 +03:00
|
|
|
features_in_need,
|
|
|
|
window_id,
|
|
|
|
)
|
2024-05-01 03:27:34 +03:00
|
|
|
}
|
2024-05-01 19:37:52 +03:00
|
|
|
}
|