di-tui/mpris/mpris.go
2025-09-23 14:50:51 -07:00

217 lines
4.9 KiB
Go

package mpris
import (
"time"
"github.com/acaloiaro/di-tui/app"
"github.com/acaloiaro/di-tui/context"
"github.com/godbus/dbus/v5"
"github.com/quarckster/go-mpris-server/pkg/server"
"github.com/quarckster/go-mpris-server/pkg/types"
)
var (
s *server.Server
statusPlaying = map[string]dbus.Variant{
"PlaybackStatus": dbus.MakeVariant(types.PlaybackStatusPlaying),
}
)
type Root struct{}
func (r Root) Raise() error {
return nil
}
func (r Root) Quit() error {
return nil
}
func (r Root) CanQuit() (bool, error) {
return false, nil
}
func (r Root) CanRaise() (bool, error) {
return false, nil
}
func (r Root) HasTrackList() (bool, error) {
return true, nil
}
func (r Root) Identity() (string, error) {
return "di-tui - di.fm player", nil
}
func (r Root) SupportedUriSchemes() ([]string, error) {
return []string{}, nil
}
func (r Root) SupportedMimeTypes() ([]string, error) {
return []string{}, nil
}
var _ types.OrgMprisMediaPlayer2Adapter = Root{}
type Player struct {
ctx *context.AppContext
metaData types.Metadata
}
func (p Player) Next() error {
return nil
}
func (p Player) Previous() error {
return nil
}
func (p Player) Pause() error {
return nil
}
func (p Player) PlayPause() error {
app.TogglePause(p.ctx)
newStatus := types.PlaybackStatusPaused
if p.ctx.IsPlaying {
newStatus = types.PlaybackStatusPlaying
}
status := map[string]dbus.Variant{
"PlaybackStatus": dbus.MakeVariant(newStatus),
}
s.Conn.Emit("/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties.PropertiesChanged", "org.mpris.MediaPlayer2.Player", status, []string{})
return nil
}
func (p Player) Stop() error {
app.Stop(p.ctx)
status := map[string]dbus.Variant{
"PlaybackStatus": dbus.MakeVariant(types.PlaybackStatusStopped),
}
s.Conn.Emit("/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties.PropertiesChanged", "org.mpris.MediaPlayer2.Player", status, []string{})
return nil
}
func (p Player) Play() error {
app.Play(p.ctx)
status := map[string]dbus.Variant{
"PlaybackStatus": dbus.MakeVariant(types.PlaybackStatusPlaying),
}
s.Conn.Emit("/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties.PropertiesChanged", "org.mpris.MediaPlayer2.Player", status, []string{})
return nil
}
func (p Player) Seek(offset types.Microseconds) error {
return nil
}
func (p Player) SetPosition(trackId string, position types.Microseconds) error {
return nil
}
func (p Player) OpenUri(uri string) error {
return nil
}
func (p Player) PlaybackStatus() (types.PlaybackStatus, error) {
return types.PlaybackStatusStopped, nil
}
func (p Player) Rate() (float64, error) {
return 1.2, nil
}
func (p Player) SetRate(float64) error {
return nil
}
func (p Player) Metadata() (types.Metadata, error) {
return p.metaData, nil
}
func (p Player) Volume() (float64, error) {
return 0, nil
}
func (p Player) SetVolume(in float64) error {
return nil
}
func (p Player) Position() (int64, error) {
return 0, nil
}
func (p Player) MinimumRate() (float64, error) {
return 0, nil
}
func (p Player) MaximumRate() (float64, error) {
return 0, nil
}
func (p Player) CanGoNext() (bool, error) {
return false, nil
}
func (p Player) CanGoPrevious() (bool, error) {
return false, nil
}
func (p Player) CanPlay() (bool, error) {
return true, nil
}
func (p Player) CanPause() (bool, error) {
return true, nil
}
func (p Player) CanSeek() (bool, error) {
return false, nil
}
func (p Player) CanControl() (bool, error) {
return true, nil
}
// Start starts the mpris server, handling play/pause events, and announces the currently playing track on an interval
func Start(ctx *context.AppContext) {
metaData := types.Metadata{
TrackId: "/TrackList/Track1",
Length: 100,
ArtUrl: "",
Album: "",
AlbumArtist: []string{},
Artist: []string{""},
AsText: "",
AudioBPM: 0,
AutoRating: 0.0,
Comment: []string{},
Composer: []string{},
ContentCreated: "",
DiscNumber: 0,
FirstUsed: "",
Genre: []string{},
LastUsed: "",
Lyricist: []string{},
Title: "",
TrackNumber: 0,
Url: "",
UseCount: 0,
UserRating: 0.0,
}
r := Root{}
p := Player{ctx: ctx, metaData: metaData}
s = server.NewServer("di-tui", r, p)
go s.Listen()
go func() {
for {
<-time.Tick(1 * time.Second)
if !p.ctx.IsPlaying {
continue
}
if s.Conn == nil {
return
}
p.metaData.Artist = []string{p.ctx.View.NowPlaying.Track.Artist}
p.metaData.Title = p.ctx.View.NowPlaying.Track.Title
props := map[string]any{
"Metadata": p.metaData.MakeMap(),
}
s.Conn.Emit("/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties.PropertiesChanged", "org.mpris.MediaPlayer2.Player", props, []string{})
s.Conn.Emit("/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties.PropertiesChanged", "org.mpris.MediaPlayer2.Player", statusPlaying, []string{})
}
}()
}