Add a mini-player to build mode
Every song in the Build tab gets a play button. A bar along the bottom plays the folder in order with seeking, previous/next, volume (kept per browser) and space to pause, and says so when the browser can't play a format. Songs stream from the master library through a new endpoint with range requests; it only serves regular music files inside the library. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
da74756c24
commit
491d679233
7 files changed
+443
-4
No files matched your search
@@ -101,6 +101,7 @@ func (s *Server) Handler() http.Handler {
|
||||
r.Post("/renames", s.handleRenames)
|
||||
r.Post("/link-identical", s.handleLinkIdentical)
|
||||
r.Get("/tree", s.handleTree)
|
||||
r.Get("/listen", s.handleListen)
|
||||
r.Get("/empty-folders", s.handleEmptyFolders)
|
||||
r.Post("/empty-folders/scan", s.handleEmptyFolderScan)
|
||||
r.Post("/empty-folders/remove", s.handleRemoveEmptyFolders)
|
||||
@@ -786,3 +787,33 @@ func (s *Server) handleRemoveEmptyFolders(w http.ResponseWriter, r *http.Request
|
||||
s.log.Info("removing folders without music", "pair", id, "folders", len(body.Folders))
|
||||
writeJSON(w, 202, j)
|
||||
}
|
||||
|
||||
// ---- listening (build mode player) ----
|
||||
|
||||
var audioTypes = map[string]string{
|
||||
".flac": "audio/flac", ".mp3": "audio/mpeg", ".m4a": "audio/mp4", ".aac": "audio/aac", ".alac": "audio/mp4",
|
||||
".ogg": "audio/ogg", ".oga": "audio/ogg", ".opus": "audio/ogg", ".wav": "audio/wav", ".aif": "audio/aiff",
|
||||
".aiff": "audio/aiff", ".mka": "audio/x-matroska", ".wma": "audio/x-ms-wma",
|
||||
}
|
||||
|
||||
// handleListen streams a song with range support, so the browser can seek.
|
||||
func (s *Server) handleListen(w http.ResponseWriter, r *http.Request) {
|
||||
id, _ := idParam(r)
|
||||
q := r.URL.Query()
|
||||
f, fi, err := s.eng.OpenSong(r.Context(), id, q.Get("side"), q.Get("path"))
|
||||
if err != nil {
|
||||
opErr(w, err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
ct := audioTypes[strings.ToLower(filepath.Ext(fi.Name()))]
|
||||
if ct == "" {
|
||||
ct = "application/octet-stream"
|
||||
}
|
||||
w.Header().Set("Content-Type", ct)
|
||||
w.Header().Set("Cache-Control", "private, max-age=300")
|
||||
// A long song on a slow connection may take longer than the server's
|
||||
// write timeout.
|
||||
_ = http.NewResponseController(w).SetWriteDeadline(time.Time{})
|
||||
http.ServeContent(w, r, fi.Name(), fi.ModTime(), f)
|
||||
}
|
||||
Reference in new issue
Block a user