-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplayer.go
132 lines (112 loc) · 4.12 KB
/
player.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main
import (
"fmt"
"github.com/godbus/dbus/v5"
)
// item that represents a dbus BusObject for a mediaplayer
type player struct {
dbus.BusObject
name string
}
// activeInfo The struct for containing information about the current
// player Much easier than invoking the methods at runtime and MUCH
// better than passing around 90 strings
type activeInfo struct {
fullName string // the FullName of the activeplayer - basically just the structs name field
identity string // the identity of the active player
desktopEntry string // the desktopEntry for the active player - basically a nicer formatted identity
playbackStatus string // The PlaybackStatus of the active player, formatted using the symbols
trackTitle string // The title of the current playing track, if no metadata is found it's just the link
}
// String String representation of the info
func (a *activeInfo) String() string {
return fmt.Sprintf("%s\x1f%s\x1f%s\x1f%s", a.fullName, a.desktopEntry, a.playbackStatus, a.trackTitle)
}
// Clear - Clear the activeInfo's fields (used for when activeplayer is nil for example)
// Kinda gross but don't want to make new instances because trying to keep this low memory
func (a *activeInfo) Clear() {
a.fullName, a.identity = "", ""
a.desktopEntry, a.playbackStatus = "", ""
a.trackTitle = ""
}
// PlayPause toggle between playing and pausing
func (p *player) PlayPause() *dbus.Error {
if p == nil {
return nil
}
p.Call("org.mpris.MediaPlayer2.Player.PlayPause", 0)
return nil
}
// GetPlayerInfo get the player info and assign it to a given activeInfo object
// Don't really need to check the errors as like they only indicate
// something wasn't found which isn't a big problem
func (player *player) GetPlayerInfo(info *activeInfo) (err error) {
info.fullName = player.name
info.trackTitle, err = player.getPlayerTrack()
info.playbackStatus, err = player.getPlaybackStatus()
info.desktopEntry, err = player.getPlayerDesktopEntry()
info.identity, err = player.getPlayerIdentity()
return
}
// getPlayerTrack Take in a busobject and return its currently playing track and it's playback status
func (player *player) getPlayerTrack() (string, error) {
prop, err := player.GetProperty("org.mpris.MediaPlayer2.Player.Metadata")
if err != nil {
return "", fmt.Errorf("Failed to get property: %v", err)
}
v, ok := prop.Value().(map[string]dbus.Variant)
if ok {
if val, ok := v["xesam:title"]; ok {
return val.Value().(string), nil // should be fine with the unsafe cast
}
if val, ok := v["xesam:url"]; ok {
return val.Value().(string), nil // it's probably always a string - cbf checking :P
}
return "", fmt.Errorf("Media missing track title")
}
return "", fmt.Errorf("Metadata not found")
}
// getPlaybackStatus get the current playback status for the player object
// the string value will be based on the constants
func (player *player) getPlaybackStatus() (string, error) {
prop, err := player.GetProperty("org.mpris.MediaPlayer2.Player.PlaybackStatus")
if err != nil {
return "", fmt.Errorf("Failed to get property: %v", err)
}
status, ok := prop.Value().(string)
if ok {
switch status {
case "Playing":
return PlaySymbol, nil
case "Paused":
return PauseSymbol, nil
case "Stopped":
return StopSymbol, nil
}
}
return "", fmt.Errorf("Failed to match playback status with value %v", status)
}
// getPlayerIdentity Get the identity for the given player
func (player *player) getPlayerIdentity() (string, error) {
prop, err := player.GetProperty("org.mpris.MediaPlayer2.Identity")
if err != nil {
return "", fmt.Errorf("Failed to get identity: %v", err)
}
identity, ok := prop.Value().(string)
if ok {
return identity, nil
}
return "", fmt.Errorf("Failed to find identity")
}
// getPlayerDesktopEntry Get this players desktop entry
func (player *player) getPlayerDesktopEntry() (string, error) {
prop, err := player.GetProperty("org.mpris.MediaPlayer2.DesktopEntry")
if err != nil {
return "", fmt.Errorf("Failed to get desktopEntry: %v", err)
}
identity, ok := prop.Value().(string)
if ok {
return identity, nil
}
return "", fmt.Errorf("Failed to find DesktopEntry")
}