A Go port of Playerctl for controlling MPRIS-compatible media players over D-Bus.
Status: Go-complete baseline. Core CLI, daemon, and library are implemented in Go.
You can download pre-compiled binaries for your platform from the GitHub Releases page.
Alternatively, you can install from source using go install:
go install github.com/arran4/go-playerctl/cmd/goplayerctl@latestgo test ./...
goplayerctl --version
goplayerctl daemon --versiongoplayerctl [flags] <command>-p, --playercomma-separated instance list (for examplevlc,spotify)-i, --ignore-playercomma-separated instance ignore list-a, --all-playersrun query/action for all discovered players-l, --list-allprint discovered player instances-f, --formatoutput format using Go template syntax-F, --followpoll and print changes for query commands--follow-intervalpolling period for--follow--tui-schemeTUI control scheme (arrow, vim, winamp, emacs)--versionprint CLI version string
playpauseplay-pause/playpausenextpreviousstatusmetadataformat [string]albumartisttitletrackloop [None|Track|Playlist]shuffle [On|Off|Toggle]volume [level]position [offset]rate [level]open <uri>playlisttracklist
# list players
goplayerctl --list-all
# query status for one player
goplayerctl --player vlc status
# query metadata for all players with formatted output
goplayerctl --all-players --format '{{ .player }}: {{ default .title "(none)" }}' metadata
# query metadata for a player showing artist, album, and title
goplayerctl --player spotify --format '{{ default .artist "Unknown Artist" }} - {{ default .album "Unknown Album" }} - {{ default .title "Unknown Title" }}' metadata
# follow status changes
goplayerctl --player spotify --follow status
# print active playlist details via template
goplayerctl --format 'Active Playlist: {{ .activePlaylistName }} ({{ .playlistCount }} total)' metadata
# print out all tracks in the tracklist
goplayerctl --format '{{ range .tracklist }}{{ .title }} by {{ .artist }}{{ "\n" }}{{ end }}' metadata
# print out all available playlists
goplayerctl --format '{{ range .playlists }}Playlist: {{ .name }}{{ "\n" }}{{ end }}' metadatago run ./cmd/goplayerctl tui [flags]goplayerctl daemon [flags]--oncerefresh and print discovered players once, then exit--refresh-intervalrefresh interval for daemon loop--versionprint daemon version string
When not in --once mode, daemon attempts to export:
- Bus name:
org.mpris.MediaPlayer2.playerctld - Object path:
/org/mpris/MediaPlayer2 - Interface:
com.github.altdesktop.playerctld
Methods/properties currently exposed by the Go port:
- methods:
Shift,Unshift - signals emitted:
ActivePlayerChangeBegin,ActivePlayerChangeEnd - properties/accessors:
PlayerNames,ActivePlayer
If you want to observe asynchronous D-Bus events for a specific player connection (like TrackAdded or Seeked or NameOwnerChanged), you can consume signals using the exported .Events() channel on the Player struct:
events := p.Events()
for sig := range events {
fmt.Printf("Received signal: %s from %s\n", sig.Name, sig.Sender)
}The package provides:
- enums and parsers (
PlaybackStatus,LoopStatus,Source) - typed errors (
ErrPlayerNotFound,InvalidCommandError,FormatError) Playerwith MPRIS property getters/commands/metadata helpersPlayerManagerfor discovery/filtering/ordering helpersFormatterbacked by Gotext/template
package main
import (
"fmt"
"log"
"github.com/arran4/go-playerctl/pkg/playerctl"
)
func main() {
p, err := playerctl.NewPlayer("vlc", playerctl.SourceDBusSession)
if err != nil {
log.Fatal(err)
}
defer p.Close()
status, err := p.PlaybackStatus()
if err != nil {
log.Fatal(err)
}
fmt.Println(status)
}Formatter uses Go text/template and supports helper functions:
lc,ucdefaultdurationmarkup_escapeemojitruncadd,subhas_playlisthas_tracklist
Example:
goplayerctl --player spotify --format '{{ emoji .status }} {{ default .title "(none)" }}' status
# Only show playlist if it exists
goplayerctl --format '{{ if has_playlist .playlistCount }}Active: {{ .activePlaylistName }}{{ else }}No playlist{{ end }}' metadata
# Print current playback rate
goplayerctl --format 'Rate: {{ .rate }}x' metadata
# Conditionally list tracks only if a tracklist is populated
goplayerctl --format '{{ if has_tracklist .trackCount }}Tracks:\n{{ range .tracklist }}{{ .title }}\n{{ end }}{{ end }}' metadata- API Reference: pkg.go.dev/github.com/arran4/go-playerctl
- Man page source:
doc/playerctl-go.1.md
go test ./...
go test -race ./...