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 } } }() }