Skip to content
Open
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
164 changes: 145 additions & 19 deletions config/bspwm/bin/MediaControl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/sh
# =============================================================
# Author: gh0stzk
# Colaborator: Maxcrazy1
# Repo: https://github.com/gh0stzk/dotfiles
# Date: 24.04.2025
# Info: This script uses playerctl and mpc to control the multimedia playback
Expand All @@ -9,7 +10,94 @@
# =============================================================

# Set the player
[ -n "$(pgrep spotify)" ] && Control="spotify" || Control="MPD"
# [ -n "$(pgrep spotify)" ] && Control="spotify" || Control="MPD"

LAST_PLAYER_FILE="/tmp/last_player"

get_active_player() {
# Prefer the last known player if it's currently playing
if [ -f "$LAST_PLAYER_FILE" ]; then
lp=$(cat "$LAST_PLAYER_FILE" 2>/dev/null || echo "")
if [ -n "$lp" ]; then
if [ "$lp" = "MPD" ]; then
if command -v mpc >/dev/null 2>&1; then
mpd_status=$(mpc status 2>/dev/null | sed -En '2s/.*\[([^]]*)\].*/\1/p')
if [ "$mpd_status" = "playing" ] || [ "$mpd_status" = "Playing" ]; then
echo "MPD"
return
fi
fi
else
status=$(playerctl --player="$lp" status 2>/dev/null)
if [ "$status" = "Playing" ]; then
echo "$lp"
return
fi
fi
fi
fi

# Prefer MPD if mpc reports it's playing (mpc/MPD is not an MPRIS player)
if command -v mpc >/dev/null 2>&1; then
mpd_status=$(mpc status 2>/dev/null || echo "")
if printf "%s" "$mpd_status" | grep -qi "playing"; then
echo "MPD"
return
fi
fi

playerctl -l 2>/dev/null | while read -r player; do
status=$(playerctl --player="$player" status 2>/dev/null)
[ "$status" = "Playing" ] && echo "$player" && exit
done
}

get_last_player() {
# Return the last player only if it is currently available via playerctl
if [ -f "$LAST_PLAYER_FILE" ]; then
lp=$(cat "$LAST_PLAYER_FILE" 2>/dev/null || echo "")
if [ -n "$lp" ]; then
# If last player was MPD, accept it when mpc reports a current song
if [ "$lp" = "MPD" ]; then
if command -v mpc >/dev/null 2>&1; then
mpd_current=$(mpc current 2>/dev/null || echo "")
if [ -n "$mpd_current" ]; then
printf "%s" "$lp"
return 0
fi
fi
fi
# playerctl -l lists available players; accept exact match
if playerctl -l 2>/dev/null | grep -xq "$lp"; then
printf "%s" "$lp"
return 0
fi
fi
fi
return 1
}

save_last_player() {
echo "$Control" > "$LAST_PLAYER_FILE"
}

Control=$(get_active_player)

if [ -z "$Control" ]; then
Control=$(get_last_player)
fi

if [ -z "$Control" ]; then
# Prefer any active MPRIS players reported by playerctl; if none, fall back to MPD.
# Historically scripts defaulted to Spotify even when closed; avoid that by
# checking playerctl and only selecting spotify if it's actually present.
first_player=$(playerctl -l 2>/dev/null | head -n1)
if [ -n "$first_player" ]; then
Control="$first_player"
else
Control="MPD"
fi
fi

# Here the cover image will be saved.
Cover=/tmp/cover.png
Expand All @@ -18,18 +106,44 @@ bkpCover=~/.config/bspwm/config/assets/fallback.webp
# mpd music directory for mpd clients.
mpddir=~/Music
LAST_SONG_FILE="/tmp/last_song.txt"
NOTIFY_REPLACE_ID=424242
NOTIFY_EXPIRE_MS=8000




