mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-11-09 20:44:03 -08:00
feat: spotify segment for windows
This commit is contained in:
parent
2844eed0f5
commit
96cac5f689
|
@ -25,6 +25,7 @@ indent_size = 2
|
||||||
; Markdown - match markdownlint settings
|
; Markdown - match markdownlint settings
|
||||||
[*.{md,markdown}]
|
[*.{md,markdown}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
; PowerShell - match defaults for New-ModuleManifest and PSScriptAnalyzer Invoke-Formatter
|
; PowerShell - match defaults for New-ModuleManifest and PSScriptAnalyzer Invoke-Formatter
|
||||||
[*.{ps1,psd1,psm1}]
|
[*.{ps1,psd1,psm1}]
|
||||||
|
|
|
@ -6,8 +6,8 @@ sidebar_label: Spotify
|
||||||
|
|
||||||
## What
|
## What
|
||||||
|
|
||||||
Show the currently playing song in the Spotify MacOS client. Only available on MacOS for obvious reasons.
|
Show the currently playing song in the Spotify MacOS/Windows client.
|
||||||
Be aware this can make the prompt a tad bit slower as it needs to get a response from the Spotify player using Applescript.
|
Be aware this can make the prompt a tad bit slower as it needs to get a response from the Spotify player.
|
||||||
|
|
||||||
## Sample Configuration
|
## Sample Configuration
|
||||||
|
|
||||||
|
@ -20,8 +20,10 @@ Be aware this can make the prompt a tad bit slower as it needs to get a response
|
||||||
"background": "#1BD760",
|
"background": "#1BD760",
|
||||||
"properties": {
|
"properties": {
|
||||||
"prefix": " ",
|
"prefix": " ",
|
||||||
|
"playing_icon": " ",
|
||||||
"paused_icon": " ",
|
"paused_icon": " ",
|
||||||
"playing_icon": " "
|
"stopped_icon": " ",
|
||||||
|
"track_separator" : " - "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -30,4 +32,5 @@ Be aware this can make the prompt a tad bit slower as it needs to get a response
|
||||||
|
|
||||||
- playing_icon: `string` - text/icon to show when playing - defaults to `\uE602 `
|
- playing_icon: `string` - text/icon to show when playing - defaults to `\uE602 `
|
||||||
- paused_icon: `string` - text/icon to show when paused - defaults to `\uF8E3 `
|
- paused_icon: `string` - text/icon to show when paused - defaults to `\uF8E3 `
|
||||||
|
- stopped_icon: `string` - text/icon to show when paused - defaults to `\uF04D `
|
||||||
- track_separator: `string` - text/icon to put between the artist and song name - defaults to ` - `
|
- track_separator: `string` - text/icon to put between the artist and song name - defaults to ` - `
|
||||||
|
|
|
@ -36,6 +36,7 @@ type environmentInfo interface {
|
||||||
getArgs() *args
|
getArgs() *args
|
||||||
getBatteryInfo() (*battery.Battery, error)
|
getBatteryInfo() (*battery.Battery, error)
|
||||||
getShellName() string
|
getShellName() string
|
||||||
|
getWindowTitle(imageName string, windowTitleRegex string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type environment struct {
|
type environment struct {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,3 +14,7 @@ func (env *environment) isRunningAsRoot() bool {
|
||||||
func (env *environment) homeDir() string {
|
func (env *environment) homeDir() string {
|
||||||
return os.Getenv("HOME")
|
return os.Getenv("HOME")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *environment) getWindowTitle(imageName string, windowTitleRegex string) (string, error) {
|
||||||
|
return "", errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -45,3 +47,7 @@ func (env *environment) homeDir() string {
|
||||||
}
|
}
|
||||||
return home
|
return home
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *environment) getWindowTitle(imageName string, windowTitleRegex string) (string, error) {
|
||||||
|
return getWindowTitle(imageName, windowTitleRegex)
|
||||||
|
}
|
||||||
|
|
174
environment_windows_win32.go
Normal file
174
environment_windows_win32.go
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WindowsProcess is an implementation of Process for Windows.
|
||||||
|
type WindowsProcess struct {
|
||||||
|
pid int
|
||||||
|
ppid int
|
||||||
|
exe string
|
||||||
|
}
|
||||||
|
|
||||||
|
// getImagePid returns the
|
||||||
|
func getImagePid(imageName string) ([]int, error) {
|
||||||
|
processes, err := processes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var pids []int
|
||||||
|
for i := 0; i < len(processes); i++ {
|
||||||
|
if strings.ToLower(processes[i].exe) == imageName {
|
||||||
|
pids = append(pids, processes[i].pid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pids, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getWindowTitle returns the title of a window linked to a process name
|
||||||
|
func getWindowTitle(imageName string, windowTitleRegex string) (string, error) {
|
||||||
|
processPid, err := getImagePid(imageName)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
// returns the first window of the first pid
|
||||||
|
_, windowTitle, err := GetWindowTitle(processPid[0], windowTitleRegex)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
return windowTitle, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newWindowsProcess(e *windows.ProcessEntry32) *WindowsProcess {
|
||||||
|
// Find when the string ends for decoding
|
||||||
|
end := 0
|
||||||
|
for {
|
||||||
|
if e.ExeFile[end] == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
end++
|
||||||
|
}
|
||||||
|
|
||||||
|
return &WindowsProcess{
|
||||||
|
pid: int(e.ProcessID),
|
||||||
|
ppid: int(e.ParentProcessID),
|
||||||
|
exe: syscall.UTF16ToString(e.ExeFile[:end]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processes returns a snapshot of all the processes
|
||||||
|
// Taken and adapted from https://github.com/mitchellh/go-ps
|
||||||
|
func processes() ([]WindowsProcess, error) {
|
||||||
|
// get process table snapshot
|
||||||
|
handle, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, syscall.GetLastError()
|
||||||
|
}
|
||||||
|
defer windows.CloseHandle(handle)
|
||||||
|
|
||||||
|
// get process infor by looping through the snapshot
|
||||||
|
var entry windows.ProcessEntry32
|
||||||
|
entry.Size = uint32(unsafe.Sizeof(entry))
|
||||||
|
err = windows.Process32First(handle, &entry)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error retrieving process info")
|
||||||
|
}
|
||||||
|
|
||||||
|
results := make([]WindowsProcess, 0, 50)
|
||||||
|
for {
|
||||||
|
results = append(results, *newWindowsProcess(&entry))
|
||||||
|
err := windows.Process32Next(handle, &entry)
|
||||||
|
if err != nil {
|
||||||
|
if err == syscall.ERROR_NO_MORE_FILES {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("Fail to syscall Process32Next: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// win32 specific code
|
||||||
|
|
||||||
|
// win32 dll load and function definitions
|
||||||
|
var (
|
||||||
|
user32 = syscall.NewLazyDLL("user32.dll")
|
||||||
|
procEnumWindows = user32.NewProc("EnumWindows")
|
||||||
|
procGetWindowTextW = user32.NewProc("GetWindowTextW")
|
||||||
|
procGetWindowThreadProcessID = user32.NewProc("GetWindowThreadProcessId")
|
||||||
|
)
|
||||||
|
|
||||||
|
// EnumWindows call EnumWindows from user32 and returns all active windows
|
||||||
|
func EnumWindows(enumFunc uintptr, lparam uintptr) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall(procEnumWindows.Addr(), 2, uintptr(enumFunc), uintptr(lparam), 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = error(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWindowText returns the title and text of a window from a window handle
|
||||||
|
func GetWindowText(hwnd syscall.Handle, str *uint16, maxCount int32) (len int32, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall(procGetWindowTextW.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(str)), uintptr(maxCount))
|
||||||
|
len = int32(r0)
|
||||||
|
if len == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = error(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWindowTitle searchs for a window attached to the pid
|
||||||
|
func GetWindowTitle(pid int, windowTitleRegex string) (syscall.Handle, string, error) {
|
||||||
|
var hwnd syscall.Handle
|
||||||
|
var title string
|
||||||
|
compiledRegex, err := regexp.Compile(windowTitleRegex)
|
||||||
|
if err != nil {
|
||||||
|
return 0, "", fmt.Errorf("Error while compiling the regex '%s'", windowTitleRegex)
|
||||||
|
}
|
||||||
|
// callback fro EnumWindows
|
||||||
|
cb := syscall.NewCallback(func(h syscall.Handle, p uintptr) uintptr {
|
||||||
|
var prcsID int = 0
|
||||||
|
// get pid
|
||||||
|
_, _, _ = procGetWindowThreadProcessID.Call(uintptr(h), uintptr(unsafe.Pointer(&prcsID)))
|
||||||
|
// check if pid matches spotify pid
|
||||||
|
if prcsID == pid {
|
||||||
|
b := make([]uint16, 200)
|
||||||
|
_, err := GetWindowText(h, &b[0], int32(len(b)))
|
||||||
|
if err != nil {
|
||||||
|
// ignore the error
|
||||||
|
return 1 // continue enumeration
|
||||||
|
}
|
||||||
|
title = syscall.UTF16ToString(b)
|
||||||
|
if compiledRegex.MatchString(title) {
|
||||||
|
hwnd = h
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1 // continue enumeration
|
||||||
|
})
|
||||||
|
// Enumerates all top-level windows on the screen
|
||||||
|
EnumWindows(cb, 0)
|
||||||
|
if hwnd == 0 {
|
||||||
|
return 0, "", fmt.Errorf("No window with title '%b' found", pid)
|
||||||
|
}
|
||||||
|
return hwnd, title, nil
|
||||||
|
}
|
|
@ -108,6 +108,11 @@ func (env *MockedEnvironment) getShellName() string {
|
||||||
return args.String(0)
|
return args.String(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *MockedEnvironment) getWindowTitle(imageName string, windowTitleRegex string) (string, error) {
|
||||||
|
args := env.Called(imageName)
|
||||||
|
return args.String(0), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
func TestIsInHomeDirTrue(t *testing.T) {
|
func TestIsInHomeDirTrue(t *testing.T) {
|
||||||
home := "/home/bill"
|
home := "/home/bill"
|
||||||
env := new(MockedEnvironment)
|
env := new(MockedEnvironment)
|
||||||
|
|
|
@ -17,35 +17,19 @@ const (
|
||||||
PlayingIcon Property = "playing_icon"
|
PlayingIcon Property = "playing_icon"
|
||||||
//PausedIcon indicates a song is paused
|
//PausedIcon indicates a song is paused
|
||||||
PausedIcon Property = "paused_icon"
|
PausedIcon Property = "paused_icon"
|
||||||
|
//StoppedIcon indicates a song is stopped
|
||||||
|
StoppedIcon Property = "stopped_icon"
|
||||||
//TrackSeparator is put between the artist and the track
|
//TrackSeparator is put between the artist and the track
|
||||||
TrackSeparator Property = "track_separator"
|
TrackSeparator Property = "track_separator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *spotify) enabled() bool {
|
|
||||||
if s.env.getRuntimeGOOS() != "darwin" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
// Check if running
|
|
||||||
running := s.runAppleScriptCommand("application \"Spotify\" is running")
|
|
||||||
if running == "false" || running == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
s.status = s.runAppleScriptCommand("tell application \"Spotify\" to player state as string")
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.status == "stopped" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
s.artist = s.runAppleScriptCommand("tell application \"Spotify\" to artist of current track as string")
|
|
||||||
s.track = s.runAppleScriptCommand("tell application \"Spotify\" to name of current track as string")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *spotify) string() string {
|
func (s *spotify) string() string {
|
||||||
icon := ""
|
icon := ""
|
||||||
switch s.status {
|
switch s.status {
|
||||||
|
case "stopped":
|
||||||
|
// in this case, no artist or track info
|
||||||
|
icon = s.props.getString(StoppedIcon, "\uF04D ")
|
||||||
|
return icon
|
||||||
case "paused":
|
case "paused":
|
||||||
icon = s.props.getString(PausedIcon, "\uF8E3 ")
|
icon = s.props.getString(PausedIcon, "\uF8E3 ")
|
||||||
case "playing":
|
case "playing":
|
||||||
|
@ -59,8 +43,3 @@ func (s *spotify) init(props *properties, env environmentInfo) {
|
||||||
s.props = props
|
s.props = props
|
||||||
s.env = env
|
s.env = env
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *spotify) runAppleScriptCommand(command string) string {
|
|
||||||
val, _ := s.env.runCommand("osascript", "-e", command)
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
27
segment_spotify_darwin.go
Normal file
27
segment_spotify_darwin.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func (s *spotify) enabled() bool {
|
||||||
|
var err error
|
||||||
|
// Check if running
|
||||||
|
running := s.runAppleScriptCommand("application \"Spotify\" is running")
|
||||||
|
if running == "false" || running == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s.status = s.runAppleScriptCommand("tell application \"Spotify\" to player state as string")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s.status == "stopped" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s.artist = s.runAppleScriptCommand("tell application \"Spotify\" to artist of current track as string")
|
||||||
|
s.track = s.runAppleScriptCommand("tell application \"Spotify\" to name of current track as string")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *spotify) runAppleScriptCommand(command string) string {
|
||||||
|
val, _ := s.env.runCommand("osascript", "-e", command)
|
||||||
|
return val
|
||||||
|
}
|
63
segment_spotify_darwin_test.go
Normal file
63
segment_spotify_darwin_test.go
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type spotifyArgs struct {
|
||||||
|
spotifyDarwinTitle string
|
||||||
|
spotifyDarwinRunning string
|
||||||
|
spotifyDarwinStatus string
|
||||||
|
spotifyDarwinArtist string
|
||||||
|
spotifyDarwinTrack string
|
||||||
|
}
|
||||||
|
|
||||||
|
func bootStrapSpotifyDarwinTest(args *spotifyArgs) *spotify {
|
||||||
|
env := new(MockedEnvironment)
|
||||||
|
env.On("runCommand", "osascript", []string{"-e", "application \"Spotify\" is running"}).Return(args.spotifyDarwinRunning, nil)
|
||||||
|
env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to player state as string"}).Return(args.spotifyDarwinStatus, nil)
|
||||||
|
env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to artist of current track as string"}).Return(args.spotifyDarwinArtist, nil)
|
||||||
|
env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to name of current track as string"}).Return(args.spotifyDarwinTrack, nil)
|
||||||
|
props := &properties{}
|
||||||
|
s := &spotify{
|
||||||
|
env: env,
|
||||||
|
props: props,
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpotifyDarwinEnabledAndSpotifyNotRunning(t *testing.T) {
|
||||||
|
args := &spotifyArgs{
|
||||||
|
spotifyDarwinRunning: "false",
|
||||||
|
}
|
||||||
|
s := bootStrapSpotifyDarwinTest(args)
|
||||||
|
assert.Equal(t, false, s.enabled())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpotifyDarwinEnabledAndSpotifyPlaying(t *testing.T) {
|
||||||
|
args := &spotifyArgs{
|
||||||
|
spotifyDarwinRunning: "true",
|
||||||
|
spotifyDarwinStatus: "playing",
|
||||||
|
spotifyDarwinArtist: "Candlemass",
|
||||||
|
spotifyDarwinTrack: "Spellbreaker",
|
||||||
|
}
|
||||||
|
s := bootStrapSpotifyDarwinTest(args)
|
||||||
|
assert.Equal(t, true, s.enabled())
|
||||||
|
assert.Equal(t, "\ue602 Candlemass - Spellbreaker", s.string())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpotifyDarwinEnabledAndSpotifyPaused(t *testing.T) {
|
||||||
|
args := &spotifyArgs{
|
||||||
|
spotifyDarwinRunning: "true",
|
||||||
|
spotifyDarwinStatus: "paused",
|
||||||
|
spotifyDarwinArtist: "Candlemass",
|
||||||
|
spotifyDarwinTrack: "Spellbreaker",
|
||||||
|
}
|
||||||
|
s := bootStrapSpotifyDarwinTest(args)
|
||||||
|
assert.Equal(t, true, s.enabled())
|
||||||
|
assert.Equal(t, "\uF8E3 Candlemass - Spellbreaker", s.string())
|
||||||
|
}
|
8
segment_spotify_others.go
Normal file
8
segment_spotify_others.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// +build !darwin
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func (s *spotify) enabled() bool {
|
||||||
|
return false
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -6,6 +8,32 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSpotifyEnabled(t *testing.T) {
|
func TestSpotifyStringPlayingSong(t *testing.T) {
|
||||||
assert.True(t, true)
|
expected := "\ue602 Candlemass - Spellbreaker"
|
||||||
|
s := &spotify{
|
||||||
|
artist: "Candlemass",
|
||||||
|
track: "Spellbreaker",
|
||||||
|
status: "playing",
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, s.string())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpotifyStringPausedSong(t *testing.T) {
|
||||||
|
expected := "\uF8E3 Candlemass - Spellbreaker"
|
||||||
|
s := &spotify{
|
||||||
|
artist: "Candlemass",
|
||||||
|
track: "Spellbreaker",
|
||||||
|
status: "paused",
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, s.string())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpotifyStringStoppedSong(t *testing.T) {
|
||||||
|
expected := "\uf04d "
|
||||||
|
s := &spotify{
|
||||||
|
artist: "Candlemass",
|
||||||
|
track: "Spellbreaker",
|
||||||
|
status: "stopped",
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, s.string())
|
||||||
}
|
}
|
||||||
|
|
28
segment_spotify_windows.go
Normal file
28
segment_spotify_windows.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *spotify) enabled() bool {
|
||||||
|
// search for spotify window to retrieve the title
|
||||||
|
// Can be either "Spotify xxx" or the song name "Candlemass - Spellbreaker"
|
||||||
|
spotifyWindowTitle, err := s.env.getWindowTitle("spotify.exe", "^(Spotify.*)|(.*\\s-\\s.*)$")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(spotifyWindowTitle, " - ") {
|
||||||
|
s.status = "stopped"
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
infos := strings.Split(spotifyWindowTitle, " - ")
|
||||||
|
s.artist = infos[0]
|
||||||
|
// remove first element and concat others(a song can contains also a " - ")
|
||||||
|
s.track = strings.Join(infos[1:], " - ")
|
||||||
|
s.status = "playing"
|
||||||
|
return true
|
||||||
|
}
|
52
segment_spotify_windows_test.go
Normal file
52
segment_spotify_windows_test.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type spotifyArgs struct {
|
||||||
|
spotifyWindowsTitle string
|
||||||
|
spotifyNotRunningError error
|
||||||
|
}
|
||||||
|
|
||||||
|
func bootStrapSpotifyWindowsTest(args *spotifyArgs) *spotify {
|
||||||
|
env := new(MockedEnvironment)
|
||||||
|
env.On("getWindowTitle", "spotify.exe").Return(args.spotifyWindowsTitle, args.spotifyNotRunningError)
|
||||||
|
props := &properties{}
|
||||||
|
s := &spotify{
|
||||||
|
env: env,
|
||||||
|
props: props,
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpotifyWindowsEnabledAndSpotifyNotRunning(t *testing.T) {
|
||||||
|
args := &spotifyArgs{
|
||||||
|
spotifyNotRunningError: errors.New(""),
|
||||||
|
}
|
||||||
|
s := bootStrapSpotifyWindowsTest(args)
|
||||||
|
assert.Equal(t, false, s.enabled())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpotifyWindowsEnabledAndSpotifyPlaying(t *testing.T) {
|
||||||
|
args := &spotifyArgs{
|
||||||
|
spotifyWindowsTitle: "Candlemass - Spellbreaker",
|
||||||
|
}
|
||||||
|
s := bootStrapSpotifyWindowsTest(args)
|
||||||
|
assert.Equal(t, true, s.enabled())
|
||||||
|
assert.Equal(t, "\ue602 Candlemass - Spellbreaker", s.string())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpotifyWindowsEnabledAndSpotifyStopped(t *testing.T) {
|
||||||
|
args := &spotifyArgs{
|
||||||
|
spotifyWindowsTitle: "Spotify premium",
|
||||||
|
}
|
||||||
|
s := bootStrapSpotifyWindowsTest(args)
|
||||||
|
assert.Equal(t, true, s.enabled())
|
||||||
|
assert.Equal(t, "\uf04d ", s.string())
|
||||||
|
}
|
Loading…
Reference in a new issue