Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add volume slider #529

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,302 changes: 661 additions & 641 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion data/dev.alextren.Spot.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,9 @@
<default>0</default>
<summary>Port to communicate with Spotify's server (access point). Setting to 0 (default) allows Spot to use servers running on any port.</summary>
</key>
<key name="volume" type='d'>
<default>0.7</default>
<summary>Volume</summary>
</key>
</schema>
</schemalist>
</schemalist>
15 changes: 15 additions & 0 deletions src/app/components/playback/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ impl PlaybackModel {
self.dispatcher
.dispatch(PlaybackAction::Seek(position).into());
}

fn change_volume(&self, volume: f64) {
self.dispatcher
.dispatch(PlaybackAction::SetVolume(volume).into())
}
}

pub struct PlaybackControl {
Expand All @@ -90,6 +95,9 @@ impl PlaybackControl {
widget.connect_repeat(clone!(@weak model => move || model.toggle_repeat()));
widget.connect_seek(clone!(@weak model => move |position| model.seek_to(position)));
widget.connect_now_playing_clicked(clone!(@weak model => move || model.go_home()));
widget.connect_volume_changed(
clone!(@weak model => move |volume| model.change_volume(volume)),
);

Self {
model,
Expand Down Expand Up @@ -124,6 +132,10 @@ impl PlaybackControl {
}
}

fn sync_volume(&self, volume: f64) {
self.widget.set_volume(volume);
}

fn sync_seek(&self, pos: u32) {
self.widget.set_seek_position(pos as f64);
}
Expand Down Expand Up @@ -156,6 +168,9 @@ impl EventListener for PlaybackControl {
AppEvent::SelectionEvent(SelectionEvent::SelectionModeChanged(active)) => {
self.widget.set_seekbar_visible(!active);
}
AppEvent::PlaybackEvent(PlaybackEvent::VolumeSet(volume)) => {
self.sync_volume(*volume);
}
_ => {}
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/app/components/playback/playback_controls.blp
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,15 @@ template $PlaybackControlsWidget : Box {
icon-name: "media-playlist-consecutive-symbolic";
tooltip-text: _("Repeat");
}

ScaleButton volume_slider {
halign: end;
tooltip-text: _("Volume");
adjustment: Adjustment {
step-increment: 0.01;
page-increment: 0.10;
upper: 1.0;
lower: 0.0;
};
}
}
27 changes: 26 additions & 1 deletion src/app/components/playback/playback_controls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ mod imp {

#[template_child]
pub repeat: TemplateChild<gtk::Button>,

#[template_child]
pub volume_slider: TemplateChild<gtk::ScaleButton>,
}

#[glib::object_subclass]
Expand All @@ -43,7 +46,12 @@ mod imp {
}
}

impl ObjectImpl for PlaybackControlsWidget {}
impl ObjectImpl for PlaybackControlsWidget {
fn constructed(&self) {
self.parent_constructed();
self.volume_slider.set_icons(&["audio-volume-high-symbolic"]);
}
}
impl WidgetImpl for PlaybackControlsWidget {}
impl BoxImpl for PlaybackControlsWidget {}
}
Expand Down Expand Up @@ -86,6 +94,12 @@ impl PlaybackControlsWidget {
self.imp().repeat.set_icon_name(repeat_mode_icon);
}

pub fn set_volume(&self, volume: f64) {
imp::PlaybackControlsWidget::from_obj(self)
.volume_slider
.set_value(volume)
}

pub fn connect_play_pause<F>(&self, f: F)
where
F: Fn() + 'static,
Expand Down Expand Up @@ -120,4 +134,15 @@ impl PlaybackControlsWidget {
{
self.imp().repeat.connect_clicked(move |_| f());
}

pub fn connect_volume_changed<F>(&self, f: F)
where
F: Fn(f64) + 'static,
{
imp::PlaybackControlsWidget::from_obj(self)
.volume_slider
.connect_value_changed(move |_, value| {
f(value);
});
}
}
17 changes: 16 additions & 1 deletion src/app/components/playback/playback_widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl PlaybackWidget {
let weak_self = self.downgrade();
worker.send_local_task(async move {
let loader = ImageLoader::new();
let result = loader.load_remote(&url, "jpg", 48, 48).await;
let result = loader.load_remote(&url, "jpg", 64, 64).await;
if let (Some(ref _self), Some(ref result)) = (weak_self.upgrade(), result) {
_self.set_artwork(result);
}
Expand Down Expand Up @@ -136,6 +136,12 @@ impl PlaybackWidget {
self.set_seek_position(value);
}

pub fn set_volume(&self, volume: f64) {
let widget = imp::PlaybackWidget::from_instance(self);
widget.controls.set_volume(volume);
widget.controls_mobile.set_volume(volume);
}

pub fn connect_now_playing_clicked<F>(&self, f: F)
where
F: Fn() + Clone + 'static,
Expand Down Expand Up @@ -239,4 +245,13 @@ impl PlaybackWidget {
widget.controls.connect_repeat(f.clone());
widget.controls_mobile.connect_repeat(f);
}

pub fn connect_volume_changed<F>(&self, f: F)
where
F: Fn(f64) + Clone + 'static,
{
let widget = imp::PlaybackWidget::from_instance(self);
widget.controls.connect_volume_changed(f.clone());
widget.controls_mobile.connect_volume_changed(f);
}
}
11 changes: 11 additions & 0 deletions src/app/components/playback/volume_slider.blp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
template $VolumeButton: ScaleButton {
receives-default: true;
halign: end;
tooltip-text: _("Volume");
adjustment: Adjustment {
step-increment: 0.01;
page-increment: 0.10;
upper: 1.0;
lower: 0.0;
};
}
7 changes: 4 additions & 3 deletions src/connect/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ impl ConnectPlayer {
debug!("polling connect device...");
let player_state = self.api.player_state().await;
let Ok(state) = player_state else {
self.device_lost();
return;
self.device_lost();
return;
};
self.apply_remote_state(&state).await;
if let Ok(mut last_state) = self.last_state.write() {
Expand All @@ -133,7 +133,8 @@ impl ConnectPlayer {
source,
offset,
song,
} = command else {
} = command
else {
panic!("Illegal call");
};
let is_diff_song = current_state
Expand Down
24 changes: 14 additions & 10 deletions src/player/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@ pub enum AudioBackend {
Alsa(String),
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq)]
pub struct SpotifyPlayerSettings {
pub bitrate: Bitrate,
pub backend: AudioBackend,
pub gapless: bool,
pub ap_port: Option<u16>,
pub volume: f64,
}

impl Default for SpotifyPlayerSettings {
Expand All @@ -81,6 +82,7 @@ impl Default for SpotifyPlayerSettings {
gapless: true,
backend: AudioBackend::PulseAudio,
ap_port: None,
volume: 0.6,
}
}
}
Expand All @@ -107,9 +109,7 @@ impl SpotifyPlayer {
async fn handle(&mut self, action: Command) -> Result<(), SpotifyError> {
match action {
Command::PlayerSetVolume(volume) => {
if let Some(mixer) = self.mixer.as_mut() {
mixer.set_volume((VolumeCtrl::MAX_VOLUME as f64 * volume) as u16);
}
self.set_volume(volume);
Ok(())
}
Command::PlayerResume => {
Expand Down Expand Up @@ -220,6 +220,13 @@ impl SpotifyPlayer {
}
}

fn set_volume(&mut self, volume: f64) {
if let Some(mixer) = self.mixer.as_mut() {
mixer.set_volume((VolumeCtrl::MAX_VOLUME as f64 * volume) as u16);
self.settings.volume = volume;
}
}

fn create_player(&mut self, session: Session) -> (Player, PlayerEventChannel) {
let backend = self.settings.backend.clone();

Expand All @@ -233,17 +240,14 @@ impl SpotifyPlayer {
let soft_volume = self
.mixer
.get_or_insert_with(|| {
let mix = Box::new(SoftMixer::open(MixerConfig {
Box::new(SoftMixer::open(MixerConfig {
// This value feels reasonable to me. Feel free to change it
volume_ctrl: VolumeCtrl::Log(VolumeCtrl::DEFAULT_DB_RANGE / 2.0),
..Default::default()
}));
// TODO: Should read volume from somewhere instead of hard coding.
// Sets volume to 100%
mix.set_volume(VolumeCtrl::MAX_VOLUME);
mix
}))
})
.get_soft_volume();
self.set_volume(self.settings.volume);
Player::new(player_config, session, soft_volume, move || match backend {
AudioBackend::GStreamer(pipeline) => {
let backend = audio_backend::find(Some("gstreamer".to_string())).unwrap();
Expand Down
3 changes: 3 additions & 0 deletions src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,14 @@ impl SpotifyPlayerSettings {
x => Some(x as u16),
};

let volume = settings.double("volume").clamp(0.0, 1.0);

Some(Self {
bitrate,
backend,
gapless,
ap_port,
volume
})
}
}
Expand Down
Loading