feat: controlling volume capability

This commit is contained in:
Ahmet Kaan GÜMÜŞ 2024-05-11 03:41:30 +03:00
parent 68b270451f
commit d44cfb37bf
4 changed files with 118 additions and 16 deletions

View file

@ -1,15 +1,18 @@
use std::fs::File;
use std::{fs::File, sync::Arc};
use iced::{
alignment,
widget::{column, container, row, text::LineHeight, Container, Rule},
widget::{column, container, row, slider, text::LineHeight, Container, Rule},
window, Color, Command, Subscription,
};
use tokio::sync::broadcast::{channel, Receiver, Sender};
use tokio::sync::{
broadcast::{channel, Receiver, Sender},
Mutex,
};
use crate::{
gui_components::{button_with_centered_text, text_centered},
gui_utils,
gui_utils::{self, change_audio_volume, change_microphone_volume},
utils::get_config,
Config, BUFFER_LENGTH,
};
@ -45,6 +48,8 @@ pub enum Event {
StopAudio,
PauseAudio,
ContinueAudio,
ChangeMicrophoneVolume(f32),
ChangeAudioVolume(f32),
LoadConfig(Config),
IcedEvent(iced::Event),
CloseWindow(window::Id),
@ -61,6 +66,8 @@ pub enum State {
StopAudio,
PausedAudio,
ContinuedAudio,
MicrophoneVolumeChanged,
AudioVolumeChanged,
}
#[derive(Debug, Clone)]
@ -89,12 +96,19 @@ enum Condition {
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 {
@ -135,6 +149,12 @@ impl Streamer {
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()),
},
},
}
}
@ -156,7 +176,8 @@ impl Streamer {
.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();
Command::perform(
async move {
gui_utils::connect(
@ -165,6 +186,8 @@ impl Streamer {
streamer_config,
streaming_to_base_sender,
base_to_streaming_receiver,
microphone_stream_volume,
audio_stream_volume,
)
.await
},
@ -286,6 +309,9 @@ impl Streamer {
let decoded_to_playing_sender_for_is_finished =
self.audio_file.decoded_to_playing_sender.clone().unwrap();
let audio_volume = self.gui_status.audio_volume.value.clone();
let playing_command = Command::perform(
async move {
gui_utils::start_playing(
@ -294,6 +320,7 @@ impl Streamer {
file,
playing_to_base_sender,
base_to_playing_receiver,
audio_volume,
)
.await
},
@ -380,6 +407,22 @@ impl Streamer {
Message::State,
)
}
Event::ChangeMicrophoneVolume(value) => {
*self.gui_status.microphone_volume.value.blocking_lock() = value;
let microphone_volume = self.gui_status.microphone_volume.value.clone();
Command::perform(
async move { change_microphone_volume(value, microphone_volume).await },
Message::State,
)
}
Event::ChangeAudioVolume(value) => {
*self.gui_status.audio_volume.value.blocking_lock() = value;
let audio_volume = self.gui_status.audio_volume.value.clone();
Command::perform(
async move { change_audio_volume(value, audio_volume).await },
Message::State,
)
}
Event::LoadConfig(config) => {
self.config = Some(config);
Command::none()
@ -434,6 +477,8 @@ impl Streamer {
self.gui_status.are_we_paused_audio = Condition::Passive;
Command::none()
}
State::MicrophoneVolumeChanged => Command::none(),
State::AudioVolumeChanged => Command::none(),
},
}
}
@ -528,6 +573,20 @@ impl Streamer {
button_with_centered_text("No Purpose")
};
let microphone_volume_slider = slider(
0.0..=1.0,
*self.gui_status.microphone_volume.value.blocking_lock(),
|value| Message::Event(Event::ChangeMicrophoneVolume(value)),
)
.step(0.01);
let audio_volume_slider = slider(
0.0..=1.0,
*self.gui_status.audio_volume.value.blocking_lock(),
|value| Message::Event(Event::ChangeAudioVolume(value)),
)
.step(0.01);
let header_content = row![header].width(350).height(50);
let text_content = row![
connection_text,
@ -558,12 +617,15 @@ impl Streamer {
connect_button,
record_button,
play_audio_button,
pause_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),
@ -571,6 +633,7 @@ impl Streamer {
button_content,
status_content,
Rule::horizontal(1),
volume_content,
]
.spacing(20)
.width(350)

View file

@ -1,6 +1,9 @@
use std::{fs::File, time::Duration};
use std::{fs::File, sync::Arc, time::Duration};
use tokio::sync::broadcast::{Receiver, Sender};
use tokio::sync::{
broadcast::{Receiver, Sender},
Mutex,
};
use crate::{
gui::{Player, State},
@ -13,6 +16,8 @@ pub async fn connect(
streamer_config: Config,
streaming_to_base_sender: Sender<bool>,
base_to_streaming_receiver: Receiver<bool>,
microphone_stream_volume: Arc<Mutex<f32>>,
audio_stream_volume: Arc<Mutex<f32>>,
) -> State {
let mut streaming_to_base_receiver = streaming_to_base_sender.subscribe();
tokio::spawn(streaming::connect(
@ -21,6 +26,8 @@ pub async fn connect(
streamer_config,
base_to_streaming_receiver,
streaming_to_base_sender.clone(),
microphone_stream_volume,
audio_stream_volume,
));
let answer = streaming_to_base_receiver.recv().await;
drop(streaming_to_base_receiver);
@ -124,6 +131,7 @@ pub async fn start_playing(
file: File,
playing_to_base_sender: Sender<Player>,
base_to_playing_receiver: Receiver<Player>,
audio_volume: Arc<Mutex<f32>>,
) -> State {
let mut playing_to_base_receiver = playing_to_base_sender.subscribe();
tokio::spawn(playing::play(
@ -132,6 +140,7 @@ pub async fn start_playing(
decoded_to_playing_sender,
playing_to_base_sender,
base_to_playing_receiver,
audio_volume,
));
let answer = playing_to_base_receiver.recv().await;
drop(playing_to_base_receiver);
@ -291,3 +300,19 @@ pub async fn continue_playing(
}
}
}
pub async fn change_microphone_volume(
desired_value: f32,
microphone_stream_volume: Arc<Mutex<f32>>,
) -> State {
*microphone_stream_volume.lock().await = desired_value;
State::MicrophoneVolumeChanged
}
pub async fn change_audio_volume(
desired_value: f32,
audio_stream_volume: Arc<Mutex<f32>>,
) -> State {
*audio_stream_volume.lock().await = desired_value;
State::AudioVolumeChanged
}

View file

@ -1,4 +1,4 @@
use std::fs::File;
use std::{fs::File, sync::Arc};
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use rubato::{
@ -13,7 +13,10 @@ use symphonia::core::{
probe::Hint,
};
use tokio::{
sync::broadcast::{Receiver, Sender},
sync::{
broadcast::{Receiver, Sender},
Mutex,
},
task,
};
@ -25,6 +28,7 @@ pub async fn play(
decoded_to_playing_sender: Sender<f32>,
playing_to_base_sender: Sender<Player>,
mut base_to_playing_receiver: Receiver<Player>,
audio_volume: Arc<Mutex<f32>>,
) {
let host = cpal::default_host();
let output_device = host.default_output_device().unwrap();
@ -50,7 +54,7 @@ pub async fn play(
for sample in data {
if decoded_to_playing_receiver.len() > 0 {
let single = match decoded_to_playing_receiver.blocking_recv() {
Ok(single) => single,
Ok(single) => single * *audio_volume.blocking_lock(),
Err(_) => 0.0,
};
if audio_stream_sender.receiver_count() > 0 {

View file

@ -4,7 +4,10 @@ use brotli::CompressorWriter;
use futures_util::SinkExt;
use ringbuf::HeapRb;
use tokio::{
sync::broadcast::{channel, Receiver, Sender},
sync::{
broadcast::{channel, Receiver, Sender},
Mutex,
},
task::JoinHandle,
};
use tokio_tungstenite::tungstenite::Message;
@ -18,6 +21,8 @@ pub async fn connect(
streamer_config: Config,
mut base_to_streaming: Receiver<bool>,
streaming_to_base: Sender<bool>,
microphone_stream_volume: Arc<Mutex<f32>>,
audio_stream_volume: Arc<Mutex<f32>>,
) {
let connect_addr = match streamer_config.tls {
true => format!("wss://{}", streamer_config.address),
@ -59,6 +64,8 @@ pub async fn connect(
let mixer_task = tokio::spawn(mixer(
microphone_stream_receiver,
audio_stream_receiver,
microphone_stream_volume,
audio_stream_volume,
flow_sender,
streamer_config.latency,
));
@ -82,6 +89,8 @@ pub async fn connect(
async fn mixer(
mut microphone_stream_receiver: Receiver<f32>,
mut audio_stream_receiver: Receiver<f32>,
microphone_stream_volume: Arc<Mutex<f32>>,
audio_stream_volume: Arc<Mutex<f32>>,
flow_sender: Sender<f32>,
latency: u16,
) {
@ -120,13 +129,14 @@ async fn mixer(
let mut flow = vec![];
for element in microphone_stream {
flow.push(element * 0.5);
flow.push(element * (*microphone_stream_volume.lock().await));
}
for (i, element) in audio_stream.iter().enumerate() {
let audio_volumized = element * (*audio_stream_volume.lock().await);
if flow.len() > i && flow.len() != 0 {
flow[i] = flow[i] + element * 0.5;
flow[i] = flow[i] + audio_volumized;
} else {
flow.push(element * 0.5);
flow.push(audio_volumized);
}
}
for element in flow {