mirror of
https://github.com/arabianq/pipewire-soundpad.git
synced 2026-07-26 05:46:59 +00:00
feat(lib, daemon, cli, gui): add volume multiplier (#175)
* initial implementation * rename DaemonConfig.volume_multiplier to default_volume_multiplier * add volume_multiplier to the FullState * add pwsp-gui integration
This commit is contained in:
@@ -88,6 +88,8 @@ enum GetCommands {
|
|||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
id: Option<u32>,
|
id: Option<u32>,
|
||||||
},
|
},
|
||||||
|
/// Volume multiplier for all tracks
|
||||||
|
VolumeMultiplier,
|
||||||
/// Playback position (in seconds)
|
/// Playback position (in seconds)
|
||||||
Position {
|
Position {
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
@@ -124,6 +126,8 @@ enum SetCommands {
|
|||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
id: Option<u32>,
|
id: Option<u32>,
|
||||||
},
|
},
|
||||||
|
/// Volume multiplier for all tracks
|
||||||
|
VolumeMultiplier { volume: f32 },
|
||||||
/// Playback position (in seconds)
|
/// Playback position (in seconds)
|
||||||
Position {
|
Position {
|
||||||
position: f32,
|
position: f32,
|
||||||
@@ -177,6 +181,7 @@ async fn main() -> Result<()> {
|
|||||||
Commands::Get { parameter } => match parameter {
|
Commands::Get { parameter } => match parameter {
|
||||||
GetCommands::IsPaused => Request::get_is_paused(),
|
GetCommands::IsPaused => Request::get_is_paused(),
|
||||||
GetCommands::Volume { id } => Request::get_volume(id),
|
GetCommands::Volume { id } => Request::get_volume(id),
|
||||||
|
GetCommands::VolumeMultiplier => Request::get_volume_multiplier(),
|
||||||
GetCommands::Position { id } => Request::get_position(id),
|
GetCommands::Position { id } => Request::get_position(id),
|
||||||
GetCommands::Duration { id } => Request::get_duration(id),
|
GetCommands::Duration { id } => Request::get_duration(id),
|
||||||
GetCommands::State => Request::get_state(),
|
GetCommands::State => Request::get_state(),
|
||||||
@@ -190,6 +195,7 @@ async fn main() -> Result<()> {
|
|||||||
},
|
},
|
||||||
Commands::Set { parameter } => match parameter {
|
Commands::Set { parameter } => match parameter {
|
||||||
SetCommands::Volume { volume, id } => Request::set_volume(volume, id),
|
SetCommands::Volume { volume, id } => Request::set_volume(volume, id),
|
||||||
|
SetCommands::VolumeMultiplier { volume } => Request::set_volume_multiplier(volume),
|
||||||
SetCommands::Position { position, id } => Request::seek(position, id),
|
SetCommands::Position { position, id } => Request::seek(position, id),
|
||||||
SetCommands::Input { name } => Request::set_input(&name),
|
SetCommands::Input { name } => Request::set_input(&name),
|
||||||
SetCommands::Loop { enabled, id } => Request::set_loop(&enabled, id),
|
SetCommands::Loop { enabled, id } => Request::set_loop(&enabled, id),
|
||||||
|
|||||||
@@ -217,6 +217,28 @@ kz = "Әрқашан дыбыс деңгейін есте сақтау"
|
|||||||
he = "זכור תמיד עוצמת קול"
|
he = "זכור תמיד עוצמת קול"
|
||||||
pt-BR = "Lembrar volume"
|
pt-BR = "Lembrar volume"
|
||||||
|
|
||||||
|
[gui.settings.remember_volume_multiplier]
|
||||||
|
en = "Always remember volume multiplier"
|
||||||
|
ru = "Всегда запоминать множитель громкости"
|
||||||
|
es = "Recordar siempre el multiplicador de volumen"
|
||||||
|
fr = "Toujours se souvenir du multiplicateur de volume"
|
||||||
|
zh = "始终记住音量乘数"
|
||||||
|
ar = "تذكر ضرب الصوت دائمًا"
|
||||||
|
kz = "Әрқашан дыбыс деңгейін есте сақтау"
|
||||||
|
he = "זכור תמיד עוצמת קול"
|
||||||
|
pt-BR = "Lembrar volume"
|
||||||
|
|
||||||
|
[gui.settings.volume_multiplier]
|
||||||
|
en = "Volume multiplier"
|
||||||
|
ru = "Множитель громкости"
|
||||||
|
es = "Multiplicador de volumen"
|
||||||
|
fr = "Multiplicateur de volume"
|
||||||
|
zh = "音量乘数"
|
||||||
|
ar = "ضرب الصوت"
|
||||||
|
kz = "Дыбыс деңгейі"
|
||||||
|
he = "עוצמת קול"
|
||||||
|
pt-BR = "Volume"
|
||||||
|
|
||||||
[gui.settings.remember_mic]
|
[gui.settings.remember_mic]
|
||||||
en = "Always remember microphone"
|
en = "Always remember microphone"
|
||||||
ru = "Всегда запоминать микрофон"
|
ru = "Всегда запоминать микрофон"
|
||||||
|
|||||||
@@ -93,6 +93,24 @@ impl App for SoundpadGui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.app_state.volume_multiplier_dragged {
|
||||||
|
make_request_async(Request::set_volume_multiplier(
|
||||||
|
self.app_state.volume_multiplier_slider_value,
|
||||||
|
));
|
||||||
|
|
||||||
|
self.app_state.volume_multiplier_dragged = false;
|
||||||
|
self.app_state.ignore_volume_multiplier_update_until =
|
||||||
|
Some(Instant::now() + Duration::from_millis(300));
|
||||||
|
|
||||||
|
if self.config.save_volume_multiplier
|
||||||
|
&& let Ok(mut daemon_config) = get_daemon_config()
|
||||||
|
{
|
||||||
|
daemon_config.default_volume_multiplier =
|
||||||
|
Some(self.app_state.volume_multiplier_slider_value);
|
||||||
|
update_daemon_config(&daemon_config).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Sync audio player state
|
// Sync audio player state
|
||||||
{
|
{
|
||||||
let mut guard = self
|
let mut guard = self
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::gui::SoundpadGui;
|
use crate::gui::SoundpadGui;
|
||||||
use egui::{Align, Button, Color32, ComboBox, Layout, RichText, Ui};
|
use egui::{Align, Button, Color32, ComboBox, Layout, RichText, Slider, Ui};
|
||||||
use egui_material_icons::icons::ICON_ARROW_BACK;
|
use egui_material_icons::icons::ICON_ARROW_BACK;
|
||||||
use pwsp_lib::types::config::PreferredTheme;
|
use pwsp_lib::types::config::PreferredTheme;
|
||||||
use rust_i18n::t;
|
use rust_i18n::t;
|
||||||
@@ -34,6 +34,10 @@ impl SoundpadGui {
|
|||||||
&mut self.config.save_volume,
|
&mut self.config.save_volume,
|
||||||
t!("gui.settings.remember_volume"),
|
t!("gui.settings.remember_volume"),
|
||||||
);
|
);
|
||||||
|
let save_volume_multiplier_response = ui.checkbox(
|
||||||
|
&mut self.config.save_volume_multiplier,
|
||||||
|
t!("gui.settings.remember_volume_multiplier"),
|
||||||
|
);
|
||||||
let save_input_response =
|
let save_input_response =
|
||||||
ui.checkbox(&mut self.config.save_input, t!("gui.settings.remember_mic"));
|
ui.checkbox(&mut self.config.save_input, t!("gui.settings.remember_mic"));
|
||||||
let save_scale_response = ui.checkbox(
|
let save_scale_response = ui.checkbox(
|
||||||
@@ -46,6 +50,7 @@ impl SoundpadGui {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if save_volume_response.changed()
|
if save_volume_response.changed()
|
||||||
|
|| save_volume_multiplier_response.changed()
|
||||||
|| save_input_response.changed()
|
|| save_input_response.changed()
|
||||||
|| save_scale_response.changed()
|
|| save_scale_response.changed()
|
||||||
|| pause_on_exit_response.changed()
|
|| pause_on_exit_response.changed()
|
||||||
@@ -88,6 +93,39 @@ impl SoundpadGui {
|
|||||||
}
|
}
|
||||||
// --------------------------------
|
// --------------------------------
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
// ----------- Sliders ------------
|
||||||
|
// Volume multiplier
|
||||||
|
let should_update_multiplier = !self.app_state.volume_multiplier_dragged
|
||||||
|
&& self
|
||||||
|
.app_state
|
||||||
|
.ignore_volume_multiplier_update_until
|
||||||
|
.map(|t| std::time::Instant::now() > t)
|
||||||
|
.unwrap_or(true);
|
||||||
|
|
||||||
|
if should_update_multiplier {
|
||||||
|
self.app_state.volume_multiplier_slider_value =
|
||||||
|
self.audio_player_state.volume_multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
let slider = Slider::new(
|
||||||
|
&mut self.app_state.volume_multiplier_slider_value,
|
||||||
|
0.01..=3.0,
|
||||||
|
);
|
||||||
|
let response = ui.add(slider);
|
||||||
|
ui.label(t!("gui.settings.volume_multiplier"));
|
||||||
|
|
||||||
|
if response.changed() {
|
||||||
|
// This condition is required to avoid spamming requests while dragging, but to allow changing the value via TextEdit
|
||||||
|
if !response.dragged() || (response.dragged() && response.drag_stopped()) {
|
||||||
|
self.app_state.volume_multiplier_dragged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// --------------------------------
|
||||||
|
|
||||||
ui.with_layout(Layout::bottom_up(Align::Min), |ui| {
|
ui.with_layout(Layout::bottom_up(Align::Min), |ui| {
|
||||||
ui.label(t!(
|
ui.label(t!(
|
||||||
"gui.settings.version",
|
"gui.settings.version",
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ pub struct FullState {
|
|||||||
pub state: PlayerState,
|
pub state: PlayerState,
|
||||||
pub tracks: Vec<TrackInfo>,
|
pub tracks: Vec<TrackInfo>,
|
||||||
pub volume: f32,
|
pub volume: f32,
|
||||||
|
pub volume_multiplier: f32,
|
||||||
pub current_input: String,
|
pub current_input: String,
|
||||||
pub all_inputs: HashMap<String, String>,
|
pub all_inputs: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
@@ -63,14 +64,17 @@ pub struct AudioPlayer {
|
|||||||
pub input_device_name: Option<String>,
|
pub input_device_name: Option<String>,
|
||||||
|
|
||||||
pub volume: f32, // Master volume
|
pub volume: f32, // Master volume
|
||||||
|
pub volume_multiplier: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioPlayer {
|
impl AudioPlayer {
|
||||||
pub async fn new() -> Result<Self> {
|
pub async fn new() -> Result<Self> {
|
||||||
let (default_input_name, default_volume) = with_daemon_config(|c| {
|
let (default_input_name, default_volume, default_volume_multiplier) =
|
||||||
|
with_daemon_config(|c| {
|
||||||
(
|
(
|
||||||
c.default_input_name.clone(),
|
c.default_input_name.clone(),
|
||||||
c.default_volume.unwrap_or(1.0),
|
c.default_volume.unwrap_or(1.0),
|
||||||
|
c.default_volume_multiplier.unwrap_or(1.0),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -84,6 +88,7 @@ impl AudioPlayer {
|
|||||||
input_device_name: default_input_name,
|
input_device_name: default_input_name,
|
||||||
|
|
||||||
volume: default_volume,
|
volume: default_volume,
|
||||||
|
volume_multiplier: default_volume_multiplier,
|
||||||
};
|
};
|
||||||
|
|
||||||
if audio_player.input_device_name.is_some() {
|
if audio_player.input_device_name.is_some() {
|
||||||
@@ -266,12 +271,16 @@ impl AudioPlayer {
|
|||||||
if let Some(id) = id {
|
if let Some(id) = id {
|
||||||
if let Some(sound) = self.tracks.get_mut(&id) {
|
if let Some(sound) = self.tracks.get_mut(&id) {
|
||||||
sound.volume = volume;
|
sound.volume = volume;
|
||||||
sound.sink.set_volume(self.volume * volume);
|
sound
|
||||||
|
.sink
|
||||||
|
.set_volume(self.volume * sound.volume * self.volume_multiplier);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.volume = volume;
|
self.volume = volume;
|
||||||
for sound in self.tracks.values_mut() {
|
for sound in self.tracks.values_mut() {
|
||||||
sound.sink.set_volume(self.volume * sound.volume);
|
sound
|
||||||
|
.sink
|
||||||
|
.set_volume(self.volume * sound.volume * self.volume_multiplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -351,7 +360,7 @@ impl AudioPlayer {
|
|||||||
.ok_or_else(|| anyhow::anyhow!("stream_handle is unexpectedly missing"))?
|
.ok_or_else(|| anyhow::anyhow!("stream_handle is unexpectedly missing"))?
|
||||||
.mixer();
|
.mixer();
|
||||||
let sink = Player::connect_new(mixer);
|
let sink = Player::connect_new(mixer);
|
||||||
sink.set_volume(self.volume); // Default volume is 1.0 * master
|
sink.set_volume(self.volume * self.volume_multiplier); // Default volume is 1.0 * master
|
||||||
sink.append(source);
|
sink.append(source);
|
||||||
sink.play();
|
sink.play();
|
||||||
|
|
||||||
|
|||||||
@@ -46,11 +46,17 @@ pub struct GetVolumeCommand {
|
|||||||
pub id: Option<u32>,
|
pub id: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct GetVolumeMultiplierCommand {}
|
||||||
|
|
||||||
pub struct SetVolumeCommand {
|
pub struct SetVolumeCommand {
|
||||||
pub volume: Option<f32>,
|
pub volume: Option<f32>,
|
||||||
pub id: Option<u32>,
|
pub id: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SetVolumeMultiplierCommand {
|
||||||
|
pub volume_multiplier: Option<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct GetPositionCommand {
|
pub struct GetPositionCommand {
|
||||||
pub id: Option<u32>,
|
pub id: Option<u32>,
|
||||||
}
|
}
|
||||||
@@ -270,6 +276,18 @@ impl Executable for GetVolumeCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Executable for GetVolumeMultiplierCommand {
|
||||||
|
async fn execute(&self) -> Response {
|
||||||
|
let audio_player = match get_audio_player().await {
|
||||||
|
Ok(player) => player.lock().await,
|
||||||
|
Err(err) => return Response::new(false, format!("Audio player error: {}", err)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Response::new(true, audio_player.volume_multiplier.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Executable for SetVolumeCommand {
|
impl Executable for SetVolumeCommand {
|
||||||
async fn execute(&self) -> Response {
|
async fn execute(&self) -> Response {
|
||||||
@@ -286,6 +304,26 @@ impl Executable for SetVolumeCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Executable for SetVolumeMultiplierCommand {
|
||||||
|
async fn execute(&self) -> Response {
|
||||||
|
if let Some(volume_multiplier) = self.volume_multiplier {
|
||||||
|
let mut audio_player = match get_audio_player().await {
|
||||||
|
Ok(player) => player.lock().await,
|
||||||
|
Err(err) => return Response::new(false, format!("Audio player error: {}", err)),
|
||||||
|
};
|
||||||
|
audio_player.volume_multiplier = volume_multiplier;
|
||||||
|
audio_player.set_volume(volume_multiplier, None); // Reset current volume for all tracks to apply multiplier
|
||||||
|
Response::new(
|
||||||
|
true,
|
||||||
|
format!("Audio volume multiplier was set to {}", volume_multiplier),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Response::new(false, "Invalid volume multiplier value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Executable for GetPositionCommand {
|
impl Executable for GetPositionCommand {
|
||||||
async fn execute(&self) -> Response {
|
async fn execute(&self) -> Response {
|
||||||
@@ -516,6 +554,7 @@ impl Executable for GetFullStateCommand {
|
|||||||
state: audio_player.get_state(),
|
state: audio_player.get_state(),
|
||||||
tracks: audio_player.get_tracks(),
|
tracks: audio_player.get_tracks(),
|
||||||
volume: audio_player.volume,
|
volume: audio_player.volume,
|
||||||
|
volume_multiplier: audio_player.volume_multiplier,
|
||||||
current_input: current_input_nick,
|
current_input: current_input_nick,
|
||||||
all_inputs,
|
all_inputs,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use std::{
|
|||||||
pub struct DaemonConfig {
|
pub struct DaemonConfig {
|
||||||
pub default_input_name: Option<String>,
|
pub default_input_name: Option<String>,
|
||||||
pub default_volume: Option<f32>,
|
pub default_volume: Option<f32>,
|
||||||
|
pub default_volume_multiplier: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DaemonConfig {
|
impl DaemonConfig {
|
||||||
@@ -73,6 +74,7 @@ pub struct GuiConfig {
|
|||||||
pub left_panel_width: f32,
|
pub left_panel_width: f32,
|
||||||
|
|
||||||
pub save_volume: bool,
|
pub save_volume: bool,
|
||||||
|
pub save_volume_multiplier: bool,
|
||||||
pub save_input: bool,
|
pub save_input: bool,
|
||||||
pub save_scale_factor: bool,
|
pub save_scale_factor: bool,
|
||||||
pub pause_on_exit: bool,
|
pub pause_on_exit: bool,
|
||||||
@@ -117,6 +119,7 @@ impl Default for GuiConfig {
|
|||||||
left_panel_width: 280.0,
|
left_panel_width: 280.0,
|
||||||
|
|
||||||
save_volume: false,
|
save_volume: false,
|
||||||
|
save_volume_multiplier: false,
|
||||||
save_input: false,
|
save_input: false,
|
||||||
save_scale_factor: false,
|
save_scale_factor: false,
|
||||||
pause_on_exit: false,
|
pause_on_exit: false,
|
||||||
|
|||||||
@@ -31,13 +31,16 @@ pub struct AppState {
|
|||||||
|
|
||||||
pub show_settings: bool,
|
pub show_settings: bool,
|
||||||
pub volume_dragged: bool,
|
pub volume_dragged: bool,
|
||||||
|
pub volume_multiplier_dragged: bool,
|
||||||
pub force_focus_search: bool,
|
pub force_focus_search: bool,
|
||||||
|
|
||||||
pub volume_slider_value: f32,
|
pub volume_slider_value: f32,
|
||||||
|
pub volume_multiplier_slider_value: f32,
|
||||||
|
|
||||||
pub search_field_id: Option<Id>,
|
pub search_field_id: Option<Id>,
|
||||||
|
|
||||||
pub ignore_volume_update_until: Option<Instant>,
|
pub ignore_volume_update_until: Option<Instant>,
|
||||||
|
pub ignore_volume_multiplier_update_until: Option<Instant>,
|
||||||
|
|
||||||
pub current_dir: Option<PathBuf>,
|
pub current_dir: Option<PathBuf>,
|
||||||
pub dirs: Vec<PathBuf>,
|
pub dirs: Vec<PathBuf>,
|
||||||
@@ -65,6 +68,7 @@ pub struct AudioPlayerState {
|
|||||||
pub tracks: Vec<TrackInfo>,
|
pub tracks: Vec<TrackInfo>,
|
||||||
|
|
||||||
pub volume: f32, // Master volume
|
pub volume: f32, // Master volume
|
||||||
|
pub volume_multiplier: f32,
|
||||||
|
|
||||||
pub current_input: String,
|
pub current_input: String,
|
||||||
pub all_inputs: HashMap<String, String>,
|
pub all_inputs: HashMap<String, String>,
|
||||||
|
|||||||
@@ -95,6 +95,10 @@ impl Request {
|
|||||||
Request::new("get_volume", args)
|
Request::new("get_volume", args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_volume_multiplier() -> Self {
|
||||||
|
Request::new("get_volume_multiplier", vec![])
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_position(id: Option<u32>) -> Self {
|
pub fn get_position(id: Option<u32>) -> Self {
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
let id_str;
|
let id_str;
|
||||||
@@ -139,6 +143,13 @@ impl Request {
|
|||||||
Request::new("set_volume".to_string(), args)
|
Request::new("set_volume".to_string(), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_volume_multiplier(volume: f32) -> Self {
|
||||||
|
Request::new(
|
||||||
|
"set_volume_multiplier",
|
||||||
|
vec![("volume_multiplier", &volume.to_string())],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn seek(position: f32, id: Option<u32>) -> Self {
|
pub fn seek(position: f32, id: Option<u32>) -> Self {
|
||||||
let mut args = vec![("position".to_string(), position.to_string())];
|
let mut args = vec![("position".to_string(), position.to_string())];
|
||||||
if let Some(id) = id {
|
if let Some(id) = id {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ pub fn parse_command(request: &Request) -> Option<Box<dyn Executable + Send>> {
|
|||||||
"is_paused" => Some(Box::new(IsPausedCommand {})),
|
"is_paused" => Some(Box::new(IsPausedCommand {})),
|
||||||
"get_state" => Some(Box::new(GetStateCommand {})),
|
"get_state" => Some(Box::new(GetStateCommand {})),
|
||||||
"get_volume" => Some(Box::new(GetVolumeCommand { id })),
|
"get_volume" => Some(Box::new(GetVolumeCommand { id })),
|
||||||
|
"get_volume_multiplier" => Some(Box::new(GetVolumeMultiplierCommand {})),
|
||||||
"set_volume" => {
|
"set_volume" => {
|
||||||
let volume = request
|
let volume = request
|
||||||
.args
|
.args
|
||||||
@@ -24,6 +25,15 @@ pub fn parse_command(request: &Request) -> Option<Box<dyn Executable + Send>> {
|
|||||||
.ok();
|
.ok();
|
||||||
Some(Box::new(SetVolumeCommand { volume, id }))
|
Some(Box::new(SetVolumeCommand { volume, id }))
|
||||||
}
|
}
|
||||||
|
"set_volume_multiplier" => {
|
||||||
|
let volume_multiplier = request
|
||||||
|
.args
|
||||||
|
.get("volume_multiplier")
|
||||||
|
.unwrap_or(&String::new())
|
||||||
|
.parse::<f32>()
|
||||||
|
.ok();
|
||||||
|
Some(Box::new(SetVolumeMultiplierCommand { volume_multiplier }))
|
||||||
|
}
|
||||||
"get_position" => Some(Box::new(GetPositionCommand { id })),
|
"get_position" => Some(Box::new(GetPositionCommand { id })),
|
||||||
"seek" => {
|
"seek" => {
|
||||||
let position = request
|
let position = request
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ pub fn start_app_state_thread(audio_player_state_shared: Arc<Mutex<AudioPlayerSt
|
|||||||
};
|
};
|
||||||
guard.tracks = full_state.tracks;
|
guard.tracks = full_state.tracks;
|
||||||
guard.volume = full_state.volume;
|
guard.volume = full_state.volume;
|
||||||
|
guard.volume_multiplier = full_state.volume_multiplier;
|
||||||
guard.current_input = full_state
|
guard.current_input = full_state
|
||||||
.current_input
|
.current_input
|
||||||
.split(" - ")
|
.split(" - ")
|
||||||
|
|||||||
Reference in New Issue
Block a user