2024-10-20 22:58:09 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
2024-11-02 23:44:33 +01:00
|
|
|
"image"
|
|
|
|
"image/color"
|
2024-11-02 17:50:15 +01:00
|
|
|
"log"
|
2024-10-20 22:58:09 +02:00
|
|
|
"xyosc/audio"
|
|
|
|
"xyosc/config"
|
2024-11-02 23:44:33 +01:00
|
|
|
"xyosc/fastsqrt"
|
2024-10-21 01:30:26 +02:00
|
|
|
"xyosc/fonts"
|
2024-11-02 23:44:33 +01:00
|
|
|
"xyosc/icons"
|
2024-10-21 00:44:44 +02:00
|
|
|
"xyosc/media"
|
2024-10-20 22:58:09 +02:00
|
|
|
|
2024-11-02 17:50:15 +01:00
|
|
|
"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"
|
2024-10-20 22:58:09 +02:00
|
|
|
)
|
|
|
|
|
2024-11-02 17:50:15 +01:00
|
|
|
type Game struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Game) Update() error {
|
|
|
|
return nil
|
|
|
|
}
|
2024-10-20 22:58:09 +02:00
|
|
|
|
2024-11-02 17:50:15 +01:00
|
|
|
func (g *Game) Draw(screen *ebiten.Image) {
|
2024-10-20 22:58:09 +02:00
|
|
|
scale := min(config.Config.WindowWidth, config.Config.WindowHeight) / 2
|
|
|
|
var AX float32
|
|
|
|
var AY float32
|
|
|
|
var BX float32
|
|
|
|
var BY float32
|
2024-11-02 17:50:15 +01:00
|
|
|
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)
|
2024-11-02 23:44:33 +01:00
|
|
|
if config.Config.LineInvSqrtOpacityControl {
|
|
|
|
|
|
|
|
inv := fastsqrt.FastInvSqrt32((fBX-fAX)*(fBX-fAX) + (fBY-fBY)*(fBY-fBY))
|
2024-11-02 23:58:30 +01:00
|
|
|
colorAdjusted := color.RGBA{config.ThirdColor.R, config.ThirdColor.G, config.ThirdColor.B, uint8(float32(config.Config.LineOpacity) * inv)}
|
2024-11-02 23:44:33 +01:00
|
|
|
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, colorAdjusted, true)
|
|
|
|
} else {
|
2024-11-02 23:58:30 +01:00
|
|
|
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.ThirdColorAdj, true)
|
2024-11-02 23:44:33 +01:00
|
|
|
|
|
|
|
}
|
2024-11-02 17:50:15 +01:00
|
|
|
AX = BX
|
|
|
|
AY = BY
|
|
|
|
}
|
|
|
|
//audio.SampleRingBuffer.Reset()
|
|
|
|
if config.Config.FPSCounter {
|
|
|
|
ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f", ebiten.ActualTPS()))
|
|
|
|
}
|
2024-10-21 01:30:26 +02:00
|
|
|
|
2024-11-02 17:50:15 +01:00
|
|
|
if config.Config.ShowMPRIS {
|
|
|
|
op := &text.DrawOptions{}
|
|
|
|
op.GeoM.Translate(16, 16)
|
2024-11-02 23:58:30 +01:00
|
|
|
op.ColorScale.ScaleWithColor(color.RGBA{config.AccentColor.R, config.AccentColor.G, config.AccentColor.B, config.Config.MPRISTextOpacity})
|
2024-11-02 17:50:15 +01:00
|
|
|
text.Draw(screen, media.PlayingMediaInfo.Artist+" - "+media.PlayingMediaInfo.Title, &text.GoTextFace{
|
|
|
|
Source: fonts.Font,
|
|
|
|
Size: 32,
|
|
|
|
}, op)
|
2024-10-20 22:58:09 +02:00
|
|
|
|
2024-11-02 17:50:15 +01:00
|
|
|
op = &text.DrawOptions{}
|
|
|
|
op.GeoM.Translate(16, 64)
|
2024-11-02 23:58:30 +01:00
|
|
|
op.ColorScale.ScaleWithColor(color.RGBA{config.ThirdColor.R, config.ThirdColor.G, config.ThirdColor.B, config.Config.MPRISTextOpacity})
|
|
|
|
|
2024-11-02 17:50:15 +01:00
|
|
|
text.Draw(screen, media.PlayingMediaInfo.Album, &text.GoTextFace{
|
|
|
|
Source: fonts.Font,
|
|
|
|
Size: 16,
|
|
|
|
}, op)
|
|
|
|
|
|
|
|
op = &text.DrawOptions{}
|
|
|
|
op.GeoM.Translate(16, 80)
|
2024-11-02 23:58:30 +01:00
|
|
|
op.ColorScale.ScaleWithColor(color.RGBA{config.AccentColor.R, config.AccentColor.G, config.AccentColor.B, config.Config.MPRISTextOpacity})
|
|
|
|
|
2024-11-02 17:50:15 +01:00
|
|
|
text.Draw(screen, media.FmtDuration(media.PlayingMediaInfo.Position)+" / "+media.FmtDuration(media.PlayingMediaInfo.Duration), &text.GoTextFace{
|
|
|
|
Source: fonts.Font,
|
|
|
|
Size: 32,
|
|
|
|
}, op)
|
2024-10-20 22:58:09 +02:00
|
|
|
}
|
2024-11-02 17:50:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
|
|
|
return int(config.Config.WindowWidth), int(config.Config.WindowHeight)
|
|
|
|
}
|
2024-10-20 22:58:09 +02:00
|
|
|
|
2024-11-02 17:50:15 +01:00
|
|
|
func main() {
|
|
|
|
config.Init()
|
|
|
|
audio.Init()
|
|
|
|
fonts.Init()
|
2024-11-02 23:44:33 +01:00
|
|
|
icons.Init()
|
2024-11-02 17:50:15 +01:00
|
|
|
go audio.Start()
|
|
|
|
go media.Start()
|
2024-11-02 23:44:33 +01:00
|
|
|
ebiten.SetWindowIcon([]image.Image{icons.WindowIcon48, icons.WindowIcon32, icons.WindowIcon16})
|
2024-11-02 17:50:15 +01:00
|
|
|
ebiten.SetWindowSize(int(config.Config.WindowWidth), int(config.Config.WindowHeight))
|
|
|
|
ebiten.SetWindowTitle("xyosc")
|
2024-11-02 23:44:33 +01:00
|
|
|
ebiten.SetWindowMousePassthrough(true)
|
2024-11-02 17:50:15 +01:00
|
|
|
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)
|
|
|
|
}
|
2024-10-20 22:58:09 +02:00
|
|
|
}
|