aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--main.go67
2 files changed, 41 insertions, 29 deletions
diff --git a/README.md b/README.md
index b617c52..455931e 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ When running, the program will pipe out json in waybar's format. Add something l
```
"custom/waybar-mpris": {
"return-type": "json",
- "exec": "waybar-mpris --position --autofocus",
+ "exec": "waybar-mpris --autofocus --text-format=\"%i [%p/%d] %a - %t\"",
"on-click": "waybar-mpris --send toggle",
// This option will switch between players on right click.
"on-click-right": "waybar-mpris --send player-next",
@@ -82,7 +82,6 @@ Usage of ./waybar-mpris:
apply.
* `--play/--pause` specify the symbols or text to display when music is paused/playing respectively.
* `--autofocus` makes waybar-mpris automatically focus on currently playing music players.
-* `--position` enables the display of the track position.
* `--interpolate` increments the track position every second. This is useful for players (e.g mpDris2) that don't regularly update the position.
* `--max-title` the maximum number of characters before the title cuts off.
* `--replace`: By default, new instances will attach to the existing one so that the output is identical. This lets this instance replace any others running. It isn't recommended.
diff --git a/main.go b/main.go
index 7597155..10be005 100644
--- a/main.go
+++ b/main.go
@@ -24,7 +24,7 @@ const (
LOGFILE = "/tmp/waybar-mpris.log"
OUTFILE = "/tmp/waybar-mpris.out" // Used for sharing waybar output when args are the same.
DATAFILE = "/tmp/waybar-mpris.data.out" // Used for sharing "\n"-separated player data between instances when args are different.
- POLL = 1
+ POLL = 900
)
// Mostly default values for flag options.
@@ -36,12 +36,11 @@ var (
autofocus = false
// Available commands that can be sent to running instances.
commands = []string{"player-next", "player-prev", "next", "prev", "toggle", "list"}
- showPos = false
interpolate = false
replace = false
isSharing = false
isDataSharing = false
- maxTitleLen = 70
+ maxTitleLen = 50
writer io.Writer = os.Stdout
shareWriter, dataWriter io.Writer
)
@@ -55,7 +54,6 @@ const (
tokPosition = 'p'
tokLength = 'd'
tokPlayer = 'P'
- tokPercent = '%'
)
const (
@@ -169,7 +167,9 @@ func secondsToString(seconds int) string {
return fmt.Sprintf("%02d:%02d", minutes, seconds)
}
-func formatOutput(p *player, icon string, fstr string) string {
+// Function to format the output as requested by the user preferences of icon,
+// format specifier string and maximum title length
+func formatOutput(p *player, icon string, fstr string, maxTitleLen int) string {
var buf []byte
for i := 0; i < len(fstr); i++ {
if fstr[i] == '%' {
@@ -181,17 +181,31 @@ func formatOutput(p *player, icon string, fstr string) string {
case tokIcon:
buf = append(buf, []byte(icon)...)
case tokArtist:
- buf = append(buf, []byte(p.Artist)...)
+ artist := strings.ReplaceAll(p.Artist, "&", "&amp;")
+ buf = append(buf, []byte(artist)...)
case tokAlbum:
- buf = append(buf, []byte(p.Album)...)
+ album := strings.ReplaceAll(p.Album, "&", "&amp;")
+ buf = append(buf, []byte(album)...)
case tokTitle:
title := p.Title
- if maxTitleLen > 0 && len(title) > maxTitleLen {
- title = title[:maxTitleLen-3] + "..."
+ if maxTitleLen > 0 && len([]rune(title)) > maxTitleLen {
+ // Probably not the most effective thing to do, but this way
+ // we don't slice the string in the middle of a UTF-8
+ // character it happens to be more than 1 byte, and the
+ // maximum length actually correlates to the displayed
+ // charaacters instead of the bytes.
+ title = string([]rune(title)[:maxTitleLen-3]) + "..."
}
+ title = strings.ReplaceAll(title, "&", "&amp;")
buf = append(buf, []byte(title)...)
case tokPosition:
- position := secondsToString(int(p.Position / 1000000))
+ var position string
+ if p.Length > 0 {
+ p.GetPosition()
+ position = secondsToString(int(p.Position / 1000000))
+ } else {
+ position = secondsToString(0)
+ }
buf = append(buf, []byte(position)...)
case tokLength:
length := secondsToString(p.Length)
@@ -206,10 +220,7 @@ func formatOutput(p *player, icon string, fstr string) string {
}
}
- out := strings.ReplaceAll(string(buf), `"`, `\"`)
- out = strings.ReplaceAll(out, "&", "&amp;")
-
- return out
+ return string(buf)
}
// Returns JSON for waybar to consume.
@@ -224,8 +235,10 @@ func playerJSON(p *player) string {
data.Class = "paused"
}
- data.Text = formatOutput(p, icon, textFormat)
- data.Tooltip = formatOutput(p, icon, tooltipFormat)
+ data.Text = formatOutput(p, icon, textFormat, maxTitleLen)
+ // There's no point in limiting the length of the output/title in the
+ // tooltip, so we set it to 0
+ data.Tooltip = formatOutput(p, icon, tooltipFormat, 0)
out, err := json.Marshal(data)
if err != nil {
@@ -277,7 +290,7 @@ func execCommand(cmd string) {
func duplicateOutput() error {
// Print to stderr to avoid errors from waybar
- os.Stderr.WriteString("waybar-mpris is already running. This instance will clone its output.")
+ os.Stderr.WriteString("waybar-mpris is already running. This instance will clone its output.\n")
conn, err := net.Dial("unix", SOCK)
if err != nil {
@@ -613,6 +626,8 @@ func main() {
os.Remove(SOCK)
os.Remove(OUTFILE)
}
+ } else {
+ fmt.Fprintf(os.Stderr, "error: %v\n", err)
}
conn, err := dbus.SessionBus()
if err != nil {
@@ -626,18 +641,16 @@ func main() {
lastLine := ""
go listenForCommands(players)
go players.mpris2.Listen()
- if showPos {
- go func() {
- for {
- time.Sleep(POLL * time.Second)
- if len(players.mpris2.List) != 0 {
- if players.mpris2.List[players.mpris2.Current].Playing {
- go fmt.Fprintln(writer, players.JSON())
- }
+ go func() {
+ for {
+ time.Sleep(POLL * time.Millisecond)
+ if len(players.mpris2.List) != 0 {
+ if players.mpris2.List[players.mpris2.Current].Playing {
+ go fmt.Fprintln(writer, players.JSON())
}
}
- }()
- }
+ }
+ }()
fmt.Fprintln(writer, players.JSON())
for v := range players.mpris2.Messages {
if v.Name == "refresh" {