1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00
2019-07-15 09:06:49 -07:00

200 lines
5.4 KiB
Go

package spotigopher
import (
"errors"
"log"
"os/exec"
"runtime"
"strconv"
"strings"
"github.com/godbus/dbus"
)
type SpotifyClient struct {
}
/*
Info holds all available Information we get over the dbus
*/
type Info struct {
Artist []string
Title string
Album string
Rating string
TrackID string
TrackNumber int32
URL string
ArtworkURL string
Status string
}
var sdbus dbus.Object
/*
NewClient returns an Instance of Spotify Cleint
*/
func NewClient() SpotifyClient {
client := SpotifyClient{}
return client
}
func getSpotifyBus() dbus.BusObject {
con, err := dbus.SessionBus()
if err != nil {
log.Fatalf("Could not get SessionBus: %v", err)
}
//TODO: Test what happens when Spotify is Closed!
spotifyBus := con.Object("org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2")
return spotifyBus
}
/*
PlayPause sends a PlayPause Command on the DBus
*/
func (s *SpotifyClient) PlayPause() {
if runtime.GOOS == "darwin" {
sendDarwinAction("playpause")
} else {
sendAction("org.mpris.MediaPlayer2.Player.PlayPause")
}
}
/*
Next sends a Next Command on the DBus
*/
func (s *SpotifyClient) Next() {
if runtime.GOOS == "darwin" {
sendDarwinAction("next")
} else {
sendAction("org.mpris.MediaPlayer2.Player.Next")
}
}
/*
Previous sends a Previous Command on the DBus
*/
func (s *SpotifyClient) Previous() {
if runtime.GOOS == "darwin" {
sendDarwinAction("previous")
} else {
sendAction("org.mpris.MediaPlayer2.Player.Previous")
}
}
/*
Stop sends a Stop Command on the DBus
*/
func (s *SpotifyClient) Stop() {
if runtime.GOOS == "darwin" {
sendDarwinAction("stop")
} else {
sendAction("org.mpris.MediaPlayer2.Player.Stop")
}
}
/*
GetInfo returns all Spotify related Information, when Spotify is running
*/
func (s *SpotifyClient) GetInfo() (Info, error) {
info := Info{}
if runtime.GOOS == "linux" {
spotifyBus := getSpotifyBus()
props, err := spotifyBus.GetProperty("org.mpris.MediaPlayer2.Player.Metadata")
if err != nil {
return Info{}, errors.New("Could not get any Info from Spotify. Are you sure Spotify is running?")
}
songData := props.Value().(map[string]dbus.Variant)
info.TrackID = songData["mpris:trackid"].Value().(string)
info.Artist = songData["xesam:artist"].Value().([]string)
info.Title = songData["xesam:title"].Value().(string)
info.Album = songData["xesam:album"].Value().(string)
info.TrackNumber = songData["xesam:trackNumber"].Value().(int32)
info.URL = songData["xesam:url"].Value().(string)
info.ArtworkURL = songData["mpris:artUrl"].Value().(string)
status, err := spotifyBus.GetProperty("org.mpris.MediaPlayer2.Player.PlaybackStatus")
if err != nil {
log.Fatalf("Could not get Playback Status : %v", err)
}
info.Status = status.Value().(string)
} else if runtime.GOOS == "darwin" {
info.TrackID = getDarwinInfo("trackid")
info.Artist = strings.Split(getDarwinInfo("artist"), ",")
info.Album = getDarwinInfo("album")
info.Title = getDarwinInfo("track")
tmpTrackNumber, err := strconv.ParseInt(getDarwinInfo("tracknumber"), 0, 32)
if err != nil {
log.Fatalf("Could not get track number: %s", err)
}
info.TrackNumber = int32(tmpTrackNumber)
info.URL = getDarwinInfo("url")
info.ArtworkURL = getDarwinInfo("artworkurl")
info.Status = getDarwinInfo("status")
}
return info, nil
}
func getDarwinInfo(infoType string) string {
args := []string{`-etell application "Spotify" to name of current track as string`}
switch infoType {
case "trackid":
args = []string{`-etell application "Spotify" to id of current track as string`}
case "artist":
args = []string{`-etell application "Spotify" to artist of current track as string`}
case "title":
args = []string{`-etell application "Spotify" to name of current track as string`}
case "album":
args = []string{`-etell application "Spotify" to album of current track as string`}
case "tracknumber":
args = []string{`-etell application "Spotify" to track number of current track as string`}
case "url":
args = []string{`-etell application "Spotify" to spotify url of current track as string`}
case "artworkurl":
args = []string{`-etell application "Spotify" to artwork url of current track as string`}
case "status":
args = []string{`-etell application "Spotify" to player state as string`}
default:
args = []string{`-etell application "Spotify" to name of current track as string`}
}
info, err := exec.Command("osascript", args...).Output()
if err != nil {
log.Fatalf("Could not get info: %s", infoType)
}
return strings.Trim(string(info), "\n")
}
func sendDarwinAction(action string) {
args := []string{`-etell application "Spotify" to pause`}
switch action {
case "play":
args = []string{`-etell application "Spotify" to play`}
case "pause":
args = []string{`-etell application "Spotify" to pause`}
case "stop":
args = []string{`-etell application "Spotify" to pause`}
case "playpause":
args = []string{`-etell application "Spotify" to playpause`}
case "next":
args = []string{`-etell application "Spotify" to next track`}
case "previous":
args = []string{`-etell application "Spotify" to previous track`}
default:
args = []string{`-etell application "Spotify" to pause`}
}
err := exec.Command("osascript", args...).Run()
if err != nil {
log.Fatalf("Could not completed action: %s", action)
}
}
func sendAction(method string) error {
sdbus := getSpotifyBus()
call := sdbus.Call(method, 0)
return call.Err
}