216 lines
3.6 KiB
Go
216 lines
3.6 KiB
Go
package marlinbox
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"time"
|
|
|
|
evdev "github.com/gvalkov/golang-evdev"
|
|
"github.com/hajimehoshi/go-mp3"
|
|
"github.com/hajimehoshi/oto/v2"
|
|
)
|
|
|
|
type MarlinBox struct {
|
|
DeviceName string `json:"devicename"`
|
|
DevicePath string `json:"devicepath,omitempty"`
|
|
CurrentID string
|
|
Volume float64 `json:"volume,omitempty"`
|
|
Playlist []*PlayCard `json:"playlist,omitempty"`
|
|
ControlCards []*ControlCard `json:"controlcards,omitempty"`
|
|
Device *evdev.InputDevice
|
|
CurrentPlayCard *PlayCard
|
|
Player oto.Player
|
|
PlayerContext *oto.Context
|
|
}
|
|
|
|
type RFIDCard struct {
|
|
ID string `json:"id"`
|
|
}
|
|
|
|
type PlayCard struct {
|
|
RFIDCard
|
|
File string `json:"file,omitempty"`
|
|
}
|
|
type ControlCard struct {
|
|
RFIDCard
|
|
Function string `json:"function,omitempty"`
|
|
}
|
|
|
|
var KeyMap = map[uint16]string{
|
|
2: "1",
|
|
3: "2",
|
|
4: "3",
|
|
5: "4",
|
|
6: "5",
|
|
7: "6",
|
|
8: "7",
|
|
9: "8",
|
|
10: "9",
|
|
11: "0",
|
|
28: "ENTER",
|
|
}
|
|
|
|
func New(path string) *MarlinBox {
|
|
var mb *MarlinBox
|
|
|
|
f, err := os.ReadFile(path)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
err = json.Unmarshal(f, &mb)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if mb.Volume == 0 {
|
|
mb.Volume = 1
|
|
}
|
|
|
|
if mb.DeviceName == "" {
|
|
panic("No DeviceName given")
|
|
}
|
|
|
|
devices, err := evdev.ListInputDevices()
|
|
|
|
for _, dev := range devices {
|
|
if dev.Name == mb.DeviceName {
|
|
mb.DevicePath = dev.Fn
|
|
}
|
|
}
|
|
|
|
if mb.DevicePath == "" {
|
|
panic("Device not found")
|
|
}
|
|
|
|
return mb
|
|
}
|
|
|
|
func (mb *MarlinBox) Run() {
|
|
var err error
|
|
mb.Device, err = evdev.Open(mb.DevicePath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
mb.Device.Grab()
|
|
|
|
go func() {
|
|
for {
|
|
events, err := mb.Device.Read()
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
|
|
for _, ev := range events {
|
|
if ev.Value != 0x1 {
|
|
continue
|
|
}
|
|
val, ok := KeyMap[ev.Code]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if val == "ENTER" {
|
|
err := mb.GetCurrentCard()
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
fmt.Println(mb.CurrentPlayCard)
|
|
mb.CurrentID = ""
|
|
// err =
|
|
// if err != nil {
|
|
// log.Println(err)
|
|
// panic(err)
|
|
// }
|
|
continue
|
|
}
|
|
|
|
mb.CurrentID += val
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (mb *MarlinBox) GetCurrentCard() error {
|
|
fmt.Println(mb.ControlCards)
|
|
for _, c := range mb.ControlCards {
|
|
if mb.CurrentID == c.ID {
|
|
switch c.Function {
|
|
case "vol+":
|
|
fmt.Println("vol+")
|
|
if mb.Volume < 1.0 {
|
|
mb.Volume = mb.Volume + 0.2
|
|
}
|
|
case "vol-":
|
|
fmt.Println("vol-")
|
|
if mb.Volume > 0 {
|
|
mb.Volume = mb.Volume - 0.2
|
|
}
|
|
default:
|
|
return nil
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
for _, c := range mb.Playlist {
|
|
if mb.CurrentID == c.ID {
|
|
mb.CurrentPlayCard = c
|
|
if mb.PlayerContext != nil {
|
|
mb.Player.Reset()
|
|
}
|
|
mb.Play()
|
|
return nil
|
|
}
|
|
}
|
|
return errors.New("Card not found: " + mb.CurrentID)
|
|
}
|
|
|
|
func (mb *MarlinBox) Play() {
|
|
go func() {
|
|
var err error
|
|
var ready chan struct{}
|
|
playingID := mb.CurrentPlayCard.ID
|
|
f, err := os.Open(mb.CurrentPlayCard.File)
|
|
if err != nil {
|
|
log.Println(err)
|
|
return
|
|
}
|
|
defer f.Close()
|
|
|
|
d, err := mp3.NewDecoder(f)
|
|
if err != nil {
|
|
log.Println(err)
|
|
return
|
|
}
|
|
|
|
mb.PlayerContext, ready, err = oto.NewContext(d.SampleRate(), 2, 2)
|
|
if err != nil {
|
|
log.Println(err)
|
|
return
|
|
}
|
|
<-ready
|
|
|
|
mb.Player = mb.PlayerContext.NewPlayer(d)
|
|
defer mb.Player.Close()
|
|
mb.Player.SetVolume(mb.Volume)
|
|
mb.Player.Play()
|
|
|
|
for {
|
|
if mb.CurrentPlayCard.ID != playingID {
|
|
break
|
|
}
|
|
if mb.Volume != mb.Player.Volume() {
|
|
mb.Player.SetVolume(mb.Volume)
|
|
}
|
|
time.Sleep(time.Second)
|
|
if !mb.Player.IsPlaying() {
|
|
break
|
|
}
|
|
}
|
|
}()
|
|
|
|
}
|