Add slate request handler

This change adds a request handler for /slate. This endpoint can
now be used to upload a new slate file.
This commit is contained in:
Saxon Nelson-Milton 2023-05-25 06:17:58 +09:30
parent e078d9f2bc
commit 382f202bb0
2 changed files with 46 additions and 4 deletions

View File

@ -34,6 +34,7 @@ import (
"io" "io"
"net" "net"
"net/http" "net/http"
"os"
"strconv" "strconv"
"sync" "sync"
"time" "time"
@ -217,6 +218,46 @@ func (m *broadcastManager) control(w http.ResponseWriter, r *http.Request) {
} }
} }
// slate handles slate API requests to upload a new slate video.
func (m *broadcastManager) slate(w http.ResponseWriter, r *http.Request) {
done := m.dogNotifier.handlerInvoked("slate")
defer done()
if r.Method != http.MethodPost {
http.Error(w, "invalid request method", http.StatusMethodNotAllowed)
return
}
file, _, err := r.FormFile("slate-file")
if err != nil {
m.errorLogWrite(m.log, w, "could not get slate file from form", "error", err)
return
}
defer file.Close()
// This will overwrite the slate file if it already exists.
dst, err := os.OpenFile(slateFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
m.errorLogWrite(m.log, w, "could not open slate file", "error", err)
return
}
defer dst.Close()
n, err := io.Copy(dst, file)
if err != nil {
m.errorLogWrite(m.log, w, "could not copy slate file", "error", err)
return
}
// Return response to client as JSON.
jsn, err := json.Marshal(map[string]interface{}{"size": n})
if err != nil {
m.errorLogWrite(m.log, w, "could not get json for response", "error", err)
return
}
fmt.Fprint(w, string(jsn))
}
// processRequest unmarshals the broadcast data object from the request into // processRequest unmarshals the broadcast data object from the request into
// a Broadcast value, and then performs the provided action with that value. // a Broadcast value, and then performs the provided action with that value.
func (m *broadcastManager) processRequest(w http.ResponseWriter, r *http.Request, action func(Broadcast) error) { func (m *broadcastManager) processRequest(w http.ResponseWriter, r *http.Request, action func(Broadcast) error) {
@ -374,6 +415,7 @@ func main() {
http.HandleFunc("/recv", m.recv) http.HandleFunc("/recv", m.recv)
http.HandleFunc("/control", m.control) http.HandleFunc("/control", m.control)
http.HandleFunc("/slate", m.slate)
go m.dogNotifier.notify() go m.dogNotifier.notify()

View File

@ -36,6 +36,10 @@ import (
"bitbucket.org/ausocean/utils/logging" "bitbucket.org/ausocean/utils/logging"
) )
// @note this is temporary; slate names will be created based on device mac so that we can
// have a slate per device (or maybe multiple slates per device).
const slateFileName = "/home/saxon/go/src/bitbucket.org/ausocean/av/cmd/vidforward/slate.h264"
func writeSlateAndCheckErrors(dst io.Writer, signalCh chan struct{}, log logging.Logger) error { func writeSlateAndCheckErrors(dst io.Writer, signalCh chan struct{}, log logging.Logger) error {
// Also create an errCh that will be used to communicate errors from the // Also create an errCh that will be used to communicate errors from the
// writeSlate routine. // writeSlate routine.
@ -72,10 +76,6 @@ func writeSlateAndCheckErrors(dst io.Writer, signalCh chan struct{}, log logging
func writeSlate(dst io.Writer, errCh chan error, exitSignal chan struct{}, log logging.Logger) { func writeSlate(dst io.Writer, errCh chan error, exitSignal chan struct{}, log logging.Logger) {
log.Info("writing slate") log.Info("writing slate")
const ( const (
// This is temporary and will eventually be part of a broadcast configuration
// where the remote vidforward API user can provide the slate image.
slateFileName = "/home/saxon/go/src/bitbucket.org/ausocean/av/cmd/vidforward/slate.h264"
// Assume 25fps until this becomes configurable. // Assume 25fps until this becomes configurable.
slateFrameRate = 25 slateFrameRate = 25