Packages

Making Music with Extempore, OSC, and SuperCollider in LFE/OTP

Current section

Files

Jump to
undertone_lib src sc client.lfe
Raw

src/sc/client.lfe

;;;; The intent for this module is that it be a low-level, very thin wrapper
;;;; around `osc_client` and that there will be a higher-level API at a
;;;; later point in time at `sc`.
(defmodule sc.client
;; constructors
(export
(connect 0) (connect 1) (connect 2) (connect 3))
;; common
(export
(conns 1)
(ping 1))
;; impl-specific
(export
(create-synth 2) (create-synth 3) (create-synth 6)
(delete-node 2)
(delete-nodes 2)
(dump 2)
(notify 2)
(query-node 2)
(set-node 3)
(start-node 2)
(status 1)
(stop-node 2)
(sync 1) (sync 2)
(toggle-node 3)
(version 1)))
(include-lib "include/osc/client.lfe")
(defun default-host () "127.0.0.1")
(defun default-port () 57110)
(defun default-synth () "default")
(defun root-node-id () 0)
;;; Constructors
(defun connect ()
(connect (default-host)))
(defun connect (host)
(connect host (default-port)))
(defun connect (host port)
(new-connection host port))
(defun connect (host port udp-opts)
(new-connection host port udp-opts))
;;; Common Functions
(defun conns (_)
(client-conns))
(defun ping (client)
(client-ping client))
;;; Implementation-specific Functions
(defun create-synth (client id)
(create-synth client id '()))
(defun create-synth (client id args)
(create-synth client
(default-synth)
id
'add-tail
(root-node-id)
args))
(defun create-synth
"Creates a new synth and returns the synth id.
Allowed actions (atoms): add-head, add-tail, prepend, append, replace."
(((match-client pid p) name id action target-id args)
(osc_client:cast_msg p "/s_new" (lists:append `(,name
,id
,(synth-action-id action)
,target-id)
args))
id))
(defun delete-node
"Deletes a node."
(((match-client pid p) id)
(osc_client:cast_msg p "/n_free" `(,id))))
(defun delete-nodes (client ids)
(list-comp ((<- id ids))
(delete-node client id)))
(defun dump
"Allowed types (atoms): off, parsed, hex, both."
(((match-client pid p) type)
(osc_client:cast_msg p "/dumpOSC" `(,(dump-id type)))))
(defun query-node
"Get info about a node."
(((match-client pid p) id)
(osc_client:cast_msg p "/n_query" `(,id))))
(defun notify
"Register to receive notifications from server.
Toggle values (atoms): on, off."
(((match-client pid p) toggle)
(format-msg
(osc_client:call_msg p "/notify" `(,(toggle-int toggle))))))
(defun set-node
"Set a node's control value(s)."
(((match-client pid p) id args)
(osc_client:cast_msg p "/n_set" (lists:append `(,id) args))))
(defun start-node (client id)
(toggle-node client id 'on))
(defun status
(((match-client pid p))
(format-msg (osc_client:call_msg p "/status"))))
(defun stop-node (client id)
(toggle-node client id 'off))
(defun sync (client)
(sync client (rand-id)))
(defun sync
(((match-client pid p) id)
(format-msg (osc_client:call_msg p "/sync" `(,id)))))
(defun toggle-node
(((match-client pid p) id mode)
(osc_client:cast_msg p "/n_run" `(,id ,(toggle-int mode)))))
(defun version
(((match-client pid p))
(format-msg (osc_client:call_msg p "/version"))))
;;; Private Functions
(defun toggle-int (type)
(case type
('off 0)
('on 1)))
(defun dump-id (type)
(case type
('off 0)
('parsed 1)
('hex 2)
('both 3)))
(defun synth-action-id (action)
(case action
('add-head 0)
('add-tail 1)
('prepend 2)
('append 3)
('replace 4)))
(defun rand-id ()
(rand:uniform 4294967295))
(defun format-msg
((`#(message "/version.reply" (,_name ,maj ,min ,micro ,branch ,commit)))
`(#(version ,(lists:flatten (io_lib:format "~p.~p~s" `(,maj ,min ,micro))))
#(branch ,branch)
#(commit-id ,commit)))
((`#(message "/status.reply" (,_ ,ug ,s ,g ,lsd ,cau ,cpu ,nsr ,asr)))
`(#(unit-generators ,ug)
#(synths ,s)
#(gruops ,g)
#(loaded-synth-definitions ,lsd)
#(cpu-average-usage ,cau)
#(cpu-peak-usage ,cpu)
#(nominal-sample-rate ,nsr)
#(actual-sample-rate ,asr)))
((`#(message "/synced" ,_))
'ok)
((`#(message "/done" ("/notify" ,id ,ml)))
`(#(client-id ,id)
#(max-logins ,ml))))