radiospiral_linux/main.go

234 lines
4.8 KiB
Go
Raw Normal View History

2023-12-04 01:24:00 +01:00
package main
import (
"bufio"
"encoding/json"
"fmt"
2023-12-04 01:24:00 +01:00
"io"
"net/http"
2023-12-04 01:24:00 +01:00
"os/exec"
"strings"
"time"
2023-12-04 01:24:00 +01:00
"fyne.io/fyne/v2"
2023-12-04 01:24:00 +01:00
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
2023-12-04 01:56:39 +01:00
"fyne.io/fyne/v2/theme"
2023-12-04 01:24:00 +01:00
"fyne.io/fyne/v2/widget"
)
// helper
func check(err error) {
if err != nil {
panic(err)
}
}
// JSON data we receive from the wp-json/radio/broadcast endpoint
type BroadcastResponse struct {
Broadcast BroadcastInfo `json:"broadcast"`
Updated int `json:"updated"`
Success bool `json:"success"`
}
type BroadcastInfo struct {
NowPlaying NowPlayingInfo `json:"now_playing"`
NextShow NextShowInfo `json:"next_show"`
CurrentShow bool `json:"current_show"`
}
type NowPlayingInfo struct {
Text string `json:"text"`
Artist string `json:"artist"`
Title string `json:"title"`
}
type NextShowInfo struct {
Day string `json:"day"`
Date string `json:"date"`
Start string `json:"start"`
End string `json:"end"`
Show ShowData `json:"show"`
}
type ShowData struct {
Name string `json:"name"`
AvatarUrl string `json:"avatar_url"`
ImageUrl string `json:"image_url"`
Hosts []HostsData `json:"hosts"`
}
type HostsData struct {
Name string `json:"name"`
}
2023-12-04 01:24:00 +01:00
// Radio player interface
type RadioPlayer interface {
Play(stream_url string)
Mute()
Pause()
IncVolume()
DecVolume()
Close()
}
// MPlayer
type MPlayer struct {
player_name string
is_playing bool
stream_url string
command *exec.Cmd
in io.WriteCloser
out io.ReadCloser
pipe_chan chan io.ReadCloser
}
func (player *MPlayer) Play(stream_url string) {
if !player.is_playing {
var err error
is_playlist := strings.HasSuffix(stream_url, ".m3u") || strings.HasSuffix(stream_url, ".pls")
if is_playlist {
// player.command = exec.Command(player.player_name, "-quiet", "-playlist", stream_url)
player.command = exec.Command(player.player_name, "-playlist", stream_url)
2023-12-04 01:24:00 +01:00
} else {
player.command = exec.Command(player.player_name, stream_url)
2023-12-04 01:24:00 +01:00
}
player.in, err = player.command.StdinPipe()
check(err)
player.out, err = player.command.StdoutPipe()
check(err)
err = player.command.Start()
check(err)
player.is_playing = true
player.stream_url = stream_url
go func() {
player.pipe_chan <- player.out
}()
}
}
func (player *MPlayer) Close() {
if player.is_playing {
player.is_playing = false
player.in.Write([]byte("q"))
player.in.Close()
player.out.Close()
player.command = nil
player.stream_url = ""
}
}
func (player *MPlayer) Mute() {
if player.is_playing {
player.in.Write([]byte("m"))
}
}
func (player *MPlayer) Pause() {
if player.is_playing {
player.in.Write([]byte("p"))
}
}
func (player *MPlayer) IncVolume() {
if player.is_playing {
player.in.Write([]byte("*"))
}
}
func (player *MPlayer) DecVolume() {
if player.is_playing {
player.in.Write([]byte("/"))
}
}
func main() {
RADIOSPIRAL_JSON_ENDPOINT := "https://radiospiral.net/wp-json/radio/broadcast"
2023-12-04 01:24:00 +01:00
status_chan := make(chan string)
pipe_chan := make(chan io.ReadCloser)
mplayer := MPlayer{player_name: "mplayer", is_playing: false, pipe_chan: pipe_chan}
// Process the output of Mplayer here
2023-12-04 01:24:00 +01:00
go func() {
for {
out_pipe := <-pipe_chan
reader := bufio.NewReader(out_pipe)
for {
data, err := reader.ReadString('\n')
if err != nil {
status_chan <- "Playing stopped"
break
} else {
status_chan <- data
}
}
}
}()
app := app.New()
window := app.NewWindow("RadioSpiral")
window.Resize(fyne.NewSize(400, 600))
2023-12-04 01:56:39 +01:00
play_status := false
2023-12-04 01:24:00 +01:00
radiospiral_label := widget.NewLabel("RadioSpiral")
nowplaying_label := widget.NewLabel("")
radiospiral_label.Alignment = fyne.TextAlignCenter
nowplaying_label.Alignment = fyne.TextAlignCenter
2023-12-04 01:56:39 +01:00
var play_button *widget.Button
play_button = widget.NewButtonWithIcon("", theme.MediaStopIcon(), func() {
if !mplayer.is_playing {
play_button.SetIcon(theme.MediaPlayIcon())
mplayer.Play("https://radiospiral.radio/stream.mp3")
2023-12-04 01:56:39 +01:00
play_status = true
} else {
if play_status {
play_status = false
play_button.SetIcon(theme.MediaPauseIcon())
} else {
play_status = true
play_button.SetIcon(theme.MediaPlayIcon())
}
mplayer.Pause()
}
})
2023-12-04 01:24:00 +01:00
2023-12-04 11:26:17 +01:00
header := container.NewCenter(radiospiral_label)
2023-12-04 01:24:00 +01:00
window.SetContent(container.NewVBox(
2023-12-04 11:26:17 +01:00
header,
layout.NewSpacer(),
2023-12-04 01:24:00 +01:00
nowplaying_label,
2023-12-04 01:56:39 +01:00
play_button,
2023-12-04 01:24:00 +01:00
))
go func() {
for {
fmt.Println("Retrieving broadcast data")
resp, err := http.Get(RADIOSPIRAL_JSON_ENDPOINT)
check(err)
body, err := io.ReadAll(resp.Body)
check(err)
var broadcastResponse BroadcastResponse
json.Unmarshal(body, &broadcastResponse)
nowplaying_label.SetText("Now playing: " + broadcastResponse.Broadcast.NowPlaying.Text)
time.Sleep(60 * time.Second)
}
}()
2023-12-04 01:24:00 +01:00
window.ShowAndRun()
2023-12-04 01:28:03 +01:00
mplayer.Close()
2023-12-04 01:24:00 +01:00
}