diff options
| -rw-r--r-- | .nrepl-port | 2 | ||||
| -rw-r--r-- | portal.clj | 84 | ||||
| -rw-r--r-- | src/.main.clj.swp | bin | 16384 -> 0 bytes | |||
| -rw-r--r-- | src/main.clj | 74 |
4 files changed, 108 insertions, 52 deletions
diff --git a/.nrepl-port b/.nrepl-port index 41bb84d..0b9fe47 100644 --- a/.nrepl-port +++ b/.nrepl-port @@ -1 +1 @@ -51213
\ No newline at end of file +53291
\ No newline at end of file diff --git a/portal.clj b/portal.clj new file mode 100644 index 0000000..ce05eb8 --- /dev/null +++ b/portal.clj @@ -0,0 +1,84 @@ +(ns portal + (:require [missionary.core :as m] + [clojure.set :refer [union difference]])) + +(def focused-tags (atom #{})) +(def >focused-tags (m/signal (m/watch focused-tags))) + +(def seen-tags (atom #{})) +(def >seen-tags (m/signal (m/watch seen-tags))) + +(defn rec + "Record flow f, tagging with id." + [id f] + (m/ap + (let [capturing? (atom nil) + [tag value] + (m/amb= [:focused-tags (m/?< >focused-tags)] + [:event (m/?< f)])] + (case tag + :focused-tags + (do + (reset! capturing? (boolean (value id))) + (m/amb)) + + :event + (do + (swap! seen-tags conj id) + (when @capturing? + (m/? (m/via m/blk ((requiring-resolve 'portal.api/submit) [id value])))) + value))))) + +(defn ptags + "Print all available tags." + [] @seen-tags) + +(def show-portal? (atom false)) +(def >show-portal? (rec :show-portal? (m/signal (m/watch show-portal?)))) + +(defn show-portal + "Show portal window." + [] + (reset! show-portal? true)) + +(defn hide-portal + "Hide portal window." + [] + (reset! show-portal? false)) + +(def >portal-ui + (m/ap + (when (m/?< >show-portal?) + (try + (m/?< + (m/observe + (fn [cb] + ((m/via m/blk ((requiring-resolve 'portal.api/open))) {} {}) + (cb :open) + (fn [] + ((m/via m/blk + ((requiring-resolve 'portal.api/close)) + ((requiring-resolve 'portal.api/clear))) {} {}))))) + (catch missionary.Cancelled _ + (m/amb))) + (m/amb)))) + +(defn cap + "Capture flow elements with specified ids to portal" + [& ids] + (reset! focused-tags (into #{} ids))) + +(defn +cap + "Add do portal capture set" + [& ids] + (swap! focused-tags union (into #{} ids))) + +(defn -cap + "Remove from portal capture set" + [& ids] + (swap! focused-tags difference (into #{} ids))) + +(def >portal-main + "Main entrypoint." + (m/ap (m/amb= (do (m/?< >portal-ui) + (m/amb))))) diff --git a/src/.main.clj.swp b/src/.main.clj.swp Binary files differdeleted file mode 100644 index b91b1b6..0000000 --- a/src/.main.clj.swp +++ /dev/null diff --git a/src/main.clj b/src/main.clj index 7674cc1..d3f7ce0 100644 --- a/src/main.clj +++ b/src/main.clj @@ -1,22 +1,7 @@ (ns main (:require [missionary.core :as m] - [clojure.set :refer [difference union]])) - -(def >portal - (m/signal - (m/ap - (try - (m/?< - (m/observe - (fn [cb] - ((m/via m/blk ((requiring-resolve 'portal.api/open))) {} {}) - (cb :open) - (fn [] - ((m/via m/blk - ((requiring-resolve 'portal.api/close)) - ((requiring-resolve 'portal.api/clear))) {} {}))))) - (catch missionary.Cancelled _ - (m/amb)))))) + [clojure.set :refer [difference union]] + [portal :refer [>portal-main rec show-portal hide-portal +cap -cap cap]])) ;; How many times per second are output continuous values sampled and turned ;; into events? @@ -28,9 +13,11 @@ (reset! sample-rate v)) (def notes-on (atom #{})) -(def >notes-on (m/signal (m/watch notes-on))) +(def >notes-on (rec :notes-set (m/signal (m/watch notes-on)))) (def midi-enabled? (atom true)) +(def >midi-enabled? (rec :midi-enabled? + (m/signal (m/watch midi-enabled?)))) (defn enable-midi "Enable midi out." @@ -62,8 +49,9 @@ ;; TODO: Currently, there will be latency when changing the sample rate ;; due to having to wait for the most recent sleep to complete ;; Update clock to be reactive on sample-rate, too - (m/? - (m/sleep (/ 1000 @sample-rate))) + (do (m/? + (m/sleep (/ 1000 @sample-rate))) + (m/amb)) :tick (recur))))) @@ -96,7 +84,7 @@ (let [local-midi-enabled? (atom nil) local-active (atom #{}) [tag value] (m/amb= - [:midi-enabled? (m/?< (m/watch midi-enabled?))] + [:midi-enabled? (m/?< >midi-enabled?)] [:note-event (m/?< output)])] (case tag :midi-enabled? @@ -137,33 +125,9 @@ (recur (rest notes))) (m/amb))))))) -(def enable-portal-submission? (atom false)) -(def >enable-portal-submission? (m/watch enable-portal-submission?)) - -(defn enable-portal-submission [] - (reset! enable-portal-submission? true)) - -(defn disable-portal-submission [] - (reset! enable-portal-submission? false)) - -(def tap-flow - (m/ap - (let [local-enable-portal-submission? (atom nil) - [tag value] - (m/amb= [:enable-portal-submission? (m/?< >enable-portal-submission?)] - [:event (m/?< set->midi-events)])] - (case tag - :enable-portal-submission? - (do - (reset! local-enable-portal-submission? value) - (when value - (m/?< >portal)) - (m/amb)) - :event - (do - (when @local-enable-portal-submission? - (m/? (m/via m/blk ((requiring-resolve 'portal.api/submit) value)))) - value))))) +(def main + (m/ap (m/amb= (m/?< (rec :root set->midi-events)) + (m/?< >portal-main)))) (defn start-engine "Start playback engine." @@ -171,7 +135,7 @@ (when (not @engine) (reset! engine (do (enable-midi) - ((m/reduce prn tap-flow) {} {}))))) + ((m/reduce {} {} main) {} {}))))) (defn stop-engine "Stop playback engine." @@ -184,14 +148,22 @@ (comment (start-engine) + (cap) + + (+cap :root :notes-set) + + (show-portal) + (play-notes 1 2 3 4 5) (stop-notes 4 5) - (enable-portal-submission) + (play-notes 1 2 3 4) + (-cap :root) + (disable-midi) (play-notes 1 2 3 4) - (disable-portal-submission) + (hide-portal) (enable-midi) (play-notes 1 2 3 4) |
