diff options
author | xengineering <me@xengineering.eu> | 2024-10-03 18:16:08 +0200 |
---|---|---|
committer | xengineering <me@xengineering.eu> | 2024-10-06 20:13:28 +0200 |
commit | a1d91fcba108a59c440f0675dd5106422cf3ff7e (patch) | |
tree | f40aea2e6cda586da1a294b1200b55f2424c199d | |
parent | bb34d5f69ca4ad66754dd9833b9d7efee41ba4f2 (diff) | |
download | soundbox-app-a1d91fcba108a59c440f0675dd5106422cf3ff7e.tar soundbox-app-a1d91fcba108a59c440f0675dd5106422cf3ff7e.tar.zst soundbox-app-a1d91fcba108a59c440f0675dd5106422cf3ff7e.zip |
Switch from local playback to soundbox streaming
This commit replaces the local playback of the received audio content by
forwarding it to one or multiple soundbox devices.
For this purpose the soundbox-go[1] library is used.
The target devices cannot be selected via the GUI. Thus all devices are
specified in the ~/.config/soundbox/config.json file. The format has to
be looked up based on the code. Further documentation will follow.
[1]: https://xengineering.eu/git/soundbox-go
-rw-r--r-- | config.go | 47 | ||||
-rw-r--r-- | go.mod | 5 | ||||
-rw-r--r-- | go.sum | 6 | ||||
-rw-r--r-- | main.go | 34 |
4 files changed, 80 insertions, 12 deletions
diff --git a/config.go b/config.go new file mode 100644 index 0000000..5bdd48c --- /dev/null +++ b/config.go @@ -0,0 +1,47 @@ +package main + +import ( + "encoding/json" + "io" + "os" + "path/filepath" +) + +const configPathRelative = `.config/soundbox/config.json` + +type SoundboxConfig struct { + Name string `json:"name"` + Mac string `json:"mac"` +} + +type GlobalConfig struct { + Soundboxes []SoundboxConfig `json:"soundboxes"` +} + +func loadConfig() (GlobalConfig, error) { + home, err := os.UserHomeDir() + if err != nil { + return GlobalConfig{}, err + } + + path := filepath.Join(home, configPathRelative) + + file, err := os.Open(path) + if err != nil { + return GlobalConfig{}, err + } + defer file.Close() + + bytes, err := io.ReadAll(file) + if err != nil { + return GlobalConfig{}, err + } + + var config GlobalConfig + err = json.Unmarshal(bytes, &config) + if err != nil { + return GlobalConfig{}, err + } + + return config, nil +} @@ -2,7 +2,10 @@ module xengineering.eu/soundbox/app go 1.23.1 -require gioui.org v0.7.1 +require ( + gioui.org v0.7.1 + xengineering.eu/soundbox v0.1.1 +) require ( gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 // indirect @@ -21,3 +21,9 @@ golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +xengineering.eu/soundbox v0.0.0-20241002195524-9c81db35038f h1:cXh21ciTMTG9K2ofbXbMSdWXVu91V4WQJspYrPHpFPQ= +xengineering.eu/soundbox v0.0.0-20241002195524-9c81db35038f/go.mod h1:wOjqdpAnoLdg5yK/twnk1Bys4QUWYAIfh+D59GuRulM= +xengineering.eu/soundbox v0.1.0 h1:XYdW+T5RjsU8+DOp1t6RLzJtzQmrBBjD7XX7qOST8Ng= +xengineering.eu/soundbox v0.1.0/go.mod h1:wOjqdpAnoLdg5yK/twnk1Bys4QUWYAIfh+D59GuRulM= +xengineering.eu/soundbox v0.1.1 h1:0zQ29w7XMzFp40yixQmPgRFwd66WAW4jDFVE0OiBQxM= +xengineering.eu/soundbox v0.1.1/go.mod h1:wOjqdpAnoLdg5yK/twnk1Bys4QUWYAIfh+D59GuRulM= @@ -4,8 +4,8 @@ import ( "context" "image/color" "log" + "net" "os" - "os/exec" "sync" "gioui.org/app" @@ -15,6 +15,8 @@ import ( "gioui.org/unit" "gioui.org/widget" "gioui.org/widget/material" + + "xengineering.eu/soundbox" ) func main() { @@ -93,7 +95,7 @@ func (ui *Ui) HandleInputs(gtx layout.Context) { ui.State.PlayerCancel() } else { ui.State.PlayerContext, ui.State.PlayerCancel = context.WithCancel(context.Background()) - go mpv(ui.State.PlayerContext, ui.State.UrlEditor.Text(), ui) + go play(ui.State.PlayerContext, ui.State.UrlEditor.Text(), ui) } } } @@ -129,7 +131,7 @@ func (ui *Ui) Layout(gtx layout.Context) layout.Dimensions { }) } -func mpv(ctx context.Context, url string, ui *Ui) { +func play(ctx context.Context, url string, ui *Ui) { setPlayingState := func(isPlaying bool) { ui.State.Lock() defer ui.Window.Invalidate() @@ -144,14 +146,24 @@ func mpv(ctx context.Context, url string, ui *Ui) { } setPlayingState(true) + defer setPlayingState(false) - cmd := exec.CommandContext( - ctx, - "mpv", - "--no-video", - url, - ) - _ = cmd.Run() + config, err := loadConfig() + if err != nil { + log.Println(err) + } - setPlayingState(false) + var devices []net.HardwareAddr + for _, entry := range config.Soundboxes { + mac, err := net.ParseMAC(entry.Mac) + if err != nil { + log.Printf("Failed to parse MAC: %v", err) + } + devices = append(devices, mac) + } + + err = soundbox.StreamURLContext(ctx, url, devices) + if err != nil { + log.Println(err) + } } |