mirror of
https://github.com/heyarne/airsonic-ui.git
synced 2026-05-07 10:43:39 +02:00
Add skipping for linear playlists with all repeat modes
This commit is contained in:
parent
98ddd1b9ca
commit
d7b8cbcc4e
3 changed files with 99 additions and 32 deletions
|
|
@ -11,38 +11,39 @@
|
|||
(defmulti ->playlist
|
||||
"Creates a new playlist that behaves according to the given playback- and
|
||||
repeat-mode parameters."
|
||||
(fn [queue play-idx playback-mode repeat-mode] playback-mode))
|
||||
(fn [queue playing-idx playback-mode repeat-mode] playback-mode))
|
||||
|
||||
(defn- playlist-queue
|
||||
[queue play-idx]
|
||||
(concat (take play-idx queue)
|
||||
[(assoc (nth queue play-idx) :currently-playing? true)]
|
||||
(drop (inc play-idx) queue)))
|
||||
[queue playing-idx]
|
||||
(concat (take playing-idx queue)
|
||||
[(assoc (nth queue playing-idx) :currently-playing? true)]
|
||||
(drop (inc playing-idx) queue)))
|
||||
|
||||
(defmethod ->playlist
|
||||
:playback-mode/linear
|
||||
[queue play-idx playback-mode repeat-mode]
|
||||
(let [queue (->> (playlist-queue queue play-idx)
|
||||
(map (fn [order song] (assoc song :order order))
|
||||
(range (count queue))))]
|
||||
(defmethod ->playlist :playback-mode/linear
|
||||
[queue playing-idx playback-mode repeat-mode]
|
||||
(let [queue (->> (playlist-queue queue playing-idx)
|
||||
(mapv (fn [order song] (assoc song :order order))
|
||||
(range (count queue))))]
|
||||
(->Playlist queue playback-mode repeat-mode)))
|
||||
|
||||
(defmethod ->playlist
|
||||
:playback-mode/shuffle
|
||||
[queue play-idx playback-mode repeat-mode]
|
||||
(let [queue (->> (playlist-queue queue play-idx)
|
||||
(map (fn [order song] (assoc song :order order))
|
||||
(shuffle (range (count queue)))))]
|
||||
(defmethod ->playlist :playback-mode/shuffle
|
||||
[queue playing-idx playback-mode repeat-mode]
|
||||
(let [queue (->> (playlist-queue queue playing-idx)
|
||||
(mapv (fn [order song] (assoc song :order order))
|
||||
(shuffle (range (count queue)))))]
|
||||
(->Playlist queue playback-mode repeat-mode)))
|
||||
|
||||
(defn- current-idx [playlist]
|
||||
(first (keep-indexed (fn [idx item]
|
||||
(when (:currently-playing? item)
|
||||
idx))
|
||||
(:queue playlist))))
|
||||
|
||||
(defn set-playback-mode
|
||||
"Changes the playback mode of a playlist and re-suffles it if necessary"
|
||||
"Changes the playback mode of a playlist and re-shuffles it if necessary"
|
||||
[playlist playback-mode]
|
||||
(let [current-idx (first (keep-indexed (fn [idx item]
|
||||
(when (:currently-playing? item)
|
||||
idx))
|
||||
(:queue playlist)))]
|
||||
(->playlist (:queue playlist) current-idx playback-mode (:repeat-mode playlist))))
|
||||
(->playlist (:queue playlist) (current-idx playlist)
|
||||
playback-mode (:repeat-mode playlist)))
|
||||
|
||||
(defn set-repeat-mode
|
||||
"Allows to change the way the next and previous song of a playlist is selected"
|
||||
|
|
@ -56,5 +57,38 @@
|
|||
(filter :currently-playing?)
|
||||
(first)))
|
||||
|
||||
(defn- ?assoc
|
||||
"Like assoc, but returns coll unchanged if (pref coll) is false"
|
||||
[coll pred & assog-args]
|
||||
(if (pred coll) (apply assoc coll assog-args) coll))
|
||||
|
||||
(defmulti next-song (juxt :playback-mode :repeat-mode))
|
||||
|
||||
(defmethod next-song [:playback-mode/linear :repeat-mode/none]
|
||||
[playlist]
|
||||
(let [current-idx (current-idx playlist)
|
||||
next-idx (inc current-idx)]
|
||||
(println "next-idx" next-idx "current-idx" current-idx "(< next-idx (count playlist))" (< next-idx (count playlist)))
|
||||
(update playlist :queue
|
||||
(fn [queue] (-> (update queue current-idx dissoc :currently-playing?)
|
||||
(?assoc #(< next-idx (count playlist))
|
||||
next-idx (assoc (get queue next-idx)
|
||||
:currently-playing? true)))))))
|
||||
|
||||
(defmethod next-song [:playback-mode/linear :repeat-mode/single]
|
||||
[playlist]
|
||||
playlist)
|
||||
|
||||
(defmethod next-song [:playback-mode/linear :repeat-mode/all]
|
||||
[playlist]
|
||||
(let [current-idx (current-idx playlist)
|
||||
next-idx (mod (inc current-idx) (count playlist))]
|
||||
(update playlist :queue
|
||||
(fn [queue] (-> (update queue current-idx dissoc :currently-playing?)
|
||||
(assoc-in [next-idx :currently-playing?] true))))))
|
||||
|
||||
(defmethod next-song [:playback-mode/shuffle :repeat-mode/single]
|
||||
[playlist]
|
||||
playlist)
|
||||
|
||||
(defmulti previous-song (juxt :playback-mode :repeat-mode))
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
[ajax.core :as ajax]
|
||||
[airsonic-ui.routes :as routes]
|
||||
[airsonic-ui.db :as db]
|
||||
[airsonic-ui.utils.api :as api]
|
||||
[day8.re-frame.tracing :refer-macros [fn-traced defn-traced]])) ; <- useful to debug handlers
|
||||
[airsonic-ui.utils.api :as api]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
;; a simple effect to keep println statements out of our event handlers
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
(:require [cljs.test :refer [deftest testing is]]
|
||||
[airsonic-ui.audio.playlist :as playlist]
|
||||
[airsonic-ui.fixtures :as fixtures]
|
||||
[airsonic-ui.test-helpers :as helpers]))
|
||||
[airsonic-ui.test-helpers :as helpers]
|
||||
[debux.cs.core :refer-macros [dbg]]))
|
||||
|
||||
(enable-console-print!)
|
||||
|
||||
|
|
@ -90,14 +91,47 @@
|
|||
(str "from " repeat-mode " to " next-repeat-mode)))))))
|
||||
|
||||
(deftest linear-next-song
|
||||
(testing "Should follow the same order as the queue used for creation")
|
||||
(testing "Should go back to the first song when repeat-mode is all")
|
||||
(testing "Should always give the same track when repeat-mode is single"))
|
||||
(testing "Should follow the same order as the queue used for creation"
|
||||
(doseq [repeat-mode [:repeat-mode/none :repeat-mode/all]]
|
||||
(let [queue (playing-queue 5)
|
||||
playlist (playlist/->playlist queue 0 :playback-mode/linear repeat-mode)]
|
||||
(is (same-song? (nth queue 1) (-> (playlist/next-song playlist)
|
||||
(playlist/peek)))
|
||||
(str repeat-mode ", skipped once"))
|
||||
(is (same-song? (nth queue 2) (-> (playlist/next-song playlist)
|
||||
(playlist/next-song)
|
||||
(playlist/peek)))
|
||||
(str repeat-mode ", skipped twice")))))
|
||||
(testing "Should go back to the first song when repeat-mode is all and we played the last song")
|
||||
(testing "Should always give the same track when repeat-mode is single"
|
||||
(let [queue (playing-queue 3)
|
||||
playing-idx (rand-int 3)
|
||||
playlist (playlist/->playlist queue playing-idx :playback-mode/linear :repeat-mode/single)]
|
||||
(is (same-song? (nth queue playing-idx) (playlist/peek playlist)))
|
||||
(is (same-song? (nth queue playing-idx)
|
||||
(-> (playlist/next-song playlist)
|
||||
(playlist/peek))))
|
||||
(is (same-song? (nth queue playing-idx)
|
||||
(-> (playlist/next-song playlist)
|
||||
(playlist/next-song)
|
||||
(playlist/peek))))
|
||||
(is (same-song? (nth queue playing-idx)
|
||||
(-> (playlist/next-song playlist)
|
||||
(playlist/next-song)
|
||||
(playlist/next-song)
|
||||
(playlist/peek)))
|
||||
"wrapping around")))
|
||||
(testing "Should stop playing at the end of the queue when repeat-mode is none"
|
||||
(is (nil? (-> (playing-queue 1)
|
||||
(playlist/->playlist 0 :playback-mode/linear :repeat-mode/none)
|
||||
(playlist/next-song)
|
||||
(playlist/peek))))))
|
||||
|
||||
(deftest shuffled-next-song
|
||||
#_(deftest shuffled-next-song
|
||||
(testing "Should play every track once when called for the entire queue")
|
||||
(testing "Should re-shuffle the playlist when wrapping around and repeat-mode is all")
|
||||
(testing "Should always give the same track when repeat-mode is single"))
|
||||
(testing "Should always give the same track when repeat-mode is single")
|
||||
(testing "Should stop playing at the end of the queue when repeat-mode is none"))
|
||||
|
||||
#_(deftest linear-previous-song)
|
||||
#_(deftest shuffled-previous-song)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue