mpris added

This commit is contained in:
foglar 2025-08-23 09:27:20 +02:00
parent 4cb67f0a17
commit 426e088c43
8 changed files with 220 additions and 2 deletions

View File

@ -6,6 +6,12 @@
go run cmd/main.go
```
- Run on nix
```shell
nix run git+https://git.foglar.tech/foglar/WhspBrd.git
```
## File structure
- may be edited in accordance with [this project standard](https://github.com/golang-standards/project-layout)

40
_examples/mpris.go Normal file
View File

@ -0,0 +1,40 @@
package main
import (
"fmt"
"log"
"whspbrd/pkg/mpris"
)
func main() {
players, err := mpris.Mpris()
if err != nil {
log.Fatalf("Error: %v", err)
}
for _, p := range players {
fmt.Printf("Player: %s\n", p.Name)
fmt.Printf("Title : %s\n", p.Title)
if len(p.Artist) > 0 {
fmt.Printf("Artist: %s\n", p.Artist[0])
}
fmt.Printf("Album : %s\n", p.Album)
if p.ArtURL != "" {
if mpris.IsRemoteArt(p.ArtURL) {
fmt.Printf("Remote artwork found: %s\n", p.ArtURL)
err := mpris.DownloadArt(p.ArtURL, p.Name+"_art.jpg")
if err != nil {
fmt.Printf("Error downloading art: %v\n", err)
} else {
fmt.Printf("Artwork saved as %s_art.jpg\n", p.Name)
}
} else {
fmt.Printf("Local artwork: %s\n", p.ArtURL)
}
} else {
fmt.Println("Artwork: not available")
}
fmt.Println()
}
}

View File

@ -20,6 +20,13 @@
"receiver": "Filip",
"content": "VG8gYnljaG9tIG1vaGxpLCB2eWhvdnVqZSB0aSB0ZW5obGUgdMO9ZGVuIHZlIHN0xZllZHU/Cg==",
"timestamp": "2024-10-01T11:23:00Z"
},
{
"id": "4",
"sender": "Bob",
"receiver": "Filip",
"content": "TmVibyB2ZSDEjXR2cnRlawo=",
"timestamp": "2024-10-01T11:24:00Z"
}
]
}

65
docs/TODO.md Normal file
View File

@ -0,0 +1,65 @@
# Tasks to be done
## TUI
- [ ] Initial configuration setup
- [ ] Solve colors issue
- [ ] Complete chat loading and sending messages to contacts so it is written to the file
- [ ] Create systray
- [ ] Share what music am i listening using mpris
### Chat
- [ ] Add scrolling capability
- [ ] Solve multiline messages and resizing the window
- [ ] Implement calculating positions of images and profile pictures
- [ ] Add rendering image previews
- [ ] Render image in chat
- [ ] Render image in chat with scroll
- [ ] Add rendering profile pictures
- [ ] Solve too long message history problem - render only first 100 messages?
- [ ] Check chat without images, if kitty image protocol is not used
- [ ] Check chat on windows
- [ ] Create timestamps like today yesterday etc...
### Sidebar
- [ ] Profile pictures next to the username
- [ ] Ability to scroll through users and rerender profile images
- [ ] Colors maybe?
- [ ] Solve too long names and window width
### Input
- [ ] Add emoji internal selector
- [ ] Add button to add attachement
- [ ] Add correct parsing of input to correct chat
### Profile Sidebar
- [ ] Profile image
- [ ] Mpris integration
## CMD
- [ ] Create basic commands template to use chat from commandline
## Configuration
- [ ] Keybindings for application
- [ ] IDs instead of usernames
- [ ] Load and Write new messages to the files
- [ ] Change preloading of Contacts from list to complex structure
- [ ] Change preloading of messages from list to complex structure
- [ ] Add new contact
- [ ] Choose server to use when running TUI
- [ ] Create colorthemes
- [ ] Add reactions to messages and replies
## Server
## Communication
## IDEAS
- just set window size of the box to be even, so there should not be need in rendering half of the profile picture

2
go.mod
View File

@ -3,6 +3,8 @@ module whspbrd
go 1.24.2
require (
github.com/Endg4meZer0/go-mpris v1.0.5
github.com/godbus/dbus/v5 v5.1.0
github.com/jroimartin/gocui v0.5.0
golang.org/x/sys v0.30.0
)

5
go.sum
View File

@ -1,3 +1,8 @@
github.com/Endg4meZer0/go-mpris v1.0.5 h1:a3FUGD/h3tQAFlcl/YH4TVwtI/NVm4UJAGMEyaKai7I=
github.com/Endg4meZer0/go-mpris v1.0.5/go.mod h1:eh//AAqSR5XF4G2mAKe9NrSp5sH8G6f3RnYzbupi8tU=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/jroimartin/gocui v0.5.0 h1:DCZc97zY9dMnHXJSJLLmx9VqiEnAj0yh0eTNpuEtG/4=
github.com/jroimartin/gocui v0.5.0/go.mod h1:l7Hz8DoYoL6NoYnlnaX6XCNR62G7J5FfSW5jEogzaxE=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=

View File

@ -66,8 +66,6 @@ func (p Palette) Underlined(c Color) string { return c.Underline() } // convenie
func (p Palette) Text(c Color) string { return c.Text() }
var Colors = Palette{
// I kept the numeric values that you originally used in your map so behavior stays the same.
// If you'd rather map them to "standard" 30..37 and 90..97 codes, change the integers here.
Base00: NewColor(31),
Base01: NewColor(32),
Base02: NewColor(33),

95
pkg/mpris/mpris.go Normal file
View File

@ -0,0 +1,95 @@
package mpris
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"github.com/Endg4meZer0/go-mpris"
"github.com/godbus/dbus/v5"
)
type PlayerInfo struct {
Name string
Title string
Artist []string
Album string
ArtURL string
}
func Mpris() ([]PlayerInfo, error) {
conn, err := dbus.SessionBus()
if err != nil {
return nil, err
}
names, err := mpris.List(conn)
if err != nil {
return nil, err
}
if len(names) == 0 {
return nil, fmt.Errorf("no MPRIS players found")
}
var players []PlayerInfo
for _, name := range names {
player := mpris.New(conn, name)
metadata, err := player.GetMetadata()
if err != nil {
return nil, err
}
title, _ := metadata["xesam:title"].Value().(string)
artist, _ := metadata["xesam:artist"].Value().([]string)
album, _ := metadata["xesam:album"].Value().(string)
var artURL string
if val, ok := metadata["mpris:artUrl"]; ok {
if url, ok := val.Value().(string); ok {
artURL = url
}
}
players = append(players, PlayerInfo{
Name: name,
Title: title,
Artist: artist,
Album: album,
ArtURL: artURL,
})
}
return players, nil
}
func IsRemoteArt(uri string) bool {
return strings.HasPrefix(uri, "http://") || strings.HasPrefix(uri, "https://")
}
func DownloadArt(url, dest string) error {
resp, err := http.Get(url)
if err != nil {
return fmt.Errorf("failed to fetch art: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("bad status: %s", resp.Status)
}
out, err := os.Create(dest)
if err != nil {
return fmt.Errorf("failed to create file: %w", err)
}
defer out.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
return fmt.Errorf("failed to save art: %w", err)
}
return nil
}