diff --git a/src/cljs/airsonic_ui/audio/core.cljs b/src/cljs/airsonic_ui/audio/core.cljs index a1747e5..fe72581 100644 --- a/src/cljs/airsonic_ui/audio/core.cljs +++ b/src/cljs/airsonic_ui/audio/core.cljs @@ -2,7 +2,8 @@ "This namespace contains some JS interop code to interact with an audio player and receive information about the current playback status so we can use it in our re-frame app." - (:require [re-frame.core :as re-frame])) + (:require [re-frame.core :as re-frame] + [airsonic-ui.audio.playlist :as playlist])) ;; TODO: Manage buffering @@ -64,15 +65,25 @@ (re-frame/reg-sub :audio/summary summary) +(defn playlist + "Lists the complete playlist" + [summary _] + (:playlist summary)) + +(re-frame/reg-sub + :audio/playlist + (fn [_ _] (re-frame/subscribe [:audio/summary])) + playlist) + (defn current-song "Gives us information about the currently played song as presented by the airsonic api" - [summary _] - (:current-song summary)) + [playlist _] + (playlist/peek playlist)) (re-frame/reg-sub :audio/current-song - (fn [_ _] (re-frame/subscribe [:audio/summary])) + (fn [_ _] (re-frame/subscribe [:audio/playlist])) current-song) (defn playback-status @@ -93,17 +104,5 @@ (re-frame/reg-sub :audio/is-playing? - (fn [_ _] (re-frame/subscribe [:audio/current-playback-status])) + (fn [_ _] (re-frame/subscribe [:audio/playback-status])) is-playing?) - -(comment - ;; NOTE: Not in use currently - (defn current-playlist - "Lists the complete playlist" - [summary _] - (:playlist summary)) - - (re-frame/reg-sub - :audio/current-playlist - (fn [_ _] (re-frame/subscribe [:audio/summary])) - current-playlist)) diff --git a/src/cljs/airsonic_ui/events.cljs b/src/cljs/airsonic_ui/events.cljs index 1d91b6d..fac3463 100644 --- a/src/cljs/airsonic_ui/events.cljs +++ b/src/cljs/airsonic_ui/events.cljs @@ -3,7 +3,8 @@ [ajax.core :as ajax] [airsonic-ui.routes :as routes] [airsonic-ui.db :as db] - [airsonic-ui.utils.api :as api])) + [airsonic-ui.utils.api :as api] + [airsonic-ui.audio.playlist :as playlist])) (re-frame/reg-fx ;; a simple effect to keep println statements out of our event handlers @@ -178,30 +179,40 @@ (re-frame/reg-event-fx ; sets up the db, starts to play a song and adds the rest to a playlist ::play-songs - (fn [{:keys [db]} [_ songs song]] - {:audio/play (song-url db song) - :db (-> (assoc-in db [:audio :current-song] song) - (assoc-in [:audio :playlist] songs))})) + (fn [{:keys [db]} [_ songs start-idx]] + (println "play-songs called with" start-idx songs) + (let [playlist (-> (playlist/->playlist songs :playback-mode :linear :repeat-mode :repeat-all) + (playlist/set-current-song start-idx))] + {:audio/play (song-url db (playlist/peek playlist)) + :db (assoc-in db [:audio :playlist] playlist)}))) + +;; FIXME: :audio/play might not get the right argument here + +(re-frame/reg-event-db + ::set-playback-mode + (fn [db [_ playback-mode]] + (update-in db [:audio :playlist] #(playlist/set-playback-mode % playback-mode)))) + +(re-frame/reg-event-db + ::set-repeat-mode + (fn [db [_ repeat-mode]] + (update-in db [:audio :playlist] #(playlist/set-repeat-mode % repeat-mode)))) (re-frame/reg-event-fx ::next-song (fn [{:keys [db]} _] - (let [playlist (get-in db [:audio :playlist]) - current-song (get-in db [:audio :current-song]) - next (first (rest (drop-while #(not= % current-song) playlist)))] - (when next - {:audio/play (song-url db next) - :db (assoc-in db [:audio :current-song] next)})))) + (let [db (update-in db [:audio :playlist] playlist/next-song) + next (playlist/peek (get-in db [:audio :playlist]))] + {:db db + :audio/play (song-url db next)}))) (re-frame/reg-event-fx ::previous-song (fn [{:keys [db]} _] - (let [playlist (get-in db [:audio :playlist]) - current-song (get-in db [:audio :current-song]) - previous (last (take-while #(not= % current-song) playlist))] - (when previous - {:audio/play (song-url db previous) - :db (assoc-in db [:audio :current-song] previous)})))) + (let [db (update-in db [:audio :playlist] playlist/previous-song) + prev (playlist/peek (get-in db [:audio :playlist]))] + {:db db + :audio/play (song-url db prev)}))) (re-frame/reg-event-fx ::toggle-play-pause diff --git a/src/cljs/airsonic_ui/subs.cljs b/src/cljs/airsonic_ui/subs.cljs index 3dc6e80..7af379c 100644 --- a/src/cljs/airsonic_ui/subs.cljs +++ b/src/cljs/airsonic_ui/subs.cljs @@ -1,5 +1,6 @@ (ns airsonic-ui.subs (:require [re-frame.core :as re-frame :refer [subscribe]] + [airsonic-ui.audio.playlist :as playlist] [airsonic-ui.utils.api :as api])) (defn is-booting? diff --git a/src/cljs/airsonic_ui/views/song.cljs b/src/cljs/airsonic_ui/views/song.cljs index a7a0c2e..408b0d7 100644 --- a/src/cljs/airsonic_ui/views/song.cljs +++ b/src/cljs/airsonic_ui/views/song.cljs @@ -4,7 +4,7 @@ [airsonic-ui.routes :as routes :refer [url-for]] [airsonic-ui.views.icon :refer [icon]])) -(defn item [songs song] +(defn item [songs song idx] (let [artist-id (:artistId song)] [:div [:a @@ -14,14 +14,14 @@ [:a {:href "#" :on-click (fn [e] (.preventDefault e) - (dispatch [::events/play-songs songs song]))} + (dispatch [::events/play-songs songs idx]))} (:title song)]])) (defn listing [songs] [:table.table.is-striped.is-hoverable.is-fullwidth>tbody (for [[idx song] (map-indexed vector songs)] ^{:key idx} [:tr - [:td.grow [item songs song]] + [:td.grow [item songs song idx]] ;; FIXME: Not implemented yet [:td>a {:title "Play next"} [icon :plus]] [:td>a {:title "Play last"} [icon :arrow-thick-right]]])])