-
-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial proof-of-concept snd-s7 client
- Loading branch information
Showing
8 changed files
with
426 additions
and
3 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
;; Sample snd/s7 code | ||
;; | ||
;;-------------------------------------------------------------------------------- | ||
;; NOTES: | ||
;; | ||
;; 1. This was tested with version 23.5 of snd downloaded from Sourceforge and | ||
;; compiled on a Macbook Air 13-inch Early 2015 running Monterey (12.6.7). | ||
;; snd program is compiled without a GUI (--without-gui). | ||
;; | ||
;; ********************************************************************** | ||
;; *** Unfortunately, it doesn't accept multi-line input being sent *** | ||
;; *** to it from Conjure. *** | ||
;; ********************************************************************** | ||
;; | ||
;; 2. Setting command to "snd" or "snd -noinit" doesn't make a difference in | ||
;; the snd REPL accepting multi-line input. | ||
;; | ||
;; - On the Neovim command line: | ||
;; :let g:conjure#client#snd#stdio#command="snd -noinit" | ||
;; :echo g:conjure#client#snd#stdio#command | ||
;; | ||
;; 3. Setting command to "snd -noinit" results in no return value from the | ||
;; REPL. | ||
;; | ||
;; 4. Turn on debugging to see what's being sent to and received from the snd | ||
;; REPL. | ||
;; | ||
;; - On the Neovim command line: | ||
;; :let g:conjure#debug=v:true | ||
;; :echo g:conjure#debug | ||
;; | ||
;;-------------------------------------------------------------------------------- | ||
|
||
;; From https://github.com/Olical/conjure/issues/507 | ||
;; - @kflak (Kenneth Flak) 06/24/2023 | ||
;; Changed to use test.snd. | ||
;; - This doesn't work because the snd/s7 REPL that this was originally tested | ||
;; with. See the NOTES above. | ||
(begin | ||
(open-sound "test.snd") | ||
(scale-channel 0.1) | ||
(save-sound-as "test-scaled.wav")) | ||
|
||
;; Start here and evaluated in order. | ||
;; 1. Create a sound consisting of two violin tones and save in "test.snd" file. | ||
;; test.snd will be overwritten each time that you evaluate this form. | ||
;; From "clm-load" section of https://ccrma.stanford.edu/software/snd/snd/sndscm.html | ||
(with-sound () (fm-violin 0 1 440 .1) (fm-violin 1 1 660 .1)) ;=> "test.snd" | ||
(play 0) ;; I think this is 0. | ||
(play) ;; What sound instance does this play? Seems like the last one loaded | ||
;; or created; not played. | ||
|
||
;; 2. The value passed to scale-channel determines the volume of the sound. | ||
(begin (open-sound "test.snd") (scale-channel 1.5) (save-sound-as "test-scaled.wav")) | ||
(play 1) ;; test-scaled.wav is 1. | ||
(open-sound "test-scaled.wav") | ||
(play 2) ;; should be 2. | ||
|
||
(scale-channel 2.0) ;; This makes the previous sound (#2) lounder. | ||
(play 2) ;; check it out | ||
|
||
;; 3. Load some other sounds. | ||
;; This assumes that you started Neovim in the clone of the Conjure repo | ||
;; on the branch that this is on. | ||
(open-sound "dev/snd-s7/one-tone.snd") | ||
(play 3) | ||
|
||
(open-sound "dev/snd-s7/three-tone.snd") | ||
(play 4) | ||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
;;------------------------------------------------------------ | ||
;; A client for snd/s7 (sound editor with s7 scheme scripting) | ||
;; | ||
;; Based on: fnl/conjure/client/scheme/stdio.fnl | ||
;; fnl/conjure/client/sql/stdio.fnl | ||
;; | ||
;; The `snd` program should be runnable on the command line. | ||
;; | ||
;; NOTE: Conflicts with the Scheme client due to the same filetype suffix. | ||
;; For testing the proof-of-concept, this client replaces the Scheme | ||
;; client in fnl/conjure/config.fnl. | ||
;; | ||
;;------------------------------------------------------------ | ||
|
||
(module conjure.client.snd-s7.stdio | ||
{autoload {a conjure.aniseed.core | ||
str conjure.aniseed.string | ||
nvim conjure.aniseed.nvim | ||
stdio conjure.remote.stdio-rt | ||
config conjure.config | ||
mapping conjure.mapping | ||
client conjure.client | ||
log conjure.log | ||
ts conjure.tree-sitter} | ||
require-macros [conjure.macros]}) | ||
|
||
(config.merge | ||
{:client | ||
{:snd-s7 | ||
{:stdio | ||
{:mapping {:start "cs" | ||
:stop "cS" | ||
:interrupt "ei"} | ||
:command "snd" | ||
:prompt_pattern "> "}}}}) | ||
|
||
(def- cfg (config.get-in-fn [:client :snd-s7 :stdio])) | ||
|
||
(defonce- state (client.new-state #(do {:repl nil}))) | ||
|
||
(def buf-suffix ".scm") | ||
(def comment-prefix "; ") | ||
(def form-node? ts.node-surrounded-by-form-pair-chars?) | ||
|
||
(defn- with-repl-or-warn [f opts] | ||
(let [repl (state :repl)] | ||
(if repl | ||
(f repl) | ||
(log.append [(.. comment-prefix "No REPL running")])))) | ||
|
||
;;;;-------- from client/sql/stdio.fnl ---------------------- | ||
(defn- format-message [msg] | ||
(str.split (or msg.out msg.err) "\n")) | ||
|
||
(defn- remove-blank-lines [msg] | ||
(->> (format-message msg) | ||
(a.filter #(not (= "" $1))))) | ||
|
||
(defn- display-result [msg] | ||
(log.append (remove-blank-lines msg))) | ||
|
||
(defn ->list [s] | ||
(if (a.first s) | ||
s | ||
[s])) | ||
|
||
(defn eval-str [opts] | ||
(with-repl-or-warn | ||
(fn [repl] | ||
(repl.send | ||
(.. opts.code "\n") | ||
(fn [msgs] | ||
(let [msgs (->list msgs)] | ||
(when opts.on-result | ||
(opts.on-result (str.join "\n" (remove-blank-lines (a.last msgs))))) | ||
(a.run! display-result msgs)) | ||
) | ||
{:batch? false})))) | ||
|
||
;;;;-------- End from client/sql/stdio.fnl ------------------ | ||
|
||
;;;;-------- from client/scheme/stdio.fnl ------------------- | ||
; (defn unbatch [msgs] | ||
; {:out (->> msgs | ||
; (a.map #(or (a.get $1 :out) (a.get $1 :err))) | ||
; (str.join ""))}) | ||
; | ||
; (defn format-msg [msg] | ||
; (->> (-> msg | ||
; (a.get :out) | ||
; (string.gsub "^%s*" "") | ||
; (string.gsub "%s+%d+%s*$" "") | ||
; (str.split "\n")) | ||
; (a.map | ||
; (fn [line] | ||
; (if | ||
; (not (cfg [:value_prefix_pattern])) | ||
; line | ||
; | ||
; (string.match line (cfg [:value_prefix_pattern])) | ||
; (string.gsub line (cfg [:value_prefix_pattern]) "") | ||
; | ||
; (.. comment-prefix "(out) " line)))) | ||
; (a.filter #(not (str.blank? $1))))) | ||
; | ||
; | ||
; (defn eval-str [opts] | ||
; (with-repl-or-warn | ||
; (fn [repl] | ||
; (repl.send | ||
; (.. opts.code "\n") | ||
; (fn [msgs] | ||
; (let [msgs (-> msgs unbatch format-msg)] | ||
; (opts.on-result (a.last msgs)) | ||
; (log.append msgs))) | ||
; {:batch? true})))) | ||
; | ||
;;;;-------- End from client/scheme/stdio.fnl --------------- | ||
|
||
(defn eval-file [opts] | ||
(eval-str (a.assoc opts :code (.. "(load \"" opts.file-path "\")")))) | ||
|
||
(defn interrupt [] | ||
(with-repl-or-warn | ||
(fn [repl] | ||
(log.append [(.. comment-prefix " Sending interrupt signal.")] {:break? true}) | ||
(repl.send-signal vim.loop.constants.SIGINT)))) | ||
|
||
(defn- display-repl-status [status] | ||
(log.append | ||
[(.. comment-prefix | ||
(cfg [:command]) | ||
" (" (or status "no status") ")")] | ||
{:break? true})) | ||
|
||
(defn stop [] | ||
(let [repl (state :repl)] | ||
(when repl | ||
(repl.destroy) | ||
(display-repl-status :stopped) | ||
(a.assoc (state) :repl nil)))) | ||
|
||
(defn start [] | ||
(if (state :repl) | ||
(log.append [(.. comment-prefix "Can't start, REPL is already running.") | ||
(.. comment-prefix "Stop the REPL with " | ||
(config.get-in [:mapping :prefix]) | ||
(cfg [:mapping :stop]))] | ||
{:break? true}) | ||
(a.assoc | ||
(state) :repl | ||
(stdio.start | ||
{:prompt-pattern (cfg [:prompt_pattern]) | ||
:cmd (cfg [:command]) | ||
|
||
:on-success | ||
(fn [] | ||
(display-repl-status :started)) | ||
|
||
:on-error | ||
(fn [err] | ||
(display-repl-status err)) | ||
|
||
:on-exit | ||
(fn [code signal] | ||
(when (and (= :number (type code)) (> code 0)) | ||
(log.append [(.. comment-prefix "process exited with code " code)])) | ||
(when (and (= :number (type signal)) (> signal 0)) | ||
(log.append [(.. comment-prefix "process exited with signal " signal)])) | ||
(stop)) | ||
|
||
:on-stray-output | ||
(fn [msg] | ||
(log.append (format-msg msg)))})))) | ||
|
||
(defn on-load [] | ||
(start)) | ||
|
||
(defn on-exit [] | ||
(stop)) | ||
|
||
(defn on-filetype [] | ||
(mapping.buf | ||
:SndStart (cfg [:mapping :start]) | ||
start | ||
{:desc "Start the REPL"}) | ||
|
||
(mapping.buf | ||
:SndStop (cfg [:mapping :stop]) | ||
stop | ||
{:desc "Stop the REPL"}) | ||
|
||
(mapping.buf | ||
:SdnInterrupt (cfg [:mapping :interrupt]) | ||
interrupt | ||
{:desc "Interrupt the REPL"})) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.