Skip to content

Commit

Permalink
add playerctl stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
jlo62 committed Oct 19, 2024
1 parent dbb8b72 commit 0f3b168
Show file tree
Hide file tree
Showing 18 changed files with 625 additions and 272 deletions.
606 changes: 334 additions & 272 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ nix = "0.26.2"
blight = "0.7.0"
anyhow = "1.0.75"
thiserror = "1.0.49"
mpris = "2.0.1"
2 changes: 2 additions & 0 deletions data/icons/scalable/status/pause-large-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions data/icons/scalable/status/play-large-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions data/icons/scalable/status/playlist-consecutive-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions data/icons/scalable/status/playlist-shuffle-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions data/icons/scalable/status/seek-backward-large-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions data/icons/scalable/status/seek-forward-large-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions data/icons/scalable/status/stop-large-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions data/swayosd.gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,13 @@
<file>icons/scalable/status/source-volume-medium-symbolic.svg</file>
<file>icons/scalable/status/source-volume-low-symbolic.svg</file>
<file>icons/scalable/status/source-volume-muted-symbolic.svg</file>

<file>icons/scalable/status/pause-large-symbolic.svg</file>
<file>icons/scalable/status/play-large-symbolic.svg</file>
<file>icons/scalable/status/seek-backward-large-symbolic.svg</file>
<file>icons/scalable/status/seek-forward-large-symbolic.svg</file>
<file>icons/scalable/status/playlist-consecutive-symbolic.svg</file>
<file>icons/scalable/status/playlist-shuffle-symbolic.svg</file>
<file>icons/scalable/status/stop-large-symbolic.svg</file>
</gresource>
</gresources>
6 changes: 6 additions & 0 deletions src/argtypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub enum ArgTypes {
TopMargin = isize::MIN + 1,
MaxVolume = isize::MIN + 2,
CustomIcon = isize::MIN + 3,
Player = isize::MIN + 4,
// Other
None = 0,
CapsLock = 1,
Expand All @@ -23,6 +24,7 @@ pub enum ArgTypes {
NumLock = 10,
ScrollLock = 11,
CustomMessage = 13,
Playerctl = 14,
}

impl fmt::Display for ArgTypes {
Expand All @@ -46,6 +48,8 @@ impl fmt::Display for ArgTypes {
ArgTypes::TopMargin => "TOP-MARGIN",
ArgTypes::CustomMessage => "CUSTOM-MESSAGE",
ArgTypes::CustomIcon => "CUSTOM-ICON",
ArgTypes::Playerctl => "PLAYERCTL",
ArgTypes::Player => "PLAYER",
};
return write!(f, "{}", string);
}
Expand Down Expand Up @@ -73,6 +77,8 @@ impl str::FromStr for ArgTypes {
"TOP-MARGIN" => ArgTypes::TopMargin,
"CUSTOM-MESSAGE" => ArgTypes::CustomMessage,
"CUSTOM-ICON" => ArgTypes::CustomIcon,
"PLAYERCTL" => ArgTypes::Playerctl,
"PLAYER" => ArgTypes::Player,
other_type => return Err(other_type.to_owned()),
};
Ok(result)
Expand Down
18 changes: 18 additions & 0 deletions src/client/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ fn main() -> Result<(), glib::Error> {
"Shows brightness osd and raises or loweres all available sources of brightness device",
Some("raise|lower|(±)number"),
);

// Control players cmdline arg
app.add_main_option(
"playerctl",
glib::Char::from(0),
OptionFlags::NONE,
OptionArg::String,
"Shows Playerctl osd and runs the playerctl command",
Some("play-pause|play|pause|stop|next|prev|shuffle"),
);
app.add_main_option(
"max-volume",
glib::Char::from(0),
Expand All @@ -172,6 +182,14 @@ fn main() -> Result<(), glib::Error> {
"For which device to increase/decrease audio",
Some("Pulseaudio device name (pactl list short sinks|sources)"),
);
app.add_main_option(
"player",
glib::Char::from(0),
OptionFlags::NONE,
OptionArg::String,
"For which player to run the playerctl commands",
Some("auto|all|(playerctl -l)"),
);

app.add_main_option(
"custom-message",
Expand Down
22 changes: 22 additions & 0 deletions src/global_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ pub(crate) fn handle_application_args(
}
}
}
"playerctl" => {

Check warning on line 98 in src/global_utils.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/SwayOSD/SwayOSD/src/client/../global_utils.rs

Check warning on line 98 in src/global_utils.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/SwayOSD/SwayOSD/src/server/../global_utils.rs
let value = child.value().str().unwrap_or("");
match value {
"play-pause" | "play" | "pause" | "next" |"prev" | "previous" | "shuffle" | "stop" => (),
x => {
eprintln!("Unknown Playerctl command: \"{}\"!...", x);
return (HandleLocalStatus::FAILURE, actions)
}
}

(ArgTypes::Playerctl, Some(value.to_string()))

Check warning on line 108 in src/global_utils.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/SwayOSD/SwayOSD/src/client/../global_utils.rs

Check warning on line 108 in src/global_utils.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/SwayOSD/SwayOSD/src/server/../global_utils.rs
},
"device" => {
let value = match child.value().str() {
Some(v) => v.to_string(),
Expand Down Expand Up @@ -125,6 +137,16 @@ pub(crate) fn handle_application_args(
};
(ArgTypes::CustomIcon, Some(value))
}
"player" => {
let value = match child.value().str() {
Some(v) => v.to_string(),
None => {
eprintln!("--player found but no name given");
return (HandleLocalStatus::FAILURE, actions);
}
};
(ArgTypes::Player, Some(value))
}
"top-margin" => {
let value = child.value().str().unwrap_or("").trim();
match value.parse::<f32>() {
Expand Down
164 changes: 164 additions & 0 deletions src/mpris-backend/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
use mpris::{

Check warning on line 1 in src/mpris-backend/mod.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/SwayOSD/SwayOSD/src/server/../mpris-backend/mod.rs
PlayerFinder,
Player,
PlaybackStatus,
};

use std::error::Error;
use crate::utils::get_player;

pub enum PlayerctlAction {
PlayPause,
Play,
Pause,
Stop,
Next,
Prev,
Shuffle,
}

#[derive(Clone, Debug)]
pub enum PlayerctlDeviceRaw {

Check warning on line 21 in src/mpris-backend/mod.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/SwayOSD/SwayOSD/src/server/../mpris-backend/mod.rs
None,
All,
Some(String),
}

pub enum PlayerctlDevice {
All(Vec<Player>),

Check warning on line 28 in src/mpris-backend/mod.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/SwayOSD/SwayOSD/src/server/../mpris-backend/mod.rs
Some(Player),
}

pub struct Playerctl {
player: PlayerctlDevice,

Check warning on line 33 in src/mpris-backend/mod.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/SwayOSD/SwayOSD/src/server/../mpris-backend/mod.rs
action: PlayerctlAction,
pub icon: Option<String>,
pub label: Option<String>,
}

impl Playerctl {
pub fn new(action: PlayerctlAction) -> Result<Playerctl, Box<dyn Error>> {

Check warning on line 40 in src/mpris-backend/mod.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/SwayOSD/SwayOSD/src/server/../mpris-backend/mod.rs
let playerfinder = PlayerFinder::new()?;
let player = get_player();
let player = match player {
PlayerctlDeviceRaw::None => PlayerctlDevice::Some(playerfinder.find_active()?),
PlayerctlDeviceRaw::Some(name) => {
PlayerctlDevice::Some(playerfinder.find_by_name(name.as_str())?)
},
PlayerctlDeviceRaw::All => PlayerctlDevice::All(playerfinder.find_all()?),
};
Ok(Self {
player,
action,
icon: None,
label: None,
})
}
pub fn run(&mut self) -> Result<(), Box<dyn Error>> {
use PlayerctlAction::*;
use PlaybackStatus::*;
let run_single = |player: &Player| -> Result<&str, Box<dyn Error>> {
let out = match self.action {
PlayPause => {
match player.get_playback_status()? {
Playing => {player.pause()?; "pause-large -symbolic"},
Paused | Stopped => {player.play()?;"play-large-symbolic"}
}
},
Shuffle => {
let shuffle = player.get_shuffle()?;
player.set_shuffle(!shuffle)?;
if shuffle {
"playlist-consecutive-symbolic"
} else {
"playlist-shuffle-symbolic"
}
},
Play => {player.play()?; "play-large-symbolic"},
Pause => {player.pause()?; "pause-large-symbolic"},
Stop => {player.stop()?; "stop-large-symbolic"},
Next => {player.next()?; "media-seek-forward-symbolic"},
Prev => {player.previous()?; "media-seek-backward-symbolic"},
};
Ok(out)
};
let mut metadata = Err("some errro");
let icon = match &self.player {
PlayerctlDevice::Some(player) => {
metadata = player.get_metadata().or_else(|x| Err(""));
run_single(player)?
},
PlayerctlDevice::All(players) => {
let mut icon = Err("couldn't change any players!");
for player in players {
let icon_new = run_single(player);
if let Ok(icon_new) = icon_new {
if icon.is_err() {
icon = Ok(icon_new);
}
};
if let Err(_) = metadata {
metadata = player.get_metadata().or_else(|x| Err(""));
}
}
icon?
},
};

self.icon = Some(icon.to_string());
let label = if let Ok(metadata) = metadata {
let artist = metadata.artists().and_then(|x| {
if x.len() != 0 {
Some(x[0].to_string())
} else {
None
}
});
let title = metadata.title().and_then(|x| Some(x.to_string()));
if title.is_none() {
if artist.is_none() {
None
} else {
artist
}
} else {
if artist.is_none() {
title
} else {
Some(format!("{} - {}", title.unwrap(), artist.unwrap()))
}
}
} else {
None
};
self.label = label;
Ok(())
}
}

impl PlayerctlAction {
pub fn from(action: &str) -> Result<Self, String> {

Check warning on line 140 in src/mpris-backend/mod.rs

View workflow job for this annotation

GitHub Actions / cargo fmt

Diff in /home/runner/work/SwayOSD/SwayOSD/src/server/../mpris-backend/mod.rs
use PlayerctlAction::*;
match action {
"play-pause" => Ok(PlayPause),
"play" => Ok(Play),
"pause" => Ok(Pause),
"stop" => Ok(Stop),
"next" => Ok(Next),
"prev" | "previous" => Ok(Prev),
"shuffle" => Ok(Shuffle),
x => Err(x.to_string())
}
}
}

impl PlayerctlDeviceRaw {
pub fn from(player: String) -> Result<Self, ()> {
use PlayerctlDeviceRaw::*;
match player.as_str() {
"auto" | "" => Ok(None),
"all" => Ok(All),
_ => Ok(Some(player))
}
}
}
26 changes: 26 additions & 0 deletions src/server/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,32 @@ impl SwayOSDApplication {
};
set_max_volume(volume)
}
(ArgTypes::Player, name) => {
set_player(name.unwrap_or("".to_string()))
}
(ArgTypes::Playerctl, value) => {
use crate::playerctl::*;
let value = &value.unwrap_or("".to_string());

let action = PlayerctlAction::from(value).unwrap();
if let Ok(mut player) = Playerctl::new(action) {
match player.run() {
Ok(_) => {
let (icon, label) = (player.icon.unwrap(), player.label.unwrap());
for window in osd_app.windows.borrow().to_owned() {
window.changed_player(&icon, &label)
}
},
Err(x) => {
eprintln!("couldn't run player change: \"{:?}\"!", x)
},
}
} else {
eprintln!("Unable to get players! are any opened?")
}

reset_player();
}
(ArgTypes::DeviceName, name) => {
set_device_name(name.unwrap_or(DEVICE_NAME_DEFAULT.to_string()))
}
Expand Down
3 changes: 3 additions & 0 deletions src/server/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ mod global_utils;
#[path = "../brightness_backend/mod.rs"]
mod brightness_backend;

#[path = "../mpris-backend/mod.rs"]
mod playerctl;

#[macro_use]
extern crate shrinkwraprs;

Expand Down
12 changes: 12 additions & 0 deletions src/server/osd_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,18 @@ impl SwayosdWindow {
self.run_timeout();
}

pub fn changed_player(&self, icon: &str, label: &str) {
self.clear_osd();

let icon = self.build_icon_widget(&icon);
let label = self.build_text_widget(Some(&label));

self.container.add(&icon);
self.container.add(&label);

self.run_timeout();
}

pub fn changed_keylock(&self, key: KeysLocks, state: bool) {
self.clear_osd();

Expand Down
Loading

0 comments on commit 0f3b168

Please sign in to comment.