hathoris/inputs/mpris/input.go

152 lines
2.8 KiB
Go

package mpris
import (
"fmt"
"log"
"strings"
"git.nemunai.re/nemunaire/hathoris/inputs"
"github.com/godbus/dbus/v5"
"github.com/leberKleber/go-mpris"
)
type MPRISClient struct {
Id string
Name string
Path string
}
var KNOWN_CLIENTS = []MPRISClient{
MPRISClient{"shairport", "ShairportSync", "org.mpris.MediaPlayer2.ShairportSync."},
MPRISClient{"firefox", "Firefox", "org.mpris.MediaPlayer2.firefox."},
}
type MPRISInput struct {
player *mpris.Player
Name string
Path string
}
var dbusConn *dbus.Conn
func init() {
var err error
dbusConn, err = dbus.ConnectSessionBus()
if err != nil {
dbusConn, err = dbus.ConnectSystemBus()
if err != nil {
log.Println("Unable to connect to DBus. MPRIS will be unavailable:", err.Error())
return
}
}
var s []string
err = dbusConn.BusObject().Call("org.freedesktop.DBus.ListNames", 0).Store(&s)
if err != nil {
log.Println("DBus unavailable:", err.Error())
return
}
log.Println("Available DBus entries:", strings.Join(s, ","))
for _, ss := range s {
for _, c := range KNOWN_CLIENTS {
if strings.HasPrefix(ss, c.Path) {
inputs.SoundInputs[c.Id] = &MPRISInput{
Name: c.Name,
Path: c.Path,
}
}
}
}
}
func (i *MPRISInput) getPlayer() (*mpris.Player, error) {
if i.player == nil {
var s []string
err := dbusConn.BusObject().Call("org.freedesktop.DBus.ListNames", 0).Store(&s)
if err != nil {
return nil, err
}
for _, ss := range s {
if strings.HasPrefix(ss, i.Path) {
player := mpris.NewPlayerWithConnection(ss, dbusConn)
if err != nil {
return nil, err
}
i.player = &player
break
}
}
if i.player == nil {
return nil, fmt.Errorf("Unable to find such dBus entry")
}
}
return i.player, nil
}
func (i *MPRISInput) GetName() string {
return i.Name
}
func (i *MPRISInput) IsActive() bool {
p, err := i.getPlayer()
if err != nil || p == nil {
log.Println(err)
return false
}
_, err = p.Metadata()
return err == nil
}
func (i *MPRISInput) CurrentlyPlaying() map[string]string {
p, err := i.getPlayer()
if err != nil || p == nil {
log.Println(err)
return nil
}
meta, err := p.Metadata()
if err != nil {
log.Println(err)
return nil
}
var infos []string
if artists, err := meta.XESAMArtist(); err == nil {
for _, artist := range artists {
if artist != "" {
infos = append(infos, artist)
}
}
}
if title, err := meta.XESAMTitle(); err == nil && title != "" {
infos = append(infos, title)
}
ret := strings.Join(infos, " - ")
return map[string]string{
"default": ret,
}
}
func (i *MPRISInput) TogglePause(id string) error {
p, err := i.getPlayer()
if err != nil {
return err
}
if ok, err := p.CanPause(); err != nil {
return err
} else if !ok {
return fmt.Errorf("The player doesn't support pause")
}
p.Pause()
return nil
}