Open victorz opened 3 years ago
Do you want to work on a PR?
Do you want to work on a PR?
Sure? I need someone to explain how the plugin works though. I tried to study the code but I can't follow along in it. Been a while since I did any python.
Maybe its an idea for @Cybolic or somebody else.
@victorz I use a workaround for this: a script that keeps the most recent player in a file, and my media keys will interact with that player. Here is my script:
#!/bin/sh
get_players(){
# gets a list of MPRIS compatible players
echo `qdbus | egrep -i 'org.mpris.MediaPlayer2|plasma.browser_integration'`
}
get_status(){
# get the current playback status of the given player
echo `qdbus $1 /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlaybackStatus 2>&1`
}
setFirstPausedPlayer() {
for player in $(get_players) ; do
if [[ $(get_status $player) == 'Paused' ]]; then
echo "$player" > ~/.config/activePlayer/currentPlaying.txt
break
fi
done
}
while true ; do
for player in $(get_players) ; do
if [[ $(get_status $player) == 'Playing' ]]; then
# if the player is playing, set it as the current playing player
echo $player > ~/.config/activePlayer/currentPlaying.txt
break
elif [[ $(get_status $player) == 'Stopped' ]]; then
# if a player is stopped, we don't want to start it again
setFirstPausedPlayer
fi
done
# if the current player does not exist anymore, look for a new one
currentPlayer=`cat ~/.config/activePlayer/currentPlaying.txt`
if [[ $(get_status $currentPlayer) == *"does not exist"* ]]; then
# if a player is stopped, search for the next paused player
setFirstPausedPlayer
fi
sleep 0.25
done
This script runs in the background and is started when I log in to my X session.
To control that latest player, I use this script:
#!/bin/sh
#Get command
case $1 in
'play-pause')
cmd='/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause';;
'next')
cmd='/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next';;
'previous')
cmd='/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous';;
'stop')
cmd='/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Stop';;
'skipForward')
# skip 5 second forward
cmd='/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Seek 5000000';;
'skipBackward')
# skip 5 second backward
cmd='/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Seek -5000000';;
*)
esac
#Send command to qdbus
if [[ `qdbus | egrep -i 'org.mpris.MediaPlayer2|plasma-browser-integration' | wc -l` -eq 1 ]]; then
# if only one player is detected
qdbus `qdbus | egrep -i 'org.mpris.MediaPlayer2|plasma-browser-integration'` $cmd
else
# if multiple players are detected, interact with the most recent active player
qdbus `cat ~/.config/activePlayer/currentPlaying.txt` $cmd
fi
unset cmd
In sxhkdrc (the config file for bspwm's hotkey daemon), I define these actions:
########################################## MEDIA KEYS ##########################################
# Media control
XF86Audio{Play,Prev,Next,Stop}
~/.config/activePlayer/control.sh {play-pause,previous,next,stop}
# Fastforward/Rewind x seconds
shift + XF86Audio{Next,Prev}
~/.config/activePlayer/control.sh {skipForward, skipBackward}
@zjeffer
That's one solution. Although my issue is that this module does the wrong thing. My media keys do the right thing, and control the expected player (most recent). I use playerctl and set my keys up in my i3 config. I use playerctl without the player flag, so that I don't limit the command/keys to only one player. But this module seems to flip between players when I pause the current player externally (e.g. via media keys).
Expected behavior would be:
If one player is playing, show that.
If multiple players are playing, show the most recently interacted-with player.
If no players are playing, show the most recently interacted-with player.
I hope that makes sense and is achievable. Thanks!
If one player is playing, show that. If multiple players are playing, show the most recently interacted-with player. If no players are playing, show the most recently interacted-with player.
This is what my script fixes, but indeed only with media keys. To fix this in the module, we could implement the above bash script into the python script. I'm going to look into it.
I managed to implement a way to keep the most recent players, the problem is that the module's buttons will start a new instance of the Python script, so that instance never knows which players were interacted with recently (as they are kept in memory).
I'll try saving the most recent players in a file for now, and reading them from that file every time a module button is pressed.
Would it be possible to use the "tail" feature of polybar instead? So that a single instance is always running, but each new line of output will be the new state in the bar? That way you could keep the player state in the script and not have to use a file on disk for this. I don't know, just spit-balling. :-)
I thought so too, but I have no idea how to program that :)
I made a few custom scripts that do this, and all it requires is that the script keeps running, with a loop or has its input piped to it or something, and that it keeps outputting lines of statuses (separated by newlines). So if you can accomplish that with this script, I think we'd be golden.
Although obviously this would be a major version as it breaks existing configs. But maybe that's okay? I don't know how you feel about that.
Doesn't sound that difficult, I'll look into that in the next couple of days.
Do you have a link to those scripts you made?
Hmm, I don't have them in a repo I don't think. I'll look into that tomorrow to see how I can best get those to you. 🙂 Cheers!
Sorry for the delay on this! Vacation came and went, finally have some time at the computer.
One example of this is a script I have called dbus-listen.sh, which looks like this:
#!/bin/bash
watchexpr="$1"
shift 1
dbus-monitor --profile "$watchexpr" |
while read -r line
do
sh -c "$*"
done
The script monitors a dbus interface given by the parameters to the script, and for every line that the monitor reads, it executes a command, also given by (the rest of) the parameters to the script.
dbus-monitor simply runs forever until killed, and the command is expected to print one polybar format line per dbus monitor trigger.
I use the script in my polybar for various things, one of which is to mute the microphone system-wide, like this:
[module/mic-mute]
type = custom/script
exec = dbus-listen.sh sender=user.victor,member=MicMuteToggle "pamixer --get-mute --default-source | sed -e 's/true/%{F#f05050}%{F-}/;>
tail = true
click-left = mic-mute-toggle.sh
click-right = pavucontrol -t 4
A simpler script for testing purposes would probably be something like this though:
#!/bin/bash
val=true
while true
do
print $val
if [[ val = true ]]
then
val=false
else
val=true
fi
done
I hope this helps!
When I'm playing Spotify and another thing, e.g. Pocket Casts web player, or YouTube, etc., there are multiple players. If I click the player-mpris-tail module to pause say currently-playing Pocket Casts, then Spotify suddenly shows up in the module. Possibly due to the formatted output by the module? But pressing unpause on my media keys again actually plays Pocket Casts again, yet clicking the module would resume Spotify playback instead.
It would be good to sort the players which have been "touched"/interacted with by recency, so that the module doesn't flip between players when interacting with it. The only thing that should change the order is by manually starting or stopping another player externally.
Thanks for your consideration.