From 3abe2c3fbe95ab0a38045c359b808fadac6220ea Mon Sep 17 00:00:00 2001 From: Samuel Johnson Date: Sun, 4 May 2025 00:25:10 -0400 Subject: Create music player GUI --- .gitignore | 1 + cmd/web/handlers/blog.go | 8 +++--- cmd/web/handlers/fs.go | 60 ++++++++++++++++++++++++++++++++++++++++++ cmd/web/handlers/routes.go | 18 +++++++++++-- cmd/web/main.go | 4 ++- cmd/web/types/application.go | 8 +++--- static/app.css | 56 +++++++++++++++++++++++++++++++++++++++ static/music_player.js | 16 +++++++++++ ui/html/base.tmpl.html | 20 ++++++++------ ui/html/music_player.tmpl.html | 28 ++++++++++++++++++++ ui/html/pages/index.tmpl.html | 2 +- 11 files changed, 203 insertions(+), 18 deletions(-) create mode 100644 cmd/web/handlers/fs.go create mode 100644 static/app.css create mode 100644 static/music_player.js create mode 100644 ui/html/music_player.tmpl.html diff --git a/.gitignore b/.gitignore index 88753d0..39f37f5 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ go.work.sum *.swp build/ +images/ diff --git a/cmd/web/handlers/blog.go b/cmd/web/handlers/blog.go index da3aec2..d995583 100644 --- a/cmd/web/handlers/blog.go +++ b/cmd/web/handlers/blog.go @@ -12,15 +12,16 @@ type blogContext struct { Name string } -func (ctx blogContext) index(w http.ResponseWriter, r *http.Request) { +func (ctx *blogContext) index(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } files := []string{ - "./ui/html/base.tmpl.html", - "./ui/html/pages/index.tmpl.html", + "ui/html/base.tmpl.html", + "ui/html/music_player.tmpl.html", + "ui/html/pages/index.tmpl.html", } compiled, err := template.ParseFiles(files...) @@ -34,5 +35,6 @@ func (ctx blogContext) index(w http.ResponseWriter, r *http.Request) { if err != nil { ctx.err.Print(err.Error()) http.Error(w, "Internal Server Error", 500) + return } } diff --git a/cmd/web/handlers/fs.go b/cmd/web/handlers/fs.go new file mode 100644 index 0000000..96f11d0 --- /dev/null +++ b/cmd/web/handlers/fs.go @@ -0,0 +1,60 @@ +package handlers + +import ( + "encoding/json" + "log" + "net/http" + "os" + "path/filepath" +) + +type fsContext struct { + err *log.Logger + path string + contentType string +} + +func (ctx *fsContext) readdir(w http.ResponseWriter, r *http.Request) { + entries, err := os.ReadDir(ctx.path) + if err != nil { + ctx.err.Print(err.Error()) + http.Error(w, "Internal Server Error", 500) + return + } + + files := make([]string, len(entries)) + for index, value := range entries { + files[index] = value.Name() + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(files) +} + +func (ctx *fsContext) get(w http.ResponseWriter, r *http.Request) { + name := r.URL.Query().Get("file") + + file, err := os.ReadFile(ctx.path + "/" + name) + if err != nil { + ctx.err.Print(err.Error()) + http.Error(w, "Internal Server Error", 500) + return + } + + if ctx.contentType != "" { + w.Header().Set("Content-Type", ctx.contentType) + } else { + switch filepath.Ext(name) { + case ".css": + w.Header().Set("Content-Type", "text/css") + case ".js": + w.Header().Set("Content-Type", "text/javascript") + case ".svg": + w.Header().Set("Content-Type", "image/svg+xml") + case ".png": + w.Header().Set("Content-Type", "image/png") + } + } + + w.Write(file) +} diff --git a/cmd/web/handlers/routes.go b/cmd/web/handlers/routes.go index 5c927c4..31fe401 100644 --- a/cmd/web/handlers/routes.go +++ b/cmd/web/handlers/routes.go @@ -6,13 +6,27 @@ import ( ) func RegisterEndpoints(app types.Application) *mux.Router { - ctx := blogContext{ + blog := blogContext{ err: app.Err, Name: app.Env.Webmaster, } + audio := fsContext{ + err: app.Err, + path: app.AudioDir, + contentType: "audio/mpeg", + } + static := fsContext{ + err: app.Err, + path: "static", + } blogRouter := mux.NewRouter() - blogRouter.HandleFunc("/", ctx.index) + blogRouter.HandleFunc("/", blog.index) + + blogRouter.HandleFunc("/audio", audio.readdir) + blogRouter.HandleFunc("/audio/get", audio.get) + + blogRouter.HandleFunc("/static/get", static.get) return blogRouter } diff --git a/cmd/web/main.go b/cmd/web/main.go index e260b42..246abeb 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -23,7 +23,9 @@ func main() { if err != nil { app.Err.Fatal("Failed to load env") } - + + app.AudioDir = os.Getenv("audio_dir") + app.Env.Webmaster = os.Getenv("webmaster") app.Env.Db.Username = os.Getenv("db_user") app.Env.Db.Password = os.Getenv("db_pass") diff --git a/cmd/web/types/application.go b/cmd/web/types/application.go index c981d64..8bc6a73 100644 --- a/cmd/web/types/application.go +++ b/cmd/web/types/application.go @@ -7,9 +7,11 @@ import ( ) type Application struct { - Err *log.Logger - Info *log.Logger + Err *log.Logger + Info *log.Logger - Env context.Environment + AudioDir string + + Env context.Environment } diff --git a/static/app.css b/static/app.css new file mode 100644 index 0000000..a52ea8d --- /dev/null +++ b/static/app.css @@ -0,0 +1,56 @@ +.pane { + margin: auto; + padding: 4px 10px; + width: 75%; + + background-color: black; + color: white; + opacity: 0.8; + + border-radius: 20px; + box-shadow: 0px 0px 15px 2px #410f5e; +} + +#bg-image { + position: fixed; + + top: 0; + left: 0; + + background-position: center; + background-repeat: no-repeat; + background-size: cover; + filter: blur(0.2rem); + -webkit-filter: blur(0.2rem); + + height: 100%; + width: 100%; + + z-index: -1; +} + +#music_player { + background-color: black; + color: white; + padding: 5px; + + position: fixed; + bottom: 0; + left: 0; + right: 0; +} + +.vert_align { + display: inline-block; + vertical-align: middle; +} + +.center { + width: 100%; + text-align: center; +} + +.button_deck { + width: 100%; + height: 5%; +} diff --git a/static/music_player.js b/static/music_player.js new file mode 100644 index 0000000..8d84774 --- /dev/null +++ b/static/music_player.js @@ -0,0 +1,16 @@ +async function mpFetchAsync (url) { + let response = await fetch(url); + let data = await response.json(); + + return data; +} + +const trackList = await mpFetchAsync("/audio"); +let trackSelector = document.getElementById("mp_tracks"); + +trackList.forEach((track) => { + let option = document.createElement("option"); + option.text = track; + + trackSelector.add(option, 0); +}); diff --git a/ui/html/base.tmpl.html b/ui/html/base.tmpl.html index f3d618d..0bcf405 100644 --- a/ui/html/base.tmpl.html +++ b/ui/html/base.tmpl.html @@ -4,16 +4,20 @@ {{template "title" .}} - Paterissa - + -
-

Paterissa

-
-
-
- {{template "main" .}} -
+ +
+
+

Paterissa

+
+
+
+ {{template "main" .}} +
+
+ {{template "music_player" .}} {{end}} diff --git a/ui/html/music_player.tmpl.html b/ui/html/music_player.tmpl.html new file mode 100644 index 0000000..e58a9c0 --- /dev/null +++ b/ui/html/music_player.tmpl.html @@ -0,0 +1,28 @@ +{{define "music_player"}} + +
+
+
+
Track Name
+
Artist
+
+
+
+ Previous Track +
+
+ Play +
+
+ Next Track +
+
+
+
00:00
+ +
00:00
+
+ +
+
+{{end}} diff --git a/ui/html/pages/index.tmpl.html b/ui/html/pages/index.tmpl.html index c252465..46a58e8 100644 --- a/ui/html/pages/index.tmpl.html +++ b/ui/html/pages/index.tmpl.html @@ -2,5 +2,5 @@ {{define "main"}}

Blog

-

Home of {{.Webmaster}}

+

Home of {{.Name}}

{{end}} -- cgit v1.2.3