PrayagS / polybar-spotify

:musical_note: Spotify status and controls module for Polybar with text scrolling
MIT License
581 stars 38 forks source link

Playerctl cannot detect players when script is running #17

Closed bowen-song closed 2 years ago

bowen-song commented 2 years ago

Setup: player = sublime-music (*sonic) player Problem: When I add the hook to the appropriate ipc polybar module, my playerctl is unable to detect sublime-music. Playerctl is normally fully functional with sublime-music, but breaks when the script is added.

get_player_status.sh

#!/bin/bash

PARENT_BAR="mainbar"
PARENT_BAR_PID=$(pgrep -a "polybar" | grep "$PARENT_BAR" | cut -d" " -f1)

PLAYER="sublime-music"

FORMAT="{{ title }} - {{ artist }}"

update_hooks() {
    while IFS= read -r id
    do
        polybar-msg -p "$id" hook music-pp $2 1>/dev/null 2>&1 # upon adding hook to "music-pp", playerctl shows no players
    done < <(echo "$1")
}

PLAYERCTL_STATUS=$(playerctl --player=$PLAYER status 2>/dev/null)
EXIT_CODE=$?

if [ $EXIT_CODE -eq 0 ]; then
    STATUS=$PLAYERCTL_STATUS
else
    STATUS="No player is running"
fi

if [ "$1" == "--status" ]; then
    echo "$STATUS"
else
    if [ "$STATUS" = "Stopped" ]; then
        echo "No music is playing"
    elif [ "$STATUS" = "Paused"  ]; then
        update_hooks "$PARENT_BAR_PID" 2
        playerctl --player=$PLAYER metadata --format "$FORMAT"
    elif [ "$STATUS" = "No player is running"  ]; then
        echo "$STATUS"
    else
        update_hooks "$PARENT_BAR_PID" 1
        playerctl --player=$PLAYER metadata --format "$FORMAT"
    fi
fi

polybar relevant modules:

[module/music]
type = custom/script
tail = true
format-prefix = " "
format = <label>
exec = ~/.config/polybar/scroll_sublime_music_status.sh

[module/music-pp]
type = custom/ipc
hook-0 = echo ""
hook-1 = echo ""
initial = 1
click-left = playerctl sublime-music play-pause

I'm not really that well versed in scripting/playerctl so I'm not sure exactly why adding the hook to the module breaks playerctl functionality for sublime-music. Hope you can help figure out what the issue is. Thanks!

PrayagS commented 2 years ago

Thanks for reaching out and opening an issue.

So from what I understand, if you don't have the polybar module running, you can control your player using playerctl like

playerctl --player=sublime-music <command>

Please let me know if my understanding is correct or not.

What happens if you have the module running but don't enable the hooks? Meaning that you comment the hooks in your polybar config and also comment the calls to update_hooks in the script. Because from my experience, the polybar module and playerctl are independent. The hooks are just communicating with polybar and shouldn't mess up with the functionality of playerctl. Whether you have the bar running or not, you should be able to control your player using playerctl directly.

Also, make sure that you have enabled ipc for the bar in which these modules are being placed.

Please let me know about any troubleshooting that you have tried.

bowen-song commented 2 years ago

Hi, thanks for the quick response.

Yes, you've got it right; when I don't have the polybar module/scripts running as written above, I have no issues controlling the player using playerctl.

Ipc is enabled in the bar with enable-ipc = true.

I think it may be something about the hook actions in the script itself that is part of the issue.

Troubleshooting things I've tried so far:

Beyond that, I've just restarted the computer to see if it was a WM/cache problem, but I haven't had time to do much other troubleshooting on the issue. If you have any additional ideas of other troubleshooting, I'm happy to give it a go. Hope this is clear, and let me know if you need any additional clarification.

PrayagS commented 2 years ago

Thanks for your detailed response.

I also seem to think that there's an issue with the script. Based on the test cases you shared, I suspect something is going wrong at this line,

PLAYERCTL_STATUS=$(playerctl --player=$PLAYER status 2>/dev/null)

Can you please echo out the output of this and let me know what it is? Just replace it with this block,

PLAYERCTL_STATUS=$(playerctl --player=$PLAYER status 2>/dev/null)
echo "playerctl status: $PLAYERCTL_STATUS"
EXIT_CODE=$?
echo "exit code: $EXIT_CODE"

Also, have you tried the script with some other player? I think you should try that out.

bowen-song commented 2 years ago

Finally had some time to muck around.

Seems like there is some incompatibility in the script and sublime-music specifically because spotify works but I am not sure where things are going wrong. playerctl continues to work fine with sublime-music on its own, but as soon as you call the commands with the script it doesn't work.

Here's the output from echoing output of playerctl status and exit code with sublime-music as the player:

playerctl status:
exit code: 0
No players found

I downloaded spotify as well, selected spotify as the player and here's the output for that:

playerctl status: Stopped
exit code: 0
No music is playing

I understand if this might now be outside the scope of this project, but would appreciate any continued advice troubleshooting.

PrayagS commented 2 years ago

Here's the output from echoing output of playerctl status and exit code with sublime-music as the player:

playerctl status:
exit code: 0
No players found

Weird. Try changing the playerctl call to

PLAYERCTL_STATUS=$(playerctl --player=$PLAYER)

This will let us know if playerctl is spitting out something on stderr which we were previously disposing to /dev/null.

Also, thanks for trying out the script with spotify. Just to make sure, was it actually stopped when you tested it? It shouldn't report Stopped when it was actually playing.

I'm still not sure of the exact issue so I might as well try and replicate your setup. I did look up sonic before and it wasn't as straightforward because of the different forks of sonic. Can you briefly tell me the exact packages to install and maybe a getting started guide to set up the server and the player?

bowen-song commented 2 years ago

Ah, I think I've actually figured out where the problem is with your latest suggestion.

PLAYERCTL_STATUS=$(playerctl --player=$PLAYER) just prints out the help menu for both spotify and sublime-music, but PLAYERCTL_STATUS=$(playerctl --player=$PLAYER status) prints out with different stdouts for spotify and sublime-music.

Here's where the problem is: These commands from terminal produce different results for the different music players:

  1. While spotify stopped, playerctl --player=spotify status -> Stopped
  2. While spotify stopped, playerctl status -> Stopped
  3. While sublime-music is stopped, playerctl --player=sublime-music status -> No players found (unexpected)
  4. While sublime-music is stopped, playerctl status -> Stopped as expected

I think this may actually have something to do with sublime-music and playerctl but I don't really know enough about either to say what the problem is.

I was able to get the script to work completely as expected when I removed the lines specifying the player and replaced them with generic playerctl status lines.

#!/bin/bash

# The name of polybar bar which houses the main spotify module and the control modules.
PARENT_BAR="mainbar"
PARENT_BAR_PID=$(pgrep -a "polybar" | grep "$PARENT_BAR" | cut -d" " -f1)

PLAYER="sublime-music"

FORMAT="{{ title }} - {{ artist }}"

update_hooks() {
    while IFS= read -r id
    do
        polybar-msg -p "$id" hook music-pp $2 1>/dev/null 2>&1 
    done < <(echo "$1")
}

PLAYERCTL_STATUS=$(playerctl status 2>/dev/null)
EXIT_CODE=$?

if [ $EXIT_CODE -eq 0 ]; then
    STATUS=$PLAYERCTL_STATUS
else
    STATUS="No player is running"
fi

if [ "$1" == "--status" ]; then
    echo "$STATUS"
else
    if [ "$STATUS" = "Stopped" ]; then
        echo "No music is playing"
    elif [ "$STATUS" = "Paused"  ]; then
        update_hooks "$PARENT_BAR_PID" 2
        playerctl  metadata --format "$FORMAT"
    elif [ "$STATUS" = "No player is running"  ]; then
        echo "$STATUS"
    else
        update_hooks "$PARENT_BAR_PID" 1
        playerctl metadata --format "$FORMAT"
    fi
fi

As far as my specific set up goes in case you would still like to troubleshoot the exact problem:

Server: Ubuntu 20.04 LTS, running Linuxserver's image of Airsonic on docker-compose Client: Arch linux 5.10.72-1 LTS, running the sublime-music 0.11.13-1 package from AUR, playerctl 2.4.1-1

If Airsonic and client are on the same network, there shouldn't be any need for any special network rules. Once Airsonic is spun up on docker-compose, you can just connect directly to the web interface at http://SERVER_IP:4040. To have any music to play, make sure there's something in the folders you mount to the docker container.

On the client, to use sublime-music, the button to the right of the settings will have a place for you to login to your http://SERVER_IP:4040 with whatever username and password you set.

Edit: I should also add - I believe whether someone is using one of the *sonics shouldn't matter as much as the player itself. In my case, sublime-music advertises itself as being compatible with playerctl, so it was possible to integrate with your script. Without a player capable of outputting to stdout and/or playerctl, it probably wouldn't matter whether someone was on Airsonic or Subsonic or any of its derivatives.

Let me know if you have any questions while working on this, I'm happy to help out with more details if needed!

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.