diff --git a/README.md b/README.md index 1980368..8700bf1 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,12 @@ Jukebox2 is a communal music player for team environments. Users can upload their own music, and jukebox2 will cycle through it and play a mix. + +## getting started + +* put your music in music/ + +## hacking + +* use `lein spec spec/jukebox_web/models/xyz_spec.clj` to run a single test suite +* use `lein ring server-headless` to run the app in development mode \ No newline at end of file diff --git a/spec/jukebox_web/models/playlist_spec.clj b/spec/jukebox_web/models/playlist_spec.clj index 18578aa..a918e37 100644 --- a/spec/jukebox_web/models/playlist_spec.clj +++ b/spec/jukebox_web/models/playlist_spec.clj @@ -55,6 +55,16 @@ (playlist/add-song! "user/artist/album/track2.mp3") (should= first-value (first (playlist/queued-songs)))))) + (describe "add-album!" + (with-test-music-library) + + (it "adds all the songs in this album to the queued songs" + (playlist/add-album! "user/artist/album") + (should= 2 (count (playlist/queued-songs))) + (should= #{(library/file-on-disk "user/artist/album/track.mp3") + (library/file-on-disk "user/artist/album/track2.mp3")} + (set (map :song (playlist/queued-songs)))))) + (describe "add-random-song!" (it "adds a random song to the queued songs" (should (empty? (playlist/queued-songs))) diff --git a/src/jukebox_web/controllers/library.clj b/src/jukebox_web/controllers/library.clj index e60a342..96b33d4 100644 --- a/src/jukebox_web/controllers/library.clj +++ b/src/jukebox_web/controllers/library.clj @@ -10,7 +10,7 @@ "upload complete")) (defn browse-root [request] - (view/browse request "Music Library" (library/list-directory))) + (view/browse request library/*music-library-title* (library/list-directory))) (defn browse [request] (let [path (-> request :params :path) diff --git a/src/jukebox_web/controllers/playlist.clj b/src/jukebox_web/controllers/playlist.clj index bc833d1..65eb0f1 100644 --- a/src/jukebox_web/controllers/playlist.clj +++ b/src/jukebox_web/controllers/playlist.clj @@ -52,6 +52,15 @@ (let [song (-> request :params :song) user (current-user request)] (when (user/canAdd? user) (playlist/add-song! song user)) - (if (json/request? ((:headers request) "accept")) - (json/response (build-playlist user)) - {:status 302 :headers {"Location" "/playlist"}}))) + (if (json/request? ((:headers request) "accept")) + (json/response (build-playlist user)) + {:status 302 :headers {"Location" "/playlist"}}))) + +(defn add-album [request] + (let [album-directory (-> request :params :album-dir) + user (current-user request)] + (when (user/canAdd? user) + (playlist/add-album! album-directory user)) + (if (json/request? ((:headers request) "accept")) + (json/response (build-playlist user)) + {:status 302 :headers {"Location" "/playlist"}}))) diff --git a/src/jukebox_web/core.clj b/src/jukebox_web/core.clj index 59d165d..955f76f 100644 --- a/src/jukebox_web/core.clj +++ b/src/jukebox_web/core.clj @@ -27,6 +27,7 @@ (POST "/playlist/add" [] playlist-controller/add) (DELETE "/playlist/:id/delete" [] playlist-controller/delete) (GET ["/playlist/add/:song" :song #".*"] [] playlist-controller/add) + (GET ["/playlist/add-album/:album-dir" :album-dir #".*"] [] playlist-controller/add-album) (GET "/player/play" [] player-controller/play) (GET "/player/pause" [] player-controller/pause) (GET "/player/skip" [] player-controller/skip) diff --git a/src/jukebox_web/models/library.clj b/src/jukebox_web/models/library.clj index 5d13fab..dd072e2 100644 --- a/src/jukebox_web/models/library.clj +++ b/src/jukebox_web/models/library.clj @@ -7,6 +7,9 @@ (:use [jukebox-player.tags] [jukebox-web.util.file :only (strip-slashes relative-uri file-path mkdir-p mv)])) +;; constants +;; TODO: earmuffs should denote mutable vars, not constants +(def *music-library-title* "Music Library") (def *music-library* "music") (def *play-counts-model* "play-counts") (def *skip-counts-model* "skip-counts") diff --git a/src/jukebox_web/models/playlist.clj b/src/jukebox_web/models/playlist.clj index 282cf7d..df0a4fd 100644 --- a/src/jukebox_web/models/playlist.clj +++ b/src/jukebox_web/models/playlist.clj @@ -56,6 +56,10 @@ (if (< (recent-songs-to-keep) (count @recent-songs-atom)) (swap! recent-songs-atom pop)))) +(defn add-album! [album-directory & [user]] + (let [album-songs (library/list-directory album-directory)] + (doseq [song album-songs] (add-song! song user)))) + (defn add-random-song! [] (loop [song (random-song) attempts 0] (if (or (nil? song) (.contains @recent-songs-atom song)) diff --git a/src/jukebox_web/util/file.clj b/src/jukebox_web/util/file.clj index fef9cd2..2ab0e95 100644 --- a/src/jukebox_web/util/file.clj +++ b/src/jukebox_web/util/file.clj @@ -18,3 +18,4 @@ (defn strip-slashes [string] (clojure-string/replace-str "/" " " string)) + diff --git a/src/jukebox_web/views/library.clj b/src/jukebox_web/views/library.clj index 0c950ed..02470c3 100644 --- a/src/jukebox_web/views/library.clj +++ b/src/jukebox_web/views/library.clj @@ -2,7 +2,8 @@ (:require [jukebox-web.views.layout :as layout] [jukebox-web.models.library :as library] [jukebox-web.models.user :as user] - [clojure.string :as string]) + [clojure.string :as string] + [ring.util.codec :as ring-util]) (:use [hiccup core page-helpers] [hiccup core form-helpers] [jukebox-player.tags] @@ -10,9 +11,19 @@ (defn link-or-string [file request] (if (user/canAdd? (-> request :session :current-user)) - (link-to (str "/playlist/add/" (relative-uri file)) (.getName file) " (" (library/play-count (library/file-on-disk file)) ")") + (link-to (str "/playlist/add/" (relative-uri file)) + (.getName file) + " (" + (library/play-count (library/file-on-disk file)) + ")") (str (.getName file) " (" (library/play-count (library/file-on-disk file)) ")"))) +(defn album-link [album-path user] + (when (and (not= album-path library/*music-library-title*) + (user/canAdd? user)) + (link-to (str "/playlist/add-album/" (ring-util/url-encode album-path)) + "Add Album!"))) + (defn display-file [file request] (if (library/track? file) (link-or-string file request) @@ -20,8 +31,9 @@ (defn browse [request path files] (let [parent-path (library/parent-directory path)] - (layout/main request "browse library" - [:h3 "Files in " path " (play count)"] - [:ul - (if-not (nil? parent-path) [:li (link-to (str "/library/browse/" parent-path) "..")]) - (map #(vector :li (display-file % request)) (sort files))]))) + (layout/main request "browse library" + [:h3 "Files in " path " (play count)"] + (album-link path (-> request :session :current-user)) + [:ul + (if-not (nil? parent-path) [:li (link-to (str "/library/browse/" parent-path) "..")]) + (map #(vector :li (display-file % request)) (sort files))])))