Improving backend

This commit is contained in:
nemunaire 2023-11-13 13:19:07 +01:00
commit c67b43ab3c
9 changed files with 301 additions and 47 deletions

View file

@ -2,16 +2,19 @@ package amp1gpio
import (
"bytes"
"fmt"
"io"
"log"
"os"
"os/exec"
"path"
"git.nemunai.re/nemunaire/hathoris/sources"
)
type AMP1GPIOSource struct {
Path string
process *exec.Cmd
Path string
}
const GPIODirectory = "/sys/class/gpio/gpio46/"
@ -39,7 +42,7 @@ func (s *AMP1GPIOSource) read() ([]byte, error) {
}
func (s *AMP1GPIOSource) IsActive() bool {
return s.IsEnabled()
return s.process != nil
}
func (s *AMP1GPIOSource) IsEnabled() bool {
@ -49,7 +52,7 @@ func (s *AMP1GPIOSource) IsEnabled() bool {
return false
}
return bytes.Compare(b, []byte{'1'}) == 0
return bytes.Compare(b, []byte{'1', '\n'}) == 0
}
func (s *AMP1GPIOSource) write(value string) error {
@ -65,9 +68,33 @@ func (s *AMP1GPIOSource) write(value string) error {
}
func (s *AMP1GPIOSource) Enable() error {
if s.process != nil {
return fmt.Errorf("Already running")
}
s.process = exec.Command("aplay", "-f", "cd", "/dev/zero")
if err := s.process.Start(); err != nil {
return err
}
go func() {
err := s.process.Wait()
if err != nil {
s.process.Process.Kill()
}
s.process = nil
}()
return s.write("1")
}
func (s *AMP1GPIOSource) Disable() error {
if s.process != nil {
if s.process.Process != nil {
s.process.Process.Kill()
}
}
return s.write("0")
}

View file

@ -11,3 +11,7 @@ type SoundSource interface {
Enable() error
Disable() error
}
type PlayingSource interface {
CurrentlyPlaying() string
}

View file

@ -2,26 +2,41 @@ package mpv
import (
"fmt"
"log"
"os"
"os/exec"
"time"
"github.com/DexterLB/mpvipc"
"git.nemunai.re/nemunaire/hathoris/sources"
)
type MPVSource struct {
process *exec.Cmd
Options []string
File string
process *exec.Cmd
ipcSocket string
Name string
Options []string
File string
}
func init() {
sources.SoundSources["mpv"] = &MPVSource{
Options: []string{"--no-video"},
File: "https://mediaserv38.live-streams.nl:18030/stream",
sources.SoundSources["mpv-1"] = &MPVSource{
Name: "Radio 1",
ipcSocket: "/tmp/tmpmpv.radio-1",
Options: []string{"--no-video", "--no-terminal"},
File: "https://mediaserv38.live-streams.nl:18030/stream",
}
sources.SoundSources["mpv-2"] = &MPVSource{
Name: "Radio 2",
ipcSocket: "/tmp/tmpmpv.radio-2",
Options: []string{"--no-video", "--no-terminal"},
File: "https://mediaserv38.live-streams.nl:18040/live",
}
}
func (s *MPVSource) GetName() string {
return "Radio 1"
return s.Name
}
func (s *MPVSource) IsActive() bool {
@ -39,6 +54,9 @@ func (s *MPVSource) Enable() (err error) {
var opts []string
opts = append(opts, s.Options...)
if s.ipcSocket != "" {
opts = append(opts, "--input-ipc-server="+s.ipcSocket, "--pause")
}
opts = append(opts, s.File)
s.process = exec.Command("mpv", opts...)
@ -55,6 +73,39 @@ func (s *MPVSource) Enable() (err error) {
s.process = nil
}()
if s.ipcSocket != "" {
_, err = os.Stat(s.ipcSocket)
for i := 20; i >= 0 && err != nil; i-- {
time.Sleep(100 * time.Millisecond)
_, err = os.Stat(s.ipcSocket)
}
time.Sleep(200 * time.Millisecond)
conn := mpvipc.NewConnection(s.ipcSocket)
err = conn.Open()
for i := 20; i >= 0 && err != nil; i-- {
time.Sleep(100 * time.Millisecond)
err = conn.Open()
}
if err != nil {
return err
}
defer conn.Close()
_, err = conn.Get("media-title")
for err != nil {
time.Sleep(100 * time.Millisecond)
_, err = conn.Get("media-title")
}
conn.Set("ao-volume", 50)
err = conn.Set("pause", false)
if err != nil {
return err
}
}
return
}
@ -67,3 +118,24 @@ func (s *MPVSource) Disable() error {
return nil
}
func (s *MPVSource) CurrentlyPlaying() string {
if s.ipcSocket != "" {
conn := mpvipc.NewConnection(s.ipcSocket)
err := conn.Open()
if err != nil {
log.Println("Unable to open mpv socket:", err.Error())
return "!"
}
defer conn.Close()
title, err := conn.Get("media-title")
if err != nil {
log.Println("Unable to retrieve title:", err.Error())
return "!"
}
return title.(string)
}
return "-"
}

116
sources/spdif/source.go Normal file
View file

@ -0,0 +1,116 @@
package spdif
import (
"fmt"
"io"
"os"
"os/exec"
"path"
"git.nemunai.re/nemunaire/hathoris/sources"
)
type SPDIFSource struct {
processRec *exec.Cmd
processPlay *exec.Cmd
DeviceIn string
DeviceOut string
Bitrate int64
Channels int64
Format string
}
func init() {
if dirs, err := os.ReadDir("/sys/class/sound"); err == nil {
for _, dir := range dirs {
thisdir := path.Join("/sys/class/sound", dir.Name())
if s, err := os.Stat(thisdir); err == nil && s.IsDir() {
idfile := path.Join(thisdir, "id")
if fd, err := os.Open(idfile); err == nil {
if cnt, err := io.ReadAll(fd); err == nil && string(cnt) == "imxspdif\n" {
sources.SoundSources["imxspdif"] = &SPDIFSource{
DeviceIn: "imxspdif",
DeviceOut: "is31ap2121",
Bitrate: 48000,
Channels: 2,
Format: "S24_LE",
}
}
fd.Close()
}
}
}
}
}
func (s *SPDIFSource) GetName() string {
return "S/PDIF"
}
func (s *SPDIFSource) IsActive() bool {
return s.processRec != nil
}
func (s *SPDIFSource) IsEnabled() bool {
return s.processRec != nil
}
func (s *SPDIFSource) Enable() error {
if s.processRec != nil {
return fmt.Errorf("Already running")
}
if s.processPlay != nil {
s.processPlay.Process.Kill()
}
pipeR, pipeW, err := os.Pipe()
if err != nil {
return err
}
s.processPlay = exec.Command("aplay", "-c", fmt.Sprintf("%d", s.Channels), "-D", "hw:"+s.DeviceOut, "--period-size=512", "-B0", "--buffer-size=512")
s.processPlay.Stdin = pipeR
if err := s.processPlay.Start(); err != nil {
return err
}
go func() {
err := s.processPlay.Wait()
if err != nil {
s.processPlay.Process.Kill()
pipeR.Close()
pipeW.Close()
}
s.processPlay = nil
}()
s.processRec = exec.Command("arecord", "-t", "wav", "-f", s.Format, fmt.Sprintf("-r%d", s.Bitrate), fmt.Sprintf("-c%d", s.Channels), "-D", "hw:"+s.DeviceIn, "-B0", "--buffer-size=512")
s.processRec.Stdout = pipeW
if err := s.processRec.Start(); err != nil {
s.processPlay.Process.Kill()
return err
}
go func() {
err := s.processRec.Wait()
if err != nil {
s.processRec.Process.Kill()
}
s.processRec = nil
}()
return nil
}
func (s *SPDIFSource) Disable() error {
if s.processRec != nil && s.processRec.Process != nil {
s.processRec.Process.Kill()
}
if s.processPlay != nil && s.processPlay.Process != nil {
s.processPlay.Process.Kill()
}
return nil
}