case $Control in
MPD)
case $1 in
--next)
mpc -q next
mpc -q next
# After advancing, ensure MPD is saved as the last player
save_last_player
# Delegate MPD notification to centralized helper
"$HOME/.local/bin/notify_song" --force --player MPD >/dev/null 2>&1 &
sh -c "sleep 0.2; \"$HOME/.local/bin/notify_song\" --force --player MPD >/dev/null 2>&1" &
;;
--previous)
mpc -q prev
# After stepping previous, ensure MPD is saved as the last player
save_last_player
"$HOME/.local/bin/notify_song" --force --player MPD >/dev/null 2>&1 &
sh -c "sleep 0.2; \"$HOME/.local/bin/notify_song\" --force --player MPD >/dev/null 2>&1" &
;;
--toggle)
mpc -q toggle
# small delay to let mpc state update, then notify if playing
sleep 0.08
mpd_status=$(mpc status | sed -En '2s/.*\[([^]]*)\].*/\1/p')
if [ "$mpd_status" = "playing" ] || [ "$mpd_status" = "Playing" ]; then
# Save MPD as last player so subsequent play commands target it
save_last_player
"$HOME/.local/bin/notify_song" --force --player MPD >/dev/null 2>&1 &
elif [ "$mpd_status" = "paused" ] || [ "$mpd_status" = "Paused" ]; then
# Remember MPD even when paused to resume it later
save_last_player
fi
;;
--stop)
mpc -q stop
Expand Down Expand Up @@ -94,12 +208,37 @@ case $Control in
case $1 in
--next)
playerctl --player="$Control" next
# Ensure notification comes from centralized helper (overwrite player's own notif)
/config/bspwm/bin/notify_song --force >/dev/null 2>&1 &
# second delayed call to overwrite any late native player notification
sh -c "sleep 0.2; /config/bspwm/bin/notify_song --force >/dev/null 2>&1" &
;;
--previous)
playerctl --player="$Control" previous
/config/bspwm/bin/notify_song --force >/dev/null 2>&1 &
sh -c "sleep 0.2; /config/bspwm/bin/notify_song --force >/dev/null 2>&1" &
;;
--toggle)
playerctl --player="$Control" play-pause
if playerctl --player="$Control" status >/dev/null 2>&1; then
playerctl --player="$Control" play-pause

sleep 0.1
status=$(playerctl --player="$Control" status)

# Si se pausó, recordarlo
if [ "$status" = "Paused" ]; then
save_last_player
fi

# Si se reanudó, notificar
if [ "$status" = "Playing" ]; then
save_last_player
# Force notify to bypass throttling when metadata lags (YouTube Music)
/config/bspwm/bin/notify_song --force || true
fi
else
mpc -q toggle
fi
;;
--stop)
playerctl --player="$Control" stop
Expand All @@ -120,23 +259,9 @@ case $Control in
echo "$Control"
;;
--cover)
current_song="$(playerctl --player="$Control" metadata --format '{{title}}-{{artist}}')"
last_song=""
[ -f "$LAST_SONG_FILE" ] && last_song=$(cat "$LAST_SONG_FILE")

if [ "$current_song" != "$last_song" ] || [ ! -f "$Cover" ]; then
albumart="$(playerctl --player="$Control" metadata mpris:artUrl | sed -e 's/open.spotify.com/i.scdn.co/g')"
art_url=$(playerctl --player="$Control" metadata mpris:artUrl)
if [ -n "$art_url" ]; then
albumart=$(echo "$art_url" | sed -e 's/open.spotify.com/i.scdn.co/g')
curl -s "$albumart" --output "$Cover"
else
cp "$bkpCover" "$Cover"
fi
echo "$current_song" > "$LAST_SONG_FILE"
fi

echo "$Cover"
# Force notify to update/download cover even if throttling would suppress notification
/config/bspwm/bin/notify_song --force || true
echo "$Cover"
;;
--position)
position=$(playerctl --player="$Control" position --format "{{ duration(position) }}")
Expand Down Expand Up @@ -164,3 +289,4 @@ case $Control in
;;
esac
esac 2>/dev/null

Loading