You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.4 KiB

package main
import (
"fmt"
"io"
"strings"
"time"
dbus "github.com/guelfey/go.dbus"
)
type SpotifyPlaybackInfo struct {
Time time.Duration
Duration time.Duration
Artist string
Title string
Album string
IsPlaying bool
}
type SpotifyClient interface {
io.Closer
GetPlaybackInfo() (SpotifyPlaybackInfo, error)
}
func newSpotify() (SpotifyClient, error) {
conn, err := dbus.SessionBus()
if err != nil {
return nil, fmt.Errorf("Failed to connect to session bus: %w", err)
}
busObject := conn.Object("org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2")
return &spotifyDBusInterface{
Conn: conn,
BusObject: busObject,
}, nil
}
type spotifyDBusInterface struct {
Conn *dbus.Conn
BusObject *dbus.Object
}
func (sdi *spotifyDBusInterface) GetPlaybackInfo() (SpotifyPlaybackInfo, error) {
var spi SpotifyPlaybackInfo
positionProp, err := sdi.BusObject.GetProperty("org.mpris.MediaPlayer2.Player.Position")
if err != nil {
return spi, fmt.Errorf("could not retrieve playback position status: %w", err)
}
if value, ok := positionProp.Value().(int64); ok {
spi.Time = time.Duration(value) / time.Nanosecond
}
playbackStatusProp, err := sdi.BusObject.GetProperty("org.mpris.MediaPlayer2.Player.PlaybackStatus")
if err != nil {
return spi, fmt.Errorf("could not retrieve playback status: %w", err)
}
if value, ok := playbackStatusProp.Value().(string); ok && value == "Playing" {
spi.IsPlaying = true
}
metadataProp, err := sdi.BusObject.GetProperty("org.mpris.MediaPlayer2.Player.Metadata")
if err != nil {
return spi, fmt.Errorf("could not retrieve metadata: %w", err)
}
if metadata, ok := metadataProp.Value().(map[string]dbus.Variant); ok {
if v := getProperty("xesam:title", metadata); v != nil {
spi.Title = v.(string)
}
if v := getProperty("xesam:album", metadata); v != nil {
spi.Album = v.(string)
}
if v := getProperty("xesam:albumArtist", metadata); v != nil {
spi.Artist = strings.Join(v.([]string), ", ")
}
if spi.Album == spi.Title {
spi.Album = ""
}
if v := getProperty("mpris:length", metadata); v != nil {
spi.Duration = time.Duration(v.(uint64)) / time.Nanosecond
}
}
return spi, nil
}
func (sdi *spotifyDBusInterface) Close() error {
return sdi.Conn.Close()
}
func getProperty(key string, metadata map[string]dbus.Variant) interface{} {
if v, ok := metadata[key]; ok {
return v.Value()
}
return nil
}