feat: switch to ebiten

This commit is contained in:
Louis Dalibard 2024-11-02 17:50:15 +01:00
parent 2b231f2155
commit 30694431e6
5 changed files with 161 additions and 92 deletions

View File

@ -8,6 +8,7 @@ import (
"path/filepath"
"xyosc/utils"
"github.com/fsnotify/fsnotify"
"github.com/kirsle/configdir"
"gopkg.in/yaml.v2"
)
@ -50,6 +51,8 @@ var AccentColor color.RGBA
var FirstColor color.RGBA
var ThirdColor color.RGBA
var watcher *fsnotify.Watcher
func Init() {
configPath := configdir.LocalConfig("ontake", "xyosc")
err := configdir.MakePath(configPath) // Ensure it exists.
@ -78,9 +81,41 @@ func Init() {
}
// Get pywal accent color
watcher, err = fsnotify.NewWatcher()
utils.CheckError(err)
updatePywalColors()
walPath := configdir.LocalCache("wal")
walFile := filepath.Join(walPath, "colors")
if _, err = os.Stat(walFile); os.IsNotExist(err) {
// Start listening for events.
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Has(fsnotify.Write) {
updatePywalColors()
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
utils.CheckError(err)
}
}
}()
if _, err := os.Stat(walFile); os.IsNotExist(err) {
} else {
err = watcher.Add(walFile)
utils.CheckError(err)
}
}
func updatePywalColors() {
walPath := configdir.LocalCache("wal")
walFile := filepath.Join(walPath, "colors")
if _, err := os.Stat(walFile); os.IsNotExist(err) {
AccentColor = color.RGBA{255, 0, 0, Config.LineOpacity}
FirstColor = color.RGBA{255, 120, 120, Config.LineOpacity}
ThirdColor = color.RGBA{255, 0, 0, Config.LineOpacity}

View File

@ -1,49 +1,21 @@
package fonts
import (
"unicode"
"os"
"xyosc/utils"
"github.com/flopp/go-findfont"
rl "github.com/gen2brain/raylib-go/raylib"
"github.com/hajimehoshi/ebiten/v2/text/v2"
)
func getAllChars(table *unicode.RangeTable) []rune {
res := make([]rune, 0)
for _, r := range table.R16 {
for c := r.Lo; c <= r.Hi; c += r.Stride {
res = append(res, rune(c))
}
}
for _, r := range table.R32 {
for c := r.Lo; c <= r.Hi; c += r.Stride {
res = append(res, rune(c))
}
}
return res
}
var FontIosevka32 rl.Font
var FontIosevka16 rl.Font
var Font *text.GoTextFaceSource
func Init() {
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
fontPath, err := findfont.Find("SourceHanSansJP-Heavy.otf")
utils.CheckError(err)
runes := make([]rune, 0)
runes = append(runes, getAllChars(unicode.Katakana)...)
runes = append(runes, getAllChars(unicode.Hiragana)...)
runes = append(runes, getAllChars(unicode.Latin)...)
runes = append(runes, getAllChars(unicode.Digit)...)
runes = append(runes, getAllChars(unicode.Punct)...)
runes = append(runes, getAllChars(unicode.Han)...)
runes = append(runes, getAllChars(unicode.Symbol)...)
FontIosevka32 = rl.LoadFontEx(fontPath, 32, runes)
rl.GenTextureMipmaps(&FontIosevka32.Texture)
rl.SetTextureFilter(FontIosevka32.Texture, rl.FilterPoint)
FontIosevka16 = rl.LoadFontEx(fontPath, 16, runes)
rl.GenTextureMipmaps(&FontIosevka16.Texture)
rl.SetTextureFilter(FontIosevka16.Texture, rl.FilterPoint)
f, err := os.Open(fontPath)
utils.CheckError(err)
Font, err = text.NewGoTextFaceSource(f)
utils.CheckError(err)
}

15
go.mod
View File

@ -4,9 +4,10 @@ go 1.23.2
require (
github.com/flopp/go-findfont v0.1.0
github.com/fsnotify/fsnotify v1.8.0
github.com/gen2brain/malgo v0.11.22
github.com/gen2brain/raylib-go/raylib v0.0.0-20241019150900-b7833eeae8d0
github.com/godbus/dbus v4.1.0+incompatible
github.com/hajimehoshi/ebiten/v2 v2.8.3
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f
github.com/leberKleber/go-mpris v1.1.0
github.com/smallnest/ringbuffer v0.0.0-20240827114233-62e3c686e6c0
@ -15,8 +16,14 @@ require (
)
require (
github.com/ebitengine/purego v0.7.1 // indirect
github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325 // indirect
github.com/ebitengine/hideconsole v1.0.0 // indirect
github.com/ebitengine/purego v0.8.0 // indirect
github.com/go-text/typesetting v0.2.0 // indirect
github.com/godbus/dbus/v5 v5.0.6 // indirect
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
golang.org/x/sys v0.20.0 // indirect
github.com/jezek/xgb v1.1.1 // indirect
golang.org/x/image v0.20.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
)

36
go.sum
View File

@ -1,17 +1,31 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA=
github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325 h1:Gk1XUEttOk0/hb6Tq3WkmutWa0ZLhNn/6fc6XZpM7tM=
github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325/go.mod h1:ulhSQcbPioQrallSuIzF8l1NKQoD7xmMZc5NxzibUMY=
github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE=
github.com/ebitengine/hideconsole v1.0.0/go.mod h1:hTTBTvVYWKBuxPr7peweneWdkUwEuHuB3C1R/ielR1A=
github.com/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE=
github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/flopp/go-findfont v0.1.0 h1:lPn0BymDUtJo+ZkV01VS3661HL6F4qFlkhcJN55u6mU=
github.com/flopp/go-findfont v0.1.0/go.mod h1:wKKxRDjD024Rh7VMwoU90i6ikQRCr+JTHB5n4Ejkqvw=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gen2brain/malgo v0.11.22 h1:fRtTbzVI9CDWnfEJGo/GxKxN7pXtCb0NsAeUVUjZk9U=
github.com/gen2brain/malgo v0.11.22/go.mod h1:f9TtuN7DVrXMiV/yIceMeWpvanyVzJQMlBecJFVMxww=
github.com/gen2brain/raylib-go/raylib v0.0.0-20241019150900-b7833eeae8d0 h1:ssHgKQvc9AIHFSlpkfHr89lJU8nzGBdpKoQJBTPkvnQ=
github.com/gen2brain/raylib-go/raylib v0.0.0-20241019150900-b7833eeae8d0/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q=
github.com/go-text/typesetting v0.2.0 h1:fbzsgbmk04KiWtE+c3ZD4W2nmCRzBqrqQOvYlwAOdho=
github.com/go-text/typesetting v0.2.0/go.mod h1:2+owI/sxa73XA581LAzVuEBZ3WEEV2pXeDswCH/3i1I=
github.com/go-text/typesetting-utils v0.0.0-20240317173224-1986cbe96c66 h1:GUrm65PQPlhFSKjLPGOZNPNxLCybjzjYBzjfoBGaDUY=
github.com/go-text/typesetting-utils v0.0.0-20240317173224-1986cbe96c66/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/hajimehoshi/bitmapfont/v3 v3.2.0 h1:0DISQM/rseKIJhdF29AkhvdzIULqNIIlXAGWit4ez1Q=
github.com/hajimehoshi/bitmapfont/v3 v3.2.0/go.mod h1:8gLqGatKVu0pwcNCJguW3Igg9WQqVXF0zg/RvrGQWyg=
github.com/hajimehoshi/ebiten/v2 v2.8.3 h1:AKHqj3QbQMzNEhK33MMJeRwXm9UzftrUUo6AWwFV258=
github.com/hajimehoshi/ebiten/v2 v2.8.3/go.mod h1:SXx/whkvpfsavGo6lvZykprerakl+8Uo1X8d2U5aAnA=
github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4=
github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f h1:dKccXx7xA56UNqOcFIbuqFjAWPVtP688j5QMgmo6OHU=
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f/go.mod h1:4rEELDSfUAlBSyUjPG0JnaNGjf13JySHFeRdD/3dLP0=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -20,6 +34,8 @@ github.com/leberKleber/go-mpris v1.1.0 h1:bHAnmUjVoxAs4uMHH9lfQ8bOm284UWtI7JhLvk
github.com/leberKleber/go-mpris v1.1.0/go.mod h1:OwKywFZwFGC0p/8xBUTUXMIFZy0Rq/7C6EayfeASTA0=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/smallnest/ringbuffer v0.0.0-20240827114233-62e3c686e6c0 h1:6wTlHUWggWb8Y5Q4f7xnIBHa3L7DgijNQP8eM6oTEhQ=
@ -28,10 +44,14 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/ztrue/tracerr v0.4.0 h1:vT5PFxwIGs7rCg9ZgJ/y0NmOpJkPCPFK8x0vVIYzd04=
github.com/ztrue/tracerr v0.4.0/go.mod h1:PaFfYlas0DfmXNpo7Eay4MFhZUONqvXM+T2HyGPpngk=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

123
main.go
View File

@ -2,63 +2,98 @@ package main
import (
"encoding/binary"
"log"
"xyosc/audio"
"xyosc/config"
"xyosc/fonts"
"xyosc/media"
rl "github.com/gen2brain/raylib-go/raylib"
"fmt"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/hajimehoshi/ebiten/v2/text/v2"
"github.com/hajimehoshi/ebiten/v2/vector"
)
func main() {
config.Init()
audio.Init()
go audio.Start()
go media.Start()
type Game struct {
}
func (g *Game) Update() error {
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
scale := min(config.Config.WindowWidth, config.Config.WindowHeight) / 2
rl.InitWindow(config.Config.WindowWidth, config.Config.WindowHeight, "xyosc")
defer rl.CloseWindow()
rl.SetWindowOpacity(config.Config.WindowOpacity)
rl.SetConfigFlags(rl.FlagWindowTransparent)
rl.SetConfigFlags(rl.FlagMsaa4xHint)
rl.SetWindowState(rl.FlagWindowUndecorated)
rl.SetTargetFPS(config.Config.TargetFPS)
rl.SetWindowPosition(rl.GetMonitorWidth(rl.GetCurrentMonitor())/2, rl.GetMonitorHeight(rl.GetCurrentMonitor())/2)
var AX float32
var AY float32
var BX float32
var BY float32
fonts.Init()
for !rl.WindowShouldClose() {
rl.BeginDrawing()
rl.ClearBackground(rl.Blank)
binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &AX)
binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &AY)
for i := uint32(0); i < config.Config.ReadBufferSize/audio.SampleSizeInBytes/2; i++ {
binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &BX)
binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &BY)
fAX := float32(AX) * config.Config.Gain * float32(scale)
fAY := -float32(AY) * config.Config.Gain * float32(scale)
fBX := float32(BX) * config.Config.Gain * float32(scale)
fBY := -float32(BY) * config.Config.Gain * float32(scale)
//inv := fastsqrt.FastInvSqrt32((fBX-fAX)*(fBX-fAX) + (fBY-fBY)*(fBY-fBY))
//colorAdjusted := color.RGBA{config.AccentColor.R, config.AccentColor.G, config.AccentColor.B, uint8(255 * inv * config.Config.LineOpacity)}
rl.DrawLineEx(rl.NewVector2(float32(config.Config.WindowWidth/2)+fAX, float32(config.Config.WindowWidth/2)+fAY), rl.NewVector2(float32(config.Config.WindowWidth/2)+fBX, float32(config.Config.WindowWidth/2)+fBY), config.Config.LineThickness, config.AccentColor)
AX = BX
AY = BY
}
//audio.SampleRingBuffer.Reset()
if config.Config.FPSCounter {
rl.DrawFPS(16, config.Config.WindowHeight-32)
}
rl.DrawTextEx(fonts.FontIosevka32, media.PlayingMediaInfo.Artist+" - "+media.PlayingMediaInfo.Title, rl.NewVector2(16, 16), 32, 2, config.AccentColor)
rl.DrawTextEx(fonts.FontIosevka16, media.PlayingMediaInfo.Album, rl.NewVector2(16, 48), 16, 1, config.ThirdColor)
rl.DrawTextEx(fonts.FontIosevka32, media.FmtDuration(media.PlayingMediaInfo.Position)+" / "+media.FmtDuration(media.PlayingMediaInfo.Duration), rl.NewVector2(16, 64), 32, 2, config.AccentColor)
rl.EndDrawing()
binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &AX)
binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &AY)
for i := uint32(0); i < config.Config.ReadBufferSize/audio.SampleSizeInBytes/2; i++ {
binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &BX)
binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &BY)
fAX := float32(AX) * config.Config.Gain * float32(scale)
fAY := -float32(AY) * config.Config.Gain * float32(scale)
fBX := float32(BX) * config.Config.Gain * float32(scale)
fBY := -float32(BY) * config.Config.Gain * float32(scale)
//inv := fastsqrt.FastInvSqrt32((fBX-fAX)*(fBX-fAX) + (fBY-fBY)*(fBY-fBY))
//colorAdjusted := color.RGBA{config.AccentColor.R, config.AccentColor.G, config.AccentColor.B, uint8(255 * inv * config.Config.LineOpacity)}
vector.StrokeLine(screen, float32(config.Config.WindowWidth/2)+fAX, float32(config.Config.WindowWidth/2)+fAY, float32(config.Config.WindowWidth/2)+fBX, float32(config.Config.WindowWidth/2)+fBY, config.Config.LineThickness, config.AccentColor, true)
AX = BX
AY = BY
}
//audio.SampleRingBuffer.Reset()
if config.Config.FPSCounter {
ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f", ebiten.ActualTPS()))
}
rl.CloseWindow()
if config.Config.ShowMPRIS {
op := &text.DrawOptions{}
op.GeoM.Translate(16, 16)
op.ColorScale.ScaleWithColor(config.AccentColor)
text.Draw(screen, media.PlayingMediaInfo.Artist+" - "+media.PlayingMediaInfo.Title, &text.GoTextFace{
Source: fonts.Font,
Size: 32,
}, op)
op = &text.DrawOptions{}
op.GeoM.Translate(16, 64)
op.ColorScale.ScaleWithColor(config.ThirdColor)
text.Draw(screen, media.PlayingMediaInfo.Album, &text.GoTextFace{
Source: fonts.Font,
Size: 16,
}, op)
op = &text.DrawOptions{}
op.GeoM.Translate(16, 80)
op.ColorScale.ScaleWithColor(config.AccentColor)
text.Draw(screen, media.FmtDuration(media.PlayingMediaInfo.Position)+" / "+media.FmtDuration(media.PlayingMediaInfo.Duration), &text.GoTextFace{
Source: fonts.Font,
Size: 32,
}, op)
}
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return int(config.Config.WindowWidth), int(config.Config.WindowHeight)
}
func main() {
config.Init()
audio.Init()
fonts.Init()
go audio.Start()
go media.Start()
ebiten.SetWindowSize(int(config.Config.WindowWidth), int(config.Config.WindowHeight))
ebiten.SetWindowTitle("xyosc")
ebiten.SetTPS(int(config.Config.TargetFPS))
ebiten.SetWindowDecorated(false)
screenW, screenH := ebiten.Monitor().Size()
ebiten.SetWindowPosition(screenW/2-int(config.Config.WindowWidth)/2, screenH/2-int(config.Config.WindowHeight)/2)
ebiten.SetVsyncEnabled(true)
if err := ebiten.RunGame(&Game{}); err != nil {
log.Fatal(err)
}
}