Initial commit

This commit is contained in:
itsscb 2022-11-20 21:54:24 +01:00
parent d350105040
commit 69686418ef
6 changed files with 277 additions and 0 deletions

2
.gitignore vendored
View File

@ -13,3 +13,5 @@
# Dependency directories (remove the comment below to include it)
# vendor/
*.mp3

13
cmd/main.go Normal file
View File

@ -0,0 +1,13 @@
package main
import (
"time"
marlinbox "github.com/itsscb/marlin-box"
)
func main() {
mb := marlinbox.New("playlist.json")
mb.Run()
time.Sleep(time.Minute * 5)
}

28
cmd/playlist.json Normal file
View File

@ -0,0 +1,28 @@
{
"devicename":"Sycreader RFID Technology Co., Ltd SYC ID&IC USB Reader",
"volume": 1.0,
"playlist": [
{
"id": "0002693373",
"file": "./music/ACDC - Back In Black.mp3"
},
{
"id": "0011415256",
"file": "./music/ACDC - TNT.mp3"
},
{
"id": "0011394336",
"file": "./music/ACDC - Thunderstruck.mp3"
}
],
"controlcards": [
{
"id": "0011462127",
"function": "vol+"
},
{
"id": "0011394129",
"function": "vol-"
}
]
}

11
go.mod Normal file
View File

@ -0,0 +1,11 @@
module marlinbox
go 1.18
require (
github.com/gvalkov/golang-evdev v0.0.0-20220815104727-7e27d6ce89b6
github.com/hajimehoshi/go-mp3 v0.3.4
github.com/hajimehoshi/oto/v2 v2.3.1
)
require golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e // indirect

8
go.sum Normal file
View File

@ -0,0 +1,8 @@
github.com/gvalkov/golang-evdev v0.0.0-20220815104727-7e27d6ce89b6 h1:K9b8efT9f1NkITNgNAm2A1LuoamhG4pAhXVjz5Sfa5Q=
github.com/gvalkov/golang-evdev v0.0.0-20220815104727-7e27d6ce89b6/go.mod h1:SAzVFKCRezozJTGavF3GX8MBUruETCqzivVLYiywouA=
github.com/hajimehoshi/go-mp3 v0.3.4 h1:NUP7pBYH8OguP4diaTZ9wJbUbk3tC0KlfzsEpWmYj68=
github.com/hajimehoshi/go-mp3 v0.3.4/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo=
github.com/hajimehoshi/oto/v2 v2.3.1 h1:qrLKpNus2UfD674oxckKjNJmesp9hMh7u7QCrStB3Rc=
github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e h1:NHvCuwuS43lGnYhten69ZWqi2QOj/CiDNcKbVqwVoew=
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

215
marlinbox.go Normal file
View File

@ -0,0 +1,215 @@
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
}
}
}()
}