236 lines
5.5 KiB
Go
236 lines
5.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"html"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/faiface/beep"
|
|
"github.com/faiface/beep/mp3"
|
|
"github.com/faiface/beep/speaker"
|
|
)
|
|
|
|
type playback struct {
|
|
File string
|
|
IsLoaded bool
|
|
Streamer beep.Streamer
|
|
Control *beep.Ctrl
|
|
}
|
|
|
|
type playbackWebReturn struct {
|
|
File string
|
|
IsLoaded bool
|
|
Id int
|
|
}
|
|
|
|
type streamBuf struct {
|
|
Streamer beep.Streamer
|
|
Format beep.Format
|
|
Buffer *beep.Buffer
|
|
}
|
|
|
|
var playbacks map[int]playback
|
|
var mapMutex = sync.Mutex{}
|
|
|
|
var streamMap map[string]streamBuf
|
|
|
|
func BufferSound(file string) bool {
|
|
_, ok := streamMap[file]
|
|
if !ok {
|
|
fmt.Println("Not in memory, loading")
|
|
f, err := os.Open("./sounds/" + file)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Println("Opened file")
|
|
streamer, format, err := mp3.Decode(f)
|
|
speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
|
|
|
|
fmt.Println("Decoded file")
|
|
buffer := beep.NewBuffer(format)
|
|
buffer.Append(streamer)
|
|
streamer.Close()
|
|
fmt.Println("Bufferd file")
|
|
|
|
// Save to streamMap
|
|
streamMap[file] = streamBuf{
|
|
Streamer: streamer,
|
|
Format: format,
|
|
Buffer: buffer,
|
|
}
|
|
return (true)
|
|
} else {
|
|
return (false)
|
|
}
|
|
}
|
|
|
|
func PlaySound(file string, index int) int {
|
|
playbacks[index] = playback{
|
|
File: file,
|
|
IsLoaded: false,
|
|
Streamer: nil,
|
|
Control: nil,
|
|
}
|
|
|
|
fmt.Println("Playing sound: " + file)
|
|
var buffer *beep.Buffer
|
|
BufferSound(file)
|
|
buffer = streamMap[file].Buffer
|
|
streamer := streamMap[file].Streamer
|
|
|
|
fmt.Println("Trying to play sound")
|
|
shot := buffer.Streamer(0, buffer.Len())
|
|
|
|
done := make(chan bool)
|
|
ctrl := &beep.Ctrl{Streamer: beep.Seq(shot, beep.Callback(func() {
|
|
done <- true
|
|
})), Paused: false}
|
|
|
|
playbacks[index] = playback{
|
|
File: file,
|
|
IsLoaded: true,
|
|
Streamer: streamer,
|
|
Control: ctrl,
|
|
}
|
|
speaker.Play(ctrl)
|
|
<-done
|
|
fmt.Println("Finished playing sound: " + file)
|
|
delete(playbacks, index)
|
|
return 1
|
|
}
|
|
|
|
func main() {
|
|
|
|
playbacks = make(map[int]playback)
|
|
streamMap = make(map[string]streamBuf)
|
|
|
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Query().Get("name")))
|
|
})
|
|
|
|
http.HandleFunc("/v1/play", func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
var cnt = r.URL.Query().Get("file")
|
|
bytArr, err := base64.StdEncoding.DecodeString(cnt)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
fmt.Println(string(bytArr[:]))
|
|
t, err := os.Stat("./sounds/" + string(bytArr[:]))
|
|
t = t
|
|
if !errors.Is(err, os.ErrNotExist) {
|
|
var currIndex = len(playbacks)
|
|
fmt.Fprintf(w, "{\"status\":\"ok\", \"id\":%d}", currIndex)
|
|
|
|
go PlaySound(string(bytArr[:]), currIndex)
|
|
|
|
} else {
|
|
fmt.Fprintf(w, "{\"status\":\"fail\", \"reason\":\"file not found\"}")
|
|
}
|
|
|
|
})
|
|
|
|
http.HandleFunc("/v1/buffer", func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
var cnt = r.URL.Query().Get("file")
|
|
bytArr, err := base64.StdEncoding.DecodeString(cnt)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
t, err := os.Stat("./sounds/" + string(bytArr[:]))
|
|
t = t
|
|
if !errors.Is(err, os.ErrNotExist) {
|
|
fmt.Fprintf(w, "{\"status\":\"ok\"}")
|
|
go BufferSound(string(bytArr[:]))
|
|
} else {
|
|
fmt.Fprintf(w, "{\"status\":\"fail\", \"reason\":\"file not found\"}")
|
|
}
|
|
|
|
})
|
|
|
|
http.HandleFunc("/v1/stopAll", func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
playbacks = make(map[int]playback)
|
|
fmt.Fprintf(w, "{\"status\":\"ok\"}")
|
|
speaker.Clear()
|
|
//fmt.Fprintf(w, "{\"status\":\"ok\", \"id\":%d}", currIndex)
|
|
|
|
})
|
|
|
|
http.HandleFunc("/v1/stop", func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
var cnt, err = strconv.Atoi(r.URL.Query().Get("id"))
|
|
if err != nil {
|
|
fmt.Fprintf(w, "{\"status\":\"fail\", \"reason\":\"invalid id\"}")
|
|
}
|
|
|
|
value, ok := playbacks[cnt]
|
|
if !ok {
|
|
fmt.Fprintf(w, "{\"status\":\"fail\", \"reason\":\"audio not playing\"}")
|
|
} else {
|
|
fmt.Fprintf(w, "{\"status\":\"ok\", \"id\":%d}", value)
|
|
value.Control.Paused = true
|
|
value.Control.Streamer = nil
|
|
delete(playbacks, cnt)
|
|
}
|
|
//fmt.Fprintf(w, "{\"status\":\"ok\", \"id\":%d}", currIndex)
|
|
|
|
})
|
|
|
|
http.HandleFunc("/v1/current", func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
var tempResultSet map[int]playbackWebReturn
|
|
tempResultSet = make(map[int]playbackWebReturn)
|
|
|
|
for index, element := range playbacks {
|
|
tempResultSet[index] = playbackWebReturn{File: element.File, IsLoaded: element.IsLoaded, Id: index}
|
|
}
|
|
|
|
j, err := json.Marshal(tempResultSet)
|
|
if err != nil {
|
|
fmt.Printf("Error: %s", err.Error())
|
|
} else {
|
|
fmt.Println(string(j))
|
|
}
|
|
fmt.Fprintf(w, string(j))
|
|
})
|
|
|
|
http.HandleFunc("/v1/list", func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
var temp [][3]string
|
|
files, err := ioutil.ReadDir("./sounds/")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
for _, f := range files {
|
|
var soundObj [3]string
|
|
soundObj[0] = f.Name()
|
|
soundObj[1] = base64.StdEncoding.EncodeToString([]byte(f.Name()))
|
|
soundObj[2] = r.URL.Host + "/v1/play?file=" + soundObj[1]
|
|
temp = append(temp, soundObj)
|
|
}
|
|
|
|
j, err := json.Marshal(temp)
|
|
if err != nil {
|
|
fmt.Printf("Error: %s", err.Error())
|
|
} else {
|
|
fmt.Println(string(j))
|
|
}
|
|
fmt.Fprintf(w, string(j))
|
|
})
|
|
log.Fatal(http.ListenAndServe(":8081", nil))
|
|
|
|
}
|