├── README.org ├── c-example ├── aseqdump.c └── build.sh ├── cl-alsaseq.asd ├── driver ├── bindings.lisp ├── cl-alsaseq.lisp └── event-lookup.lisp ├── easy-api.lisp ├── midihelper ├── clock.lisp ├── midihelper.lisp ├── reader.lisp ├── slime-bindings.el └── writer.lisp ├── midiloops.lisp ├── package.lisp ├── readtable.lisp └── swig ├── bindings.i ├── bits.poll.h ├── generate.sh ├── poll.h └── seq_event.h /README.org: -------------------------------------------------------------------------------- 1 | #+TITLE: cl-alsaseq 2 | 3 | This is cl-alsaseq, a Common Lisp library for accessing the ALSA MIDI interface. With it, you can send and receive MIDI messages to and from any program or device that is supported by ALSA. 4 | 5 | This library was originally written by Richard Venn, however after he deleted his GitHub account (and the original repo for this project with it), I (modula t.) re-hosted it. 6 | 7 | I'm making a few improvements here and there to the system, however most major improvements will instead be done as part of [[https://github.com/defaultxr/cl-alsa-midi][cl-alsa-midi]]. 8 | 9 | If you're just using the library for your own projects and need something stable, use cl-alsaseq. cl-alsaseq's API should remain stable, but it will not be submitted to Quicklisp. 10 | 11 | If you're intending to make improvements to the code of the library, consider adding them to [[https://github.com/defaultxr/cl-alsa-midi][cl-alsa-midi]] instead, as I intend to deprecate cl-alsaseq in favor of it, as it (and its API) will be vastly simpler and its code should be much improved. After cl-alsa-midi's API is improved and stabilized, it will be submitted to Quicklisp. 12 | 13 | * Example 14 | 15 | #+BEGIN_SRC lisp 16 | (ql:quickload :cl-alsaseq) ; Load the system. 17 | 18 | ;; Define a basic handler function for MIDI input. 19 | (defun midi-map (messages) 20 | (dolist (message messages) 21 | (let* ((event-type (getf message :event-type)) 22 | (event-data (getf message :event-data)) 23 | (source (car (getf message :source))) 24 | (destination (car (getf message :dest)))) 25 | (declare (ignorable source destination)) 26 | (format t "~A: ~S~%" 27 | (case event-type 28 | (:snd_seq_event_noteon "Note on") 29 | (:snd_seq_event_noteoff "Note off") 30 | (:snd_seq_event_controller "CC") 31 | (t event-type)) 32 | event-data)))) 33 | 34 | ;; Start the ALSA MIDI client with midi-map function as input handler. 35 | (midihelper:start-midihelper :master 96 'midi-map) 36 | 37 | ;; ...Then connect the "CL" ALSA MIDI source to the destination of your choice. 38 | ;; I usually use Qjackctl to manage MIDI connections. 39 | 40 | (defparameter *midi-channel* 0) 41 | 42 | (midihelper:send-event (midihelper:ev-noteon *midi-channel* 69 127)) ; Send a MIDI note on event. 69 is the note number, 127 is the velocity 43 | 44 | (midihelper:send-event (midihelper:ev-noteoff *midi-channel* 69 127)) ; Send a MIDI note off to stop the previous note. 45 | 46 | (midihelper:send-event (midihelper:ev-pgmchange *midi-channel* 2)) ; Send a program change message to switch to program #2. 47 | #+END_SRC 48 | -------------------------------------------------------------------------------- /c-example/aseqdump.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | static snd_seq_t *seq; 9 | static int port_count; 10 | static volatile sig_atomic_t stop = 0; 11 | 12 | static void init_seq(void) 13 | { 14 | snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); 15 | snd_seq_set_client_name(seq, "aseqdump"); 16 | } 17 | 18 | int create_port(void) 19 | { 20 | return snd_seq_create_simple_port(seq, "aseqdump", 21 | SND_SEQ_PORT_CAP_WRITE | 22 | SND_SEQ_PORT_CAP_SUBS_WRITE | 23 | SND_SEQ_PORT_CAP_READ | 24 | SND_SEQ_PORT_CAP_SUBS_READ, 25 | SND_SEQ_PORT_TYPE_MIDI_GENERIC | 26 | SND_SEQ_PORT_TYPE_APPLICATION); 27 | } 28 | 29 | int main(int argc, char *argv[]) 30 | { 31 | 32 | init_seq(); 33 | 34 | int my_port = create_port(); 35 | 36 | snd_seq_nonblock(seq, 1); 37 | 38 | if (port_count > 0) 39 | printf("Waiting for data."); 40 | else 41 | printf("Waiting for data at port %d:0.", 42 | snd_seq_client_id(seq)); 43 | printf(" Press Ctrl+C to end.\n"); 44 | printf("Source_ Event_________________ Ch _Data__\n"); 45 | 46 | struct pollfd *pfds; 47 | int npfds; 48 | npfds = snd_seq_poll_descriptors_count(seq, POLLIN); 49 | pfds = alloca(sizeof(*pfds) * npfds); 50 | printf("allocated %d descriptors\n", npfds); 51 | snd_seq_poll_descriptors(seq, pfds, npfds, POLLIN); 52 | 53 | snd_seq_event_t *event; 54 | while(1) { 55 | int npolls; 56 | if ( (npolls = poll(pfds, npfds, -1)) > 0 ) { 57 | printf ("polled %d times\n", npolls); 58 | snd_seq_event_input(seq, &event); 59 | printf ("got thing from %d, %d. Type = %d\n", 60 | event->source.client, 61 | event->source.port, 62 | event->type); 63 | printf ("sending thing to %d, %d. Type = %d\n", 64 | event->dest.client, 65 | event->dest.port, 66 | event->type); 67 | 68 | snd_seq_ev_set_source(event, my_port); 69 | snd_seq_ev_set_subs(event); 70 | snd_seq_ev_set_direct(event); 71 | 72 | printf ("got thing from %d, %d. Type = %d\n", 73 | event->source.client, 74 | event->source.port, 75 | event->type); 76 | printf ("sending thing to %d, %d. Type = %d\n", 77 | event->dest.client, 78 | event->dest.port, 79 | event->type); 80 | 81 | snd_seq_event_output_direct(seq, event); 82 | /* Should be equivalent to the two lines below */ 83 | /* snd_seq_event_output(seq, event); */ 84 | /* snd_seq_drain_output(seq); */ 85 | } 86 | else 87 | printf("failed to poll %d times\n", npolls); 88 | } 89 | snd_seq_close(seq); 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /c-example/build.sh: -------------------------------------------------------------------------------- 1 | gcc -Wall -o aseqdump aseqdump.c -I../../include -lasound -lm -ldl -lpthread 2 | -------------------------------------------------------------------------------- /cl-alsaseq.asd: -------------------------------------------------------------------------------- 1 | ;;;; cl-alsaseq.asd 2 | 3 | (asdf:defsystem #:cl-alsaseq 4 | :name "cl-alsaseq" 5 | :description "Common Lisp bindings to ALSA MIDI." 6 | :author "Rick Venn " 7 | :maintainer "modula t. " 8 | :license "GPL" 9 | :depends-on (#:cffi #:calispel #:optima #:let-over-lambda) 10 | :serial t 11 | :components ((:file "package") 12 | (:file "driver/bindings") 13 | (:file "driver/event-lookup") 14 | (:file "driver/cl-alsaseq") 15 | (:file "midihelper/reader") 16 | (:file "midihelper/writer") 17 | (:file "midihelper/clock") 18 | (:file "midihelper/midihelper") 19 | (:file "easy-api") 20 | (:file "readtable") 21 | (:file "midiloops"))) 22 | -------------------------------------------------------------------------------- /driver/bindings.lisp: -------------------------------------------------------------------------------- 1 | ;;; This file was automatically generated by SWIG (http://www.swig.org). 2 | ;;; Version 3.0.3 3 | ;;; 4 | ;;; Do not make changes to this file unless you know what you are doing--modify 5 | ;;; the SWIG interface file instead. 6 | 7 | (in-package :cl-alsaseq) 8 | 9 | 10 | 11 | (cl:defconstant _SYS_POLL_H 1) 12 | 13 | (cffi:defcstruct pollfd 14 | (fd :int) 15 | (events :short) 16 | (revents :short)) 17 | 18 | (cffi:defcfun ("poll" poll) :int 19 | (__fds :pointer) 20 | (__nfds :unsigned-long) 21 | (__timeout :int)) 22 | 23 | (cl:defconstant POLLIN #x001) 24 | 25 | (cl:defconstant POLLPRI #x002) 26 | 27 | (cl:defconstant POLLOUT #x004) 28 | 29 | (cl:defconstant POLLERR #x008) 30 | 31 | (cl:defconstant POLLHUP #x010) 32 | 33 | (cl:defconstant POLLNVAL #x020) 34 | 35 | (cffi:defcenum snd_seq_event_type 36 | (:SND_SEQ_EVENT_SYSTEM #.0) 37 | :SND_SEQ_EVENT_RESULT 38 | (:SND_SEQ_EVENT_NOTE #.5) 39 | :SND_SEQ_EVENT_NOTEON 40 | :SND_SEQ_EVENT_NOTEOFF 41 | :SND_SEQ_EVENT_KEYPRESS 42 | (:SND_SEQ_EVENT_CONTROLLER #.10) 43 | :SND_SEQ_EVENT_PGMCHANGE 44 | :SND_SEQ_EVENT_CHANPRESS 45 | :SND_SEQ_EVENT_PITCHBEND 46 | :SND_SEQ_EVENT_CONTROL14 47 | :SND_SEQ_EVENT_NONREGPARAM 48 | :SND_SEQ_EVENT_REGPARAM 49 | (:SND_SEQ_EVENT_SONGPOS #.20) 50 | :SND_SEQ_EVENT_SONGSEL 51 | :SND_SEQ_EVENT_QFRAME 52 | :SND_SEQ_EVENT_TIMESIGN 53 | :SND_SEQ_EVENT_KEYSIGN 54 | (:SND_SEQ_EVENT_START #.30) 55 | :SND_SEQ_EVENT_CONTINUE 56 | :SND_SEQ_EVENT_STOP 57 | :SND_SEQ_EVENT_SETPOS_TICK 58 | :SND_SEQ_EVENT_SETPOS_TIME 59 | :SND_SEQ_EVENT_TEMPO 60 | :SND_SEQ_EVENT_CLOCK 61 | :SND_SEQ_EVENT_TICK 62 | :SND_SEQ_EVENT_QUEUE_SKEW 63 | :SND_SEQ_EVENT_SYNC_POS 64 | (:SND_SEQ_EVENT_TUNE_REQUEST #.40) 65 | :SND_SEQ_EVENT_RESET 66 | :SND_SEQ_EVENT_SENSING 67 | (:SND_SEQ_EVENT_ECHO #.50) 68 | :SND_SEQ_EVENT_OSS 69 | (:SND_SEQ_EVENT_CLIENT_START #.60) 70 | :SND_SEQ_EVENT_CLIENT_EXIT 71 | :SND_SEQ_EVENT_CLIENT_CHANGE 72 | :SND_SEQ_EVENT_PORT_START 73 | :SND_SEQ_EVENT_PORT_EXIT 74 | :SND_SEQ_EVENT_PORT_CHANGE 75 | :SND_SEQ_EVENT_PORT_SUBSCRIBED 76 | :SND_SEQ_EVENT_PORT_UNSUBSCRIBED 77 | (:SND_SEQ_EVENT_USR0 #.90) 78 | :SND_SEQ_EVENT_USR1 79 | :SND_SEQ_EVENT_USR2 80 | :SND_SEQ_EVENT_USR3 81 | :SND_SEQ_EVENT_USR4 82 | :SND_SEQ_EVENT_USR5 83 | :SND_SEQ_EVENT_USR6 84 | :SND_SEQ_EVENT_USR7 85 | :SND_SEQ_EVENT_USR8 86 | :SND_SEQ_EVENT_USR9 87 | (:SND_SEQ_EVENT_SYSEX #.130) 88 | :SND_SEQ_EVENT_BOUNCE 89 | (:SND_SEQ_EVENT_USR_VAR0 #.135) 90 | :SND_SEQ_EVENT_USR_VAR1 91 | :SND_SEQ_EVENT_USR_VAR2 92 | :SND_SEQ_EVENT_USR_VAR3 93 | :SND_SEQ_EVENT_USR_VAR4 94 | (:SND_SEQ_EVENT_NONE #.255)) 95 | 96 | (cffi:defcstruct snd_seq_addr_t 97 | (client :unsigned-char) 98 | (port :unsigned-char)) 99 | 100 | (cffi:defcstruct snd_seq_connect_t 101 | (sender (:struct snd_seq_addr_t)) 102 | (dest (:struct snd_seq_addr_t))) 103 | 104 | (cffi:defcstruct snd_seq_real_time_t 105 | (tv_sec :unsigned-int) 106 | (tv_nsec :unsigned-int)) 107 | 108 | (cffi:defcunion snd_seq_timestamp_t 109 | (tick :unsigned-int) 110 | (time (:struct snd_seq_real_time_t))) 111 | 112 | (cl:defconstant SND_SEQ_TIME_STAMP_TICK (cl:ash 0 0)) 113 | 114 | (cl:defconstant SND_SEQ_TIME_STAMP_REAL (cl:ash 1 0)) 115 | 116 | (cl:defconstant SND_SEQ_TIME_STAMP_MASK (cl:ash 1 0)) 117 | 118 | (cl:defconstant SND_SEQ_TIME_MODE_ABS (cl:ash 0 1)) 119 | 120 | (cl:defconstant SND_SEQ_TIME_MODE_REL (cl:ash 1 1)) 121 | 122 | (cl:defconstant SND_SEQ_TIME_MODE_MASK (cl:ash 1 1)) 123 | 124 | (cl:defconstant SND_SEQ_EVENT_LENGTH_FIXED (cl:ash 0 2)) 125 | 126 | (cl:defconstant SND_SEQ_EVENT_LENGTH_VARIABLE (cl:ash 1 2)) 127 | 128 | (cl:defconstant SND_SEQ_EVENT_LENGTH_VARUSR (cl:ash 2 2)) 129 | 130 | (cl:defconstant SND_SEQ_EVENT_LENGTH_MASK (cl:ash 3 2)) 131 | 132 | (cl:defconstant SND_SEQ_PRIORITY_NORMAL (cl:ash 0 4)) 133 | 134 | (cl:defconstant SND_SEQ_PRIORITY_HIGH (cl:ash 1 4)) 135 | 136 | (cl:defconstant SND_SEQ_PRIORITY_MASK (cl:ash 1 4)) 137 | 138 | (cffi:defcstruct snd_seq_ev_note_t 139 | (channel :unsigned-char) 140 | (note :unsigned-char) 141 | (velocity :unsigned-char) 142 | (off_velocity :unsigned-char) 143 | (duration :unsigned-int)) 144 | 145 | (cffi:defcstruct snd_seq_ev_ctrl_t 146 | (channel :unsigned-char) 147 | (param :unsigned-int) 148 | (value :int)) 149 | 150 | (cffi:defcstruct snd_seq_ev_raw8_t 151 | (d :pointer)) 152 | 153 | (cffi:defcstruct snd_seq_ev_raw32_t 154 | (d :pointer)) 155 | 156 | (cffi:defcstruct snd_seq_ev_ext_t 157 | (len :unsigned-int) 158 | (ptr :pointer)) 159 | 160 | (cffi:defcstruct snd_seq_result_t 161 | (event :int) 162 | (result :int)) 163 | 164 | (cffi:defcstruct snd_seq_queue_skew_t 165 | (value :unsigned-int) 166 | (base :unsigned-int)) 167 | 168 | (cffi:defcstruct snd_seq_ev_queue_control_t 169 | (queue :unsigned-char) 170 | (unused :pointer) 171 | (param :pointer)) 172 | 173 | (cffi:defcunion snd_seq_ev_queue_control_param 174 | (value :int) 175 | (time (:union snd_seq_timestamp_t)) 176 | (position :unsigned-int) 177 | (skew (:struct snd_seq_queue_skew_t)) 178 | (d32 :pointer) 179 | (d8 :pointer)) 180 | 181 | (cffi:defcunion snd_seq_event_data 182 | (note (:struct snd_seq_ev_note_t)) 183 | (control (:struct snd_seq_ev_ctrl_t)) 184 | (raw8 (:struct snd_seq_ev_raw8_t)) 185 | (raw32 (:struct snd_seq_ev_raw32_t)) 186 | (ext (:struct snd_seq_ev_ext_t)) 187 | (queue (:struct snd_seq_ev_queue_control_t)) 188 | (time (:union snd_seq_timestamp_t)) 189 | ;; (time :pointer) 190 | (addr (:struct snd_seq_addr_t)) 191 | (connect (:struct snd_seq_connect_t)) 192 | (result (:struct snd_seq_result_t))) 193 | 194 | (cffi:defcstruct snd_seq_event_t 195 | (type :unsigned-char) 196 | (flags :unsigned-char) 197 | (tag :unsigned-char) 198 | (queue :unsigned-char) 199 | (time (:union snd_seq_timestamp_t)) 200 | (source (:struct snd_seq_addr_t)) 201 | (dest (:struct snd_seq_addr_t)) 202 | (data (:union snd_seq_event_data)) 203 | ) 204 | 205 | (cl:defconstant SND_SEQ_OPEN_OUTPUT 1) 206 | 207 | (cl:defconstant SND_SEQ_OPEN_INPUT 2) 208 | 209 | (cl:defconstant SND_SEQ_OPEN_DUPLEX (cl:logior 1 2)) 210 | 211 | (cl:defconstant SND_SEQ_NONBLOCK #x0001) 212 | 213 | (cffi:defcenum snd_seq_type_t 214 | :SND_SEQ_TYPE_HW 215 | :SND_SEQ_TYPE_SHM 216 | :SND_SEQ_TYPE_INET) 217 | 218 | (cl:defconstant SND_SEQ_ADDRESS_UNKNOWN 253) 219 | 220 | (cl:defconstant SND_SEQ_ADDRESS_SUBSCRIBERS 254) 221 | 222 | (cl:defconstant SND_SEQ_ADDRESS_BROADCAST 255) 223 | 224 | (cl:defconstant SND_SEQ_CLIENT_SYSTEM 0) 225 | 226 | (cffi:defcfun ("snd_seq_open" snd_seq_open) :int 227 | (handle :pointer) 228 | (name :string) 229 | (streams :int) 230 | (mode :int)) 231 | 232 | (cffi:defcfun ("snd_seq_open_lconf" snd_seq_open_lconf) :int 233 | (handle :pointer) 234 | (name :string) 235 | (streams :int) 236 | (mode :int) 237 | (lconf :pointer)) 238 | 239 | (cffi:defcfun ("snd_seq_name" snd_seq_name) :string 240 | (seq :pointer)) 241 | 242 | (cffi:defcfun ("snd_seq_type" snd_seq_type) snd_seq_type_t 243 | (seq :pointer)) 244 | 245 | (cffi:defcfun ("snd_seq_close" snd_seq_close) :int 246 | (handle :pointer)) 247 | 248 | (cffi:defcfun ("snd_seq_poll_descriptors_count" snd_seq_poll_descriptors_count) :int 249 | (handle :pointer) 250 | (events :short)) 251 | 252 | (cffi:defcfun ("snd_seq_poll_descriptors" snd_seq_poll_descriptors) :int 253 | (handle :pointer) 254 | (pfds :pointer) 255 | (space :unsigned-int) 256 | (events :short)) 257 | 258 | (cffi:defcfun ("snd_seq_poll_descriptors_revents" snd_seq_poll_descriptors_revents) :int 259 | (seq :pointer) 260 | (pfds :pointer) 261 | (nfds :unsigned-int) 262 | (revents :pointer)) 263 | 264 | (cffi:defcfun ("snd_seq_nonblock" snd_seq_nonblock) :int 265 | (handle :pointer) 266 | (nonblock :int)) 267 | 268 | (cffi:defcfun ("snd_seq_client_id" snd_seq_client_id) :int 269 | (handle :pointer)) 270 | 271 | (cffi:defcfun ("snd_seq_get_output_buffer_size" snd_seq_get_output_buffer_size) :pointer 272 | (handle :pointer)) 273 | 274 | (cffi:defcfun ("snd_seq_get_input_buffer_size" snd_seq_get_input_buffer_size) :pointer 275 | (handle :pointer)) 276 | 277 | (cffi:defcfun ("snd_seq_set_output_buffer_size" snd_seq_set_output_buffer_size) :int 278 | (handle :pointer) 279 | (size :pointer)) 280 | 281 | (cffi:defcfun ("snd_seq_set_input_buffer_size" snd_seq_set_input_buffer_size) :int 282 | (handle :pointer) 283 | (size :pointer)) 284 | 285 | (cffi:defcfun ("snd_seq_system_info_sizeof" snd_seq_system_info_sizeof) :pointer) 286 | 287 | (cffi:defcfun ("snd_seq_system_info_malloc" snd_seq_system_info_malloc) :int 288 | (ptr :pointer)) 289 | 290 | (cffi:defcfun ("snd_seq_system_info_free" snd_seq_system_info_free) :void 291 | (ptr :pointer)) 292 | 293 | (cffi:defcfun ("snd_seq_system_info_copy" snd_seq_system_info_copy) :void 294 | (dst :pointer) 295 | (src :pointer)) 296 | 297 | (cffi:defcfun ("snd_seq_system_info_get_queues" snd_seq_system_info_get_queues) :int 298 | (info :pointer)) 299 | 300 | (cffi:defcfun ("snd_seq_system_info_get_clients" snd_seq_system_info_get_clients) :int 301 | (info :pointer)) 302 | 303 | (cffi:defcfun ("snd_seq_system_info_get_ports" snd_seq_system_info_get_ports) :int 304 | (info :pointer)) 305 | 306 | (cffi:defcfun ("snd_seq_system_info_get_channels" snd_seq_system_info_get_channels) :int 307 | (info :pointer)) 308 | 309 | (cffi:defcfun ("snd_seq_system_info_get_cur_clients" snd_seq_system_info_get_cur_clients) :int 310 | (info :pointer)) 311 | 312 | (cffi:defcfun ("snd_seq_system_info_get_cur_queues" snd_seq_system_info_get_cur_queues) :int 313 | (info :pointer)) 314 | 315 | (cffi:defcfun ("snd_seq_system_info" snd_seq_system_info) :int 316 | (handle :pointer) 317 | (info :pointer)) 318 | 319 | (cffi:defcenum snd_seq_client_type_t 320 | (:SND_SEQ_USER_CLIENT #.1) 321 | (:SND_SEQ_KERNEL_CLIENT #.2)) 322 | 323 | (cffi:defcfun ("snd_seq_client_info_sizeof" snd_seq_client_info_sizeof) :pointer) 324 | 325 | (cffi:defcfun ("snd_seq_client_info_malloc" snd_seq_client_info_malloc) :int 326 | (ptr :pointer)) 327 | 328 | (cffi:defcfun ("snd_seq_client_info_free" snd_seq_client_info_free) :void 329 | (ptr :pointer)) 330 | 331 | (cffi:defcfun ("snd_seq_client_info_copy" snd_seq_client_info_copy) :void 332 | (dst :pointer) 333 | (src :pointer)) 334 | 335 | (cffi:defcfun ("snd_seq_client_info_get_client" snd_seq_client_info_get_client) :int 336 | (info :pointer)) 337 | 338 | (cffi:defcfun ("snd_seq_client_info_get_type" snd_seq_client_info_get_type) snd_seq_client_type_t 339 | (info :pointer)) 340 | 341 | (cffi:defcfun ("snd_seq_client_info_get_name" snd_seq_client_info_get_name) :string 342 | (info :pointer)) 343 | 344 | (cffi:defcfun ("snd_seq_client_info_get_broadcast_filter" snd_seq_client_info_get_broadcast_filter) :int 345 | (info :pointer)) 346 | 347 | (cffi:defcfun ("snd_seq_client_info_get_error_bounce" snd_seq_client_info_get_error_bounce) :int 348 | (info :pointer)) 349 | 350 | (cffi:defcfun ("snd_seq_client_info_get_event_filter" snd_seq_client_info_get_event_filter) :pointer 351 | (info :pointer)) 352 | 353 | (cffi:defcfun ("snd_seq_client_info_get_num_ports" snd_seq_client_info_get_num_ports) :int 354 | (info :pointer)) 355 | 356 | (cffi:defcfun ("snd_seq_client_info_get_event_lost" snd_seq_client_info_get_event_lost) :int 357 | (info :pointer)) 358 | 359 | (cffi:defcfun ("snd_seq_client_info_set_client" snd_seq_client_info_set_client) :void 360 | (info :pointer) 361 | (client :int)) 362 | 363 | (cffi:defcfun ("snd_seq_client_info_set_name" snd_seq_client_info_set_name) :void 364 | (info :pointer) 365 | (name :string)) 366 | 367 | (cffi:defcfun ("snd_seq_client_info_set_broadcast_filter" snd_seq_client_info_set_broadcast_filter) :void 368 | (info :pointer) 369 | (val :int)) 370 | 371 | (cffi:defcfun ("snd_seq_client_info_set_error_bounce" snd_seq_client_info_set_error_bounce) :void 372 | (info :pointer) 373 | (val :int)) 374 | 375 | (cffi:defcfun ("snd_seq_client_info_set_event_filter" snd_seq_client_info_set_event_filter) :void 376 | (info :pointer) 377 | (filter :pointer)) 378 | 379 | (cffi:defcfun ("snd_seq_client_info_event_filter_clear" snd_seq_client_info_event_filter_clear) :void 380 | (info :pointer)) 381 | 382 | (cffi:defcfun ("snd_seq_client_info_event_filter_add" snd_seq_client_info_event_filter_add) :void 383 | (info :pointer) 384 | (event_type :int)) 385 | 386 | (cffi:defcfun ("snd_seq_client_info_event_filter_del" snd_seq_client_info_event_filter_del) :void 387 | (info :pointer) 388 | (event_type :int)) 389 | 390 | (cffi:defcfun ("snd_seq_client_info_event_filter_check" snd_seq_client_info_event_filter_check) :int 391 | (info :pointer) 392 | (event_type :int)) 393 | 394 | (cffi:defcfun ("snd_seq_get_client_info" snd_seq_get_client_info) :int 395 | (handle :pointer) 396 | (info :pointer)) 397 | 398 | (cffi:defcfun ("snd_seq_get_any_client_info" snd_seq_get_any_client_info) :int 399 | (handle :pointer) 400 | (client :int) 401 | (info :pointer)) 402 | 403 | (cffi:defcfun ("snd_seq_set_client_info" snd_seq_set_client_info) :int 404 | (handle :pointer) 405 | (info :pointer)) 406 | 407 | (cffi:defcfun ("snd_seq_query_next_client" snd_seq_query_next_client) :int 408 | (handle :pointer) 409 | (info :pointer)) 410 | 411 | (cffi:defcfun ("snd_seq_client_pool_sizeof" snd_seq_client_pool_sizeof) :pointer) 412 | 413 | (cffi:defcfun ("snd_seq_client_pool_malloc" snd_seq_client_pool_malloc) :int 414 | (ptr :pointer)) 415 | 416 | (cffi:defcfun ("snd_seq_client_pool_free" snd_seq_client_pool_free) :void 417 | (ptr :pointer)) 418 | 419 | (cffi:defcfun ("snd_seq_client_pool_copy" snd_seq_client_pool_copy) :void 420 | (dst :pointer) 421 | (src :pointer)) 422 | 423 | (cffi:defcfun ("snd_seq_client_pool_get_client" snd_seq_client_pool_get_client) :int 424 | (info :pointer)) 425 | 426 | (cffi:defcfun ("snd_seq_client_pool_get_output_pool" snd_seq_client_pool_get_output_pool) :pointer 427 | (info :pointer)) 428 | 429 | (cffi:defcfun ("snd_seq_client_pool_get_input_pool" snd_seq_client_pool_get_input_pool) :pointer 430 | (info :pointer)) 431 | 432 | (cffi:defcfun ("snd_seq_client_pool_get_output_room" snd_seq_client_pool_get_output_room) :pointer 433 | (info :pointer)) 434 | 435 | (cffi:defcfun ("snd_seq_client_pool_get_output_free" snd_seq_client_pool_get_output_free) :pointer 436 | (info :pointer)) 437 | 438 | (cffi:defcfun ("snd_seq_client_pool_get_input_free" snd_seq_client_pool_get_input_free) :pointer 439 | (info :pointer)) 440 | 441 | (cffi:defcfun ("snd_seq_client_pool_set_output_pool" snd_seq_client_pool_set_output_pool) :void 442 | (info :pointer) 443 | (size :pointer)) 444 | 445 | (cffi:defcfun ("snd_seq_client_pool_set_input_pool" snd_seq_client_pool_set_input_pool) :void 446 | (info :pointer) 447 | (size :pointer)) 448 | 449 | (cffi:defcfun ("snd_seq_client_pool_set_output_room" snd_seq_client_pool_set_output_room) :void 450 | (info :pointer) 451 | (size :pointer)) 452 | 453 | (cffi:defcfun ("snd_seq_get_client_pool" snd_seq_get_client_pool) :int 454 | (handle :pointer) 455 | (info :pointer)) 456 | 457 | (cffi:defcfun ("snd_seq_set_client_pool" snd_seq_set_client_pool) :int 458 | (handle :pointer) 459 | (info :pointer)) 460 | 461 | (cl:defconstant SND_SEQ_PORT_SYSTEM_TIMER 0) 462 | 463 | (cl:defconstant SND_SEQ_PORT_SYSTEM_ANNOUNCE 1) 464 | 465 | (cl:defconstant SND_SEQ_PORT_CAP_READ (cl:ash 1 0)) 466 | 467 | (cl:defconstant SND_SEQ_PORT_CAP_WRITE (cl:ash 1 1)) 468 | 469 | (cl:defconstant SND_SEQ_PORT_CAP_SYNC_READ (cl:ash 1 2)) 470 | 471 | (cl:defconstant SND_SEQ_PORT_CAP_SYNC_WRITE (cl:ash 1 3)) 472 | 473 | (cl:defconstant SND_SEQ_PORT_CAP_DUPLEX (cl:ash 1 4)) 474 | 475 | (cl:defconstant SND_SEQ_PORT_CAP_SUBS_READ (cl:ash 1 5)) 476 | 477 | (cl:defconstant SND_SEQ_PORT_CAP_SUBS_WRITE (cl:ash 1 6)) 478 | 479 | (cl:defconstant SND_SEQ_PORT_CAP_NO_EXPORT (cl:ash 1 7)) 480 | 481 | (cl:defconstant SND_SEQ_PORT_TYPE_SPECIFIC (cl:ash 1 0)) 482 | 483 | (cl:defconstant SND_SEQ_PORT_TYPE_MIDI_GENERIC (cl:ash 1 1)) 484 | 485 | (cl:defconstant SND_SEQ_PORT_TYPE_MIDI_GM (cl:ash 1 2)) 486 | 487 | (cl:defconstant SND_SEQ_PORT_TYPE_MIDI_GS (cl:ash 1 3)) 488 | 489 | (cl:defconstant SND_SEQ_PORT_TYPE_MIDI_XG (cl:ash 1 4)) 490 | 491 | (cl:defconstant SND_SEQ_PORT_TYPE_MIDI_MT32 (cl:ash 1 5)) 492 | 493 | (cl:defconstant SND_SEQ_PORT_TYPE_MIDI_GM2 (cl:ash 1 6)) 494 | 495 | (cl:defconstant SND_SEQ_PORT_TYPE_SYNTH (cl:ash 1 10)) 496 | 497 | (cl:defconstant SND_SEQ_PORT_TYPE_DIRECT_SAMPLE (cl:ash 1 11)) 498 | 499 | (cl:defconstant SND_SEQ_PORT_TYPE_SAMPLE (cl:ash 1 12)) 500 | 501 | (cl:defconstant SND_SEQ_PORT_TYPE_HARDWARE (cl:ash 1 16)) 502 | 503 | (cl:defconstant SND_SEQ_PORT_TYPE_SOFTWARE (cl:ash 1 17)) 504 | 505 | (cl:defconstant SND_SEQ_PORT_TYPE_SYNTHESIZER (cl:ash 1 18)) 506 | 507 | (cl:defconstant SND_SEQ_PORT_TYPE_PORT (cl:ash 1 19)) 508 | 509 | (cl:defconstant SND_SEQ_PORT_TYPE_APPLICATION (cl:ash 1 20)) 510 | 511 | (cffi:defcfun ("snd_seq_port_info_sizeof" snd_seq_port_info_sizeof) :pointer) 512 | 513 | (cffi:defcfun ("snd_seq_port_info_malloc" snd_seq_port_info_malloc) :int 514 | (ptr :pointer)) 515 | 516 | (cffi:defcfun ("snd_seq_port_info_free" snd_seq_port_info_free) :void 517 | (ptr :pointer)) 518 | 519 | (cffi:defcfun ("snd_seq_port_info_copy" snd_seq_port_info_copy) :void 520 | (dst :pointer) 521 | (src :pointer)) 522 | 523 | (cffi:defcfun ("snd_seq_port_info_get_client" snd_seq_port_info_get_client) :int 524 | (info :pointer)) 525 | 526 | (cffi:defcfun ("snd_seq_port_info_get_port" snd_seq_port_info_get_port) :int 527 | (info :pointer)) 528 | 529 | (cffi:defcfun ("snd_seq_port_info_get_addr" snd_seq_port_info_get_addr) :pointer 530 | (info :pointer)) 531 | 532 | (cffi:defcfun ("snd_seq_port_info_get_name" snd_seq_port_info_get_name) :string 533 | (info :pointer)) 534 | 535 | (cffi:defcfun ("snd_seq_port_info_get_capability" snd_seq_port_info_get_capability) :unsigned-int 536 | (info :pointer)) 537 | 538 | (cffi:defcfun ("snd_seq_port_info_get_type" snd_seq_port_info_get_type) :unsigned-int 539 | (info :pointer)) 540 | 541 | (cffi:defcfun ("snd_seq_port_info_get_midi_channels" snd_seq_port_info_get_midi_channels) :int 542 | (info :pointer)) 543 | 544 | (cffi:defcfun ("snd_seq_port_info_get_midi_voices" snd_seq_port_info_get_midi_voices) :int 545 | (info :pointer)) 546 | 547 | (cffi:defcfun ("snd_seq_port_info_get_synth_voices" snd_seq_port_info_get_synth_voices) :int 548 | (info :pointer)) 549 | 550 | (cffi:defcfun ("snd_seq_port_info_get_read_use" snd_seq_port_info_get_read_use) :int 551 | (info :pointer)) 552 | 553 | (cffi:defcfun ("snd_seq_port_info_get_write_use" snd_seq_port_info_get_write_use) :int 554 | (info :pointer)) 555 | 556 | (cffi:defcfun ("snd_seq_port_info_get_port_specified" snd_seq_port_info_get_port_specified) :int 557 | (info :pointer)) 558 | 559 | (cffi:defcfun ("snd_seq_port_info_get_timestamping" snd_seq_port_info_get_timestamping) :int 560 | (info :pointer)) 561 | 562 | (cffi:defcfun ("snd_seq_port_info_get_timestamp_real" snd_seq_port_info_get_timestamp_real) :int 563 | (info :pointer)) 564 | 565 | (cffi:defcfun ("snd_seq_port_info_get_timestamp_queue" snd_seq_port_info_get_timestamp_queue) :int 566 | (info :pointer)) 567 | 568 | (cffi:defcfun ("snd_seq_port_info_set_client" snd_seq_port_info_set_client) :void 569 | (info :pointer) 570 | (client :int)) 571 | 572 | (cffi:defcfun ("snd_seq_port_info_set_port" snd_seq_port_info_set_port) :void 573 | (info :pointer) 574 | (port :int)) 575 | 576 | (cffi:defcfun ("snd_seq_port_info_set_addr" snd_seq_port_info_set_addr) :void 577 | (info :pointer) 578 | (addr :pointer)) 579 | 580 | (cffi:defcfun ("snd_seq_port_info_set_name" snd_seq_port_info_set_name) :void 581 | (info :pointer) 582 | (name :string)) 583 | 584 | (cffi:defcfun ("snd_seq_port_info_set_capability" snd_seq_port_info_set_capability) :void 585 | (info :pointer) 586 | (capability :unsigned-int)) 587 | 588 | (cffi:defcfun ("snd_seq_port_info_set_type" snd_seq_port_info_set_type) :void 589 | (info :pointer) 590 | (type :unsigned-int)) 591 | 592 | (cffi:defcfun ("snd_seq_port_info_set_midi_channels" snd_seq_port_info_set_midi_channels) :void 593 | (info :pointer) 594 | (channels :int)) 595 | 596 | (cffi:defcfun ("snd_seq_port_info_set_midi_voices" snd_seq_port_info_set_midi_voices) :void 597 | (info :pointer) 598 | (voices :int)) 599 | 600 | (cffi:defcfun ("snd_seq_port_info_set_synth_voices" snd_seq_port_info_set_synth_voices) :void 601 | (info :pointer) 602 | (voices :int)) 603 | 604 | (cffi:defcfun ("snd_seq_port_info_set_port_specified" snd_seq_port_info_set_port_specified) :void 605 | (info :pointer) 606 | (val :int)) 607 | 608 | (cffi:defcfun ("snd_seq_port_info_set_timestamping" snd_seq_port_info_set_timestamping) :void 609 | (info :pointer) 610 | (enable :int)) 611 | 612 | (cffi:defcfun ("snd_seq_port_info_set_timestamp_real" snd_seq_port_info_set_timestamp_real) :void 613 | (info :pointer) 614 | (realtime :int)) 615 | 616 | (cffi:defcfun ("snd_seq_port_info_set_timestamp_queue" snd_seq_port_info_set_timestamp_queue) :void 617 | (info :pointer) 618 | (queue :int)) 619 | 620 | (cffi:defcfun ("snd_seq_create_port" snd_seq_create_port) :int 621 | (handle :pointer) 622 | (info :pointer)) 623 | 624 | (cffi:defcfun ("snd_seq_delete_port" snd_seq_delete_port) :int 625 | (handle :pointer) 626 | (port :int)) 627 | 628 | (cffi:defcfun ("snd_seq_get_port_info" snd_seq_get_port_info) :int 629 | (handle :pointer) 630 | (port :int) 631 | (info :pointer)) 632 | 633 | (cffi:defcfun ("snd_seq_get_any_port_info" snd_seq_get_any_port_info) :int 634 | (handle :pointer) 635 | (client :int) 636 | (port :int) 637 | (info :pointer)) 638 | 639 | (cffi:defcfun ("snd_seq_set_port_info" snd_seq_set_port_info) :int 640 | (handle :pointer) 641 | (port :int) 642 | (info :pointer)) 643 | 644 | (cffi:defcfun ("snd_seq_query_next_port" snd_seq_query_next_port) :int 645 | (handle :pointer) 646 | (info :pointer)) 647 | 648 | (cffi:defcfun ("snd_seq_port_subscribe_sizeof" snd_seq_port_subscribe_sizeof) :pointer) 649 | 650 | (cffi:defcfun ("snd_seq_port_subscribe_malloc" snd_seq_port_subscribe_malloc) :int 651 | (ptr :pointer)) 652 | 653 | (cffi:defcfun ("snd_seq_port_subscribe_free" snd_seq_port_subscribe_free) :void 654 | (ptr :pointer)) 655 | 656 | (cffi:defcfun ("snd_seq_port_subscribe_copy" snd_seq_port_subscribe_copy) :void 657 | (dst :pointer) 658 | (src :pointer)) 659 | 660 | (cffi:defcfun ("snd_seq_port_subscribe_get_sender" snd_seq_port_subscribe_get_sender) :pointer 661 | (info :pointer)) 662 | 663 | (cffi:defcfun ("snd_seq_port_subscribe_get_dest" snd_seq_port_subscribe_get_dest) :pointer 664 | (info :pointer)) 665 | 666 | (cffi:defcfun ("snd_seq_port_subscribe_get_queue" snd_seq_port_subscribe_get_queue) :int 667 | (info :pointer)) 668 | 669 | (cffi:defcfun ("snd_seq_port_subscribe_get_exclusive" snd_seq_port_subscribe_get_exclusive) :int 670 | (info :pointer)) 671 | 672 | (cffi:defcfun ("snd_seq_port_subscribe_get_time_update" snd_seq_port_subscribe_get_time_update) :int 673 | (info :pointer)) 674 | 675 | (cffi:defcfun ("snd_seq_port_subscribe_get_time_real" snd_seq_port_subscribe_get_time_real) :int 676 | (info :pointer)) 677 | 678 | (cffi:defcfun ("snd_seq_port_subscribe_set_sender" snd_seq_port_subscribe_set_sender) :void 679 | (info :pointer) 680 | (addr :pointer)) 681 | 682 | (cffi:defcfun ("snd_seq_port_subscribe_set_dest" snd_seq_port_subscribe_set_dest) :void 683 | (info :pointer) 684 | (addr :pointer)) 685 | 686 | (cffi:defcfun ("snd_seq_port_subscribe_set_queue" snd_seq_port_subscribe_set_queue) :void 687 | (info :pointer) 688 | (q :int)) 689 | 690 | (cffi:defcfun ("snd_seq_port_subscribe_set_exclusive" snd_seq_port_subscribe_set_exclusive) :void 691 | (info :pointer) 692 | (val :int)) 693 | 694 | (cffi:defcfun ("snd_seq_port_subscribe_set_time_update" snd_seq_port_subscribe_set_time_update) :void 695 | (info :pointer) 696 | (val :int)) 697 | 698 | (cffi:defcfun ("snd_seq_port_subscribe_set_time_real" snd_seq_port_subscribe_set_time_real) :void 699 | (info :pointer) 700 | (val :int)) 701 | 702 | (cffi:defcfun ("snd_seq_get_port_subscription" snd_seq_get_port_subscription) :int 703 | (handle :pointer) 704 | (sub :pointer)) 705 | 706 | (cffi:defcfun ("snd_seq_subscribe_port" snd_seq_subscribe_port) :int 707 | (handle :pointer) 708 | (sub :pointer)) 709 | 710 | (cffi:defcfun ("snd_seq_unsubscribe_port" snd_seq_unsubscribe_port) :int 711 | (handle :pointer) 712 | (sub :pointer)) 713 | 714 | (cffi:defcenum snd_seq_query_subs_type_t 715 | :SND_SEQ_QUERY_SUBS_READ 716 | :SND_SEQ_QUERY_SUBS_WRITE) 717 | 718 | (cffi:defcfun ("snd_seq_query_subscribe_sizeof" snd_seq_query_subscribe_sizeof) :pointer) 719 | 720 | (cffi:defcfun ("snd_seq_query_subscribe_malloc" snd_seq_query_subscribe_malloc) :int 721 | (ptr :pointer)) 722 | 723 | (cffi:defcfun ("snd_seq_query_subscribe_free" snd_seq_query_subscribe_free) :void 724 | (ptr :pointer)) 725 | 726 | (cffi:defcfun ("snd_seq_query_subscribe_copy" snd_seq_query_subscribe_copy) :void 727 | (dst :pointer) 728 | (src :pointer)) 729 | 730 | (cffi:defcfun ("snd_seq_query_subscribe_get_client" snd_seq_query_subscribe_get_client) :int 731 | (info :pointer)) 732 | 733 | (cffi:defcfun ("snd_seq_query_subscribe_get_port" snd_seq_query_subscribe_get_port) :int 734 | (info :pointer)) 735 | 736 | (cffi:defcfun ("snd_seq_query_subscribe_get_root" snd_seq_query_subscribe_get_root) :pointer 737 | (info :pointer)) 738 | 739 | (cffi:defcfun ("snd_seq_query_subscribe_get_type" snd_seq_query_subscribe_get_type) snd_seq_query_subs_type_t 740 | (info :pointer)) 741 | 742 | (cffi:defcfun ("snd_seq_query_subscribe_get_index" snd_seq_query_subscribe_get_index) :int 743 | (info :pointer)) 744 | 745 | (cffi:defcfun ("snd_seq_query_subscribe_get_num_subs" snd_seq_query_subscribe_get_num_subs) :int 746 | (info :pointer)) 747 | 748 | (cffi:defcfun ("snd_seq_query_subscribe_get_addr" snd_seq_query_subscribe_get_addr) :pointer 749 | (info :pointer)) 750 | 751 | (cffi:defcfun ("snd_seq_query_subscribe_get_queue" snd_seq_query_subscribe_get_queue) :int 752 | (info :pointer)) 753 | 754 | (cffi:defcfun ("snd_seq_query_subscribe_get_exclusive" snd_seq_query_subscribe_get_exclusive) :int 755 | (info :pointer)) 756 | 757 | (cffi:defcfun ("snd_seq_query_subscribe_get_time_update" snd_seq_query_subscribe_get_time_update) :int 758 | (info :pointer)) 759 | 760 | (cffi:defcfun ("snd_seq_query_subscribe_get_time_real" snd_seq_query_subscribe_get_time_real) :int 761 | (info :pointer)) 762 | 763 | (cffi:defcfun ("snd_seq_query_subscribe_set_client" snd_seq_query_subscribe_set_client) :void 764 | (info :pointer) 765 | (client :int)) 766 | 767 | (cffi:defcfun ("snd_seq_query_subscribe_set_port" snd_seq_query_subscribe_set_port) :void 768 | (info :pointer) 769 | (port :int)) 770 | 771 | (cffi:defcfun ("snd_seq_query_subscribe_set_root" snd_seq_query_subscribe_set_root) :void 772 | (info :pointer) 773 | (addr :pointer)) 774 | 775 | (cffi:defcfun ("snd_seq_query_subscribe_set_type" snd_seq_query_subscribe_set_type) :void 776 | (info :pointer) 777 | (type snd_seq_query_subs_type_t)) 778 | 779 | (cffi:defcfun ("snd_seq_query_subscribe_set_index" snd_seq_query_subscribe_set_index) :void 780 | (info :pointer) 781 | (_index :int)) 782 | 783 | (cffi:defcfun ("snd_seq_query_port_subscribers" snd_seq_query_port_subscribers) :int 784 | (seq :pointer) 785 | (subs :pointer)) 786 | 787 | (cl:defconstant SND_SEQ_QUEUE_DIRECT 253) 788 | 789 | (cffi:defcfun ("snd_seq_queue_info_sizeof" snd_seq_queue_info_sizeof) :pointer) 790 | 791 | (cffi:defcfun ("snd_seq_queue_info_malloc" snd_seq_queue_info_malloc) :int 792 | (ptr :pointer)) 793 | 794 | (cffi:defcfun ("snd_seq_queue_info_free" snd_seq_queue_info_free) :void 795 | (ptr :pointer)) 796 | 797 | (cffi:defcfun ("snd_seq_queue_info_copy" snd_seq_queue_info_copy) :void 798 | (dst :pointer) 799 | (src :pointer)) 800 | 801 | (cffi:defcfun ("snd_seq_queue_info_get_queue" snd_seq_queue_info_get_queue) :int 802 | (info :pointer)) 803 | 804 | (cffi:defcfun ("snd_seq_queue_info_get_name" snd_seq_queue_info_get_name) :string 805 | (info :pointer)) 806 | 807 | (cffi:defcfun ("snd_seq_queue_info_get_owner" snd_seq_queue_info_get_owner) :int 808 | (info :pointer)) 809 | 810 | (cffi:defcfun ("snd_seq_queue_info_get_locked" snd_seq_queue_info_get_locked) :int 811 | (info :pointer)) 812 | 813 | (cffi:defcfun ("snd_seq_queue_info_get_flags" snd_seq_queue_info_get_flags) :unsigned-int 814 | (info :pointer)) 815 | 816 | (cffi:defcfun ("snd_seq_queue_info_set_name" snd_seq_queue_info_set_name) :void 817 | (info :pointer) 818 | (name :string)) 819 | 820 | (cffi:defcfun ("snd_seq_queue_info_set_owner" snd_seq_queue_info_set_owner) :void 821 | (info :pointer) 822 | (owner :int)) 823 | 824 | (cffi:defcfun ("snd_seq_queue_info_set_locked" snd_seq_queue_info_set_locked) :void 825 | (info :pointer) 826 | (locked :int)) 827 | 828 | (cffi:defcfun ("snd_seq_queue_info_set_flags" snd_seq_queue_info_set_flags) :void 829 | (info :pointer) 830 | (flags :unsigned-int)) 831 | 832 | (cffi:defcfun ("snd_seq_create_queue" snd_seq_create_queue) :int 833 | (seq :pointer) 834 | (info :pointer)) 835 | 836 | (cffi:defcfun ("snd_seq_alloc_named_queue" snd_seq_alloc_named_queue) :int 837 | (seq :pointer) 838 | (name :string)) 839 | 840 | (cffi:defcfun ("snd_seq_alloc_queue" snd_seq_alloc_queue) :int 841 | (handle :pointer)) 842 | 843 | (cffi:defcfun ("snd_seq_free_queue" snd_seq_free_queue) :int 844 | (handle :pointer) 845 | (q :int)) 846 | 847 | (cffi:defcfun ("snd_seq_get_queue_info" snd_seq_get_queue_info) :int 848 | (seq :pointer) 849 | (q :int) 850 | (info :pointer)) 851 | 852 | (cffi:defcfun ("snd_seq_set_queue_info" snd_seq_set_queue_info) :int 853 | (seq :pointer) 854 | (q :int) 855 | (info :pointer)) 856 | 857 | (cffi:defcfun ("snd_seq_query_named_queue" snd_seq_query_named_queue) :int 858 | (seq :pointer) 859 | (name :string)) 860 | 861 | (cffi:defcfun ("snd_seq_get_queue_usage" snd_seq_get_queue_usage) :int 862 | (handle :pointer) 863 | (q :int)) 864 | 865 | (cffi:defcfun ("snd_seq_set_queue_usage" snd_seq_set_queue_usage) :int 866 | (handle :pointer) 867 | (q :int) 868 | (used :int)) 869 | 870 | (cffi:defcfun ("snd_seq_queue_status_sizeof" snd_seq_queue_status_sizeof) :pointer) 871 | 872 | (cffi:defcfun ("snd_seq_queue_status_malloc" snd_seq_queue_status_malloc) :int 873 | (ptr :pointer)) 874 | 875 | (cffi:defcfun ("snd_seq_queue_status_free" snd_seq_queue_status_free) :void 876 | (ptr :pointer)) 877 | 878 | (cffi:defcfun ("snd_seq_queue_status_copy" snd_seq_queue_status_copy) :void 879 | (dst :pointer) 880 | (src :pointer)) 881 | 882 | (cffi:defcfun ("snd_seq_queue_status_get_queue" snd_seq_queue_status_get_queue) :int 883 | (info :pointer)) 884 | 885 | (cffi:defcfun ("snd_seq_queue_status_get_events" snd_seq_queue_status_get_events) :int 886 | (info :pointer)) 887 | 888 | (cffi:defcfun ("snd_seq_queue_status_get_tick_time" snd_seq_queue_status_get_tick_time) :unsigned-int 889 | (info :pointer)) 890 | 891 | (cffi:defcfun ("snd_seq_queue_status_get_real_time" snd_seq_queue_status_get_real_time) :pointer 892 | (info :pointer)) 893 | 894 | (cffi:defcfun ("snd_seq_queue_status_get_status" snd_seq_queue_status_get_status) :unsigned-int 895 | (info :pointer)) 896 | 897 | (cffi:defcfun ("snd_seq_get_queue_status" snd_seq_get_queue_status) :int 898 | (handle :pointer) 899 | (q :int) 900 | (status :pointer)) 901 | 902 | (cffi:defcfun ("snd_seq_queue_tempo_sizeof" snd_seq_queue_tempo_sizeof) :pointer) 903 | 904 | (cffi:defcfun ("snd_seq_queue_tempo_malloc" snd_seq_queue_tempo_malloc) :int 905 | (ptr :pointer)) 906 | 907 | (cffi:defcfun ("snd_seq_queue_tempo_free" snd_seq_queue_tempo_free) :void 908 | (ptr :pointer)) 909 | 910 | (cffi:defcfun ("snd_seq_queue_tempo_copy" snd_seq_queue_tempo_copy) :void 911 | (dst :pointer) 912 | (src :pointer)) 913 | 914 | (cffi:defcfun ("snd_seq_queue_tempo_get_queue" snd_seq_queue_tempo_get_queue) :int 915 | (info :pointer)) 916 | 917 | (cffi:defcfun ("snd_seq_queue_tempo_get_tempo" snd_seq_queue_tempo_get_tempo) :unsigned-int 918 | (info :pointer)) 919 | 920 | (cffi:defcfun ("snd_seq_queue_tempo_get_ppq" snd_seq_queue_tempo_get_ppq) :int 921 | (info :pointer)) 922 | 923 | (cffi:defcfun ("snd_seq_queue_tempo_get_skew" snd_seq_queue_tempo_get_skew) :unsigned-int 924 | (info :pointer)) 925 | 926 | (cffi:defcfun ("snd_seq_queue_tempo_get_skew_base" snd_seq_queue_tempo_get_skew_base) :unsigned-int 927 | (info :pointer)) 928 | 929 | (cffi:defcfun ("snd_seq_queue_tempo_set_tempo" snd_seq_queue_tempo_set_tempo) :void 930 | (info :pointer) 931 | (tempo :unsigned-int)) 932 | 933 | (cffi:defcfun ("snd_seq_queue_tempo_set_ppq" snd_seq_queue_tempo_set_ppq) :void 934 | (info :pointer) 935 | (ppq :int)) 936 | 937 | (cffi:defcfun ("snd_seq_queue_tempo_set_skew" snd_seq_queue_tempo_set_skew) :void 938 | (info :pointer) 939 | (skew :unsigned-int)) 940 | 941 | (cffi:defcfun ("snd_seq_queue_tempo_set_skew_base" snd_seq_queue_tempo_set_skew_base) :void 942 | (info :pointer) 943 | (base :unsigned-int)) 944 | 945 | (cffi:defcfun ("snd_seq_get_queue_tempo" snd_seq_get_queue_tempo) :int 946 | (handle :pointer) 947 | (q :int) 948 | (tempo :pointer)) 949 | 950 | (cffi:defcfun ("snd_seq_set_queue_tempo" snd_seq_set_queue_tempo) :int 951 | (handle :pointer) 952 | (q :int) 953 | (tempo :pointer)) 954 | 955 | (cffi:defcenum snd_seq_queue_timer_type_t 956 | (:SND_SEQ_TIMER_ALSA #.0) 957 | (:SND_SEQ_TIMER_MIDI_CLOCK #.1) 958 | (:SND_SEQ_TIMER_MIDI_TICK #.2)) 959 | 960 | (cffi:defcfun ("snd_seq_queue_timer_sizeof" snd_seq_queue_timer_sizeof) :pointer) 961 | 962 | (cffi:defcfun ("snd_seq_queue_timer_malloc" snd_seq_queue_timer_malloc) :int 963 | (ptr :pointer)) 964 | 965 | (cffi:defcfun ("snd_seq_queue_timer_free" snd_seq_queue_timer_free) :void 966 | (ptr :pointer)) 967 | 968 | (cffi:defcfun ("snd_seq_queue_timer_copy" snd_seq_queue_timer_copy) :void 969 | (dst :pointer) 970 | (src :pointer)) 971 | 972 | (cffi:defcfun ("snd_seq_queue_timer_get_queue" snd_seq_queue_timer_get_queue) :int 973 | (info :pointer)) 974 | 975 | (cffi:defcfun ("snd_seq_queue_timer_get_type" snd_seq_queue_timer_get_type) snd_seq_queue_timer_type_t 976 | (info :pointer)) 977 | 978 | (cffi:defcfun ("snd_seq_queue_timer_get_id" snd_seq_queue_timer_get_id) :pointer 979 | (info :pointer)) 980 | 981 | (cffi:defcfun ("snd_seq_queue_timer_get_resolution" snd_seq_queue_timer_get_resolution) :unsigned-int 982 | (info :pointer)) 983 | 984 | (cffi:defcfun ("snd_seq_queue_timer_set_type" snd_seq_queue_timer_set_type) :void 985 | (info :pointer) 986 | (type snd_seq_queue_timer_type_t)) 987 | 988 | (cffi:defcfun ("snd_seq_queue_timer_set_id" snd_seq_queue_timer_set_id) :void 989 | (info :pointer) 990 | (id :pointer)) 991 | 992 | (cffi:defcfun ("snd_seq_queue_timer_set_resolution" snd_seq_queue_timer_set_resolution) :void 993 | (info :pointer) 994 | (resolution :unsigned-int)) 995 | 996 | (cffi:defcfun ("snd_seq_get_queue_timer" snd_seq_get_queue_timer) :int 997 | (handle :pointer) 998 | (q :int) 999 | (timer :pointer)) 1000 | 1001 | (cffi:defcfun ("snd_seq_set_queue_timer" snd_seq_set_queue_timer) :int 1002 | (handle :pointer) 1003 | (q :int) 1004 | (timer :pointer)) 1005 | 1006 | (cffi:defcfun ("snd_seq_free_event" snd_seq_free_event) :int 1007 | (ev :pointer)) 1008 | 1009 | (cffi:defcfun ("snd_seq_event_length" snd_seq_event_length) :pointer 1010 | (ev :pointer)) 1011 | 1012 | (cffi:defcfun ("snd_seq_event_output" snd_seq_event_output) :int 1013 | (handle :pointer) 1014 | (ev :pointer)) 1015 | 1016 | (cffi:defcfun ("snd_seq_event_output_buffer" snd_seq_event_output_buffer) :int 1017 | (handle :pointer) 1018 | (ev :pointer)) 1019 | 1020 | (cffi:defcfun ("snd_seq_event_output_direct" snd_seq_event_output_direct) :int 1021 | (handle :pointer) 1022 | (ev :pointer)) 1023 | 1024 | (cffi:defcfun ("snd_seq_event_input" snd_seq_event_input) :int 1025 | (handle :pointer) 1026 | (ev :pointer)) 1027 | 1028 | (cffi:defcfun ("snd_seq_event_input_pending" snd_seq_event_input_pending) :int 1029 | (seq :pointer) 1030 | (fetch_sequencer :int)) 1031 | 1032 | (cffi:defcfun ("snd_seq_drain_output" snd_seq_drain_output) :int 1033 | (handle :pointer)) 1034 | 1035 | (cffi:defcfun ("snd_seq_event_output_pending" snd_seq_event_output_pending) :int 1036 | (seq :pointer)) 1037 | 1038 | (cffi:defcfun ("snd_seq_extract_output" snd_seq_extract_output) :int 1039 | (handle :pointer) 1040 | (ev :pointer)) 1041 | 1042 | (cffi:defcfun ("snd_seq_drop_output" snd_seq_drop_output) :int 1043 | (handle :pointer)) 1044 | 1045 | (cffi:defcfun ("snd_seq_drop_output_buffer" snd_seq_drop_output_buffer) :int 1046 | (handle :pointer)) 1047 | 1048 | (cffi:defcfun ("snd_seq_drop_input" snd_seq_drop_input) :int 1049 | (handle :pointer)) 1050 | 1051 | (cffi:defcfun ("snd_seq_drop_input_buffer" snd_seq_drop_input_buffer) :int 1052 | (handle :pointer)) 1053 | 1054 | (cl:defconstant SND_SEQ_REMOVE_INPUT (cl:ash 1 0)) 1055 | 1056 | (cl:defconstant SND_SEQ_REMOVE_OUTPUT (cl:ash 1 1)) 1057 | 1058 | (cl:defconstant SND_SEQ_REMOVE_DEST (cl:ash 1 2)) 1059 | 1060 | (cl:defconstant SND_SEQ_REMOVE_DEST_CHANNEL (cl:ash 1 3)) 1061 | 1062 | (cl:defconstant SND_SEQ_REMOVE_TIME_BEFORE (cl:ash 1 4)) 1063 | 1064 | (cl:defconstant SND_SEQ_REMOVE_TIME_AFTER (cl:ash 1 5)) 1065 | 1066 | (cl:defconstant SND_SEQ_REMOVE_TIME_TICK (cl:ash 1 6)) 1067 | 1068 | (cl:defconstant SND_SEQ_REMOVE_EVENT_TYPE (cl:ash 1 7)) 1069 | 1070 | (cl:defconstant SND_SEQ_REMOVE_IGNORE_OFF (cl:ash 1 8)) 1071 | 1072 | (cl:defconstant SND_SEQ_REMOVE_TAG_MATCH (cl:ash 1 9)) 1073 | 1074 | (cffi:defcfun ("snd_seq_remove_events_sizeof" snd_seq_remove_events_sizeof) :pointer) 1075 | 1076 | (cffi:defcfun ("snd_seq_remove_events_malloc" snd_seq_remove_events_malloc) :int 1077 | (ptr :pointer)) 1078 | 1079 | (cffi:defcfun ("snd_seq_remove_events_free" snd_seq_remove_events_free) :void 1080 | (ptr :pointer)) 1081 | 1082 | (cffi:defcfun ("snd_seq_remove_events_copy" snd_seq_remove_events_copy) :void 1083 | (dst :pointer) 1084 | (src :pointer)) 1085 | 1086 | (cffi:defcfun ("snd_seq_remove_events_get_condition" snd_seq_remove_events_get_condition) :unsigned-int 1087 | (info :pointer)) 1088 | 1089 | (cffi:defcfun ("snd_seq_remove_events_get_queue" snd_seq_remove_events_get_queue) :int 1090 | (info :pointer)) 1091 | 1092 | (cffi:defcfun ("snd_seq_remove_events_get_time" snd_seq_remove_events_get_time) :pointer 1093 | (info :pointer)) 1094 | 1095 | (cffi:defcfun ("snd_seq_remove_events_get_dest" snd_seq_remove_events_get_dest) :pointer 1096 | (info :pointer)) 1097 | 1098 | (cffi:defcfun ("snd_seq_remove_events_get_channel" snd_seq_remove_events_get_channel) :int 1099 | (info :pointer)) 1100 | 1101 | (cffi:defcfun ("snd_seq_remove_events_get_event_type" snd_seq_remove_events_get_event_type) :int 1102 | (info :pointer)) 1103 | 1104 | (cffi:defcfun ("snd_seq_remove_events_get_tag" snd_seq_remove_events_get_tag) :int 1105 | (info :pointer)) 1106 | 1107 | (cffi:defcfun ("snd_seq_remove_events_set_condition" snd_seq_remove_events_set_condition) :void 1108 | (info :pointer) 1109 | (flags :unsigned-int)) 1110 | 1111 | (cffi:defcfun ("snd_seq_remove_events_set_queue" snd_seq_remove_events_set_queue) :void 1112 | (info :pointer) 1113 | (queue :int)) 1114 | 1115 | (cffi:defcfun ("snd_seq_remove_events_set_time" snd_seq_remove_events_set_time) :void 1116 | (info :pointer) 1117 | (time :pointer)) 1118 | 1119 | (cffi:defcfun ("snd_seq_remove_events_set_dest" snd_seq_remove_events_set_dest) :void 1120 | (info :pointer) 1121 | (addr :pointer)) 1122 | 1123 | (cffi:defcfun ("snd_seq_remove_events_set_channel" snd_seq_remove_events_set_channel) :void 1124 | (info :pointer) 1125 | (channel :int)) 1126 | 1127 | (cffi:defcfun ("snd_seq_remove_events_set_event_type" snd_seq_remove_events_set_event_type) :void 1128 | (info :pointer) 1129 | (type :int)) 1130 | 1131 | (cffi:defcfun ("snd_seq_remove_events_set_tag" snd_seq_remove_events_set_tag) :void 1132 | (info :pointer) 1133 | (tag :int)) 1134 | 1135 | (cffi:defcfun ("snd_seq_remove_events" snd_seq_remove_events) :int 1136 | (handle :pointer) 1137 | (info :pointer)) 1138 | 1139 | (cffi:defcfun ("snd_seq_set_bit" snd_seq_set_bit) :void 1140 | (nr :int) 1141 | (array :pointer)) 1142 | 1143 | (cffi:defcfun ("snd_seq_unset_bit" snd_seq_unset_bit) :void 1144 | (nr :int) 1145 | (array :pointer)) 1146 | 1147 | (cffi:defcfun ("snd_seq_change_bit" snd_seq_change_bit) :int 1148 | (nr :int) 1149 | (array :pointer)) 1150 | 1151 | (cffi:defcfun ("snd_seq_get_bit" snd_seq_get_bit) :int 1152 | (nr :int) 1153 | (array :pointer)) 1154 | 1155 | ;; (defanonenum 1156 | ;; SND_SEQ_EVFLG_RESULT 1157 | ;; SND_SEQ_EVFLG_NOTE 1158 | ;; SND_SEQ_EVFLG_CONTROL 1159 | ;; SND_SEQ_EVFLG_QUEUE 1160 | ;; SND_SEQ_EVFLG_SYSTEM 1161 | ;; SND_SEQ_EVFLG_MESSAGE 1162 | ;; SND_SEQ_EVFLG_CONNECTION 1163 | ;; SND_SEQ_EVFLG_SAMPLE 1164 | ;; SND_SEQ_EVFLG_USERS 1165 | ;; SND_SEQ_EVFLG_INSTR 1166 | ;; SND_SEQ_EVFLG_QUOTE 1167 | ;; SND_SEQ_EVFLG_NONE 1168 | ;; SND_SEQ_EVFLG_RAW 1169 | ;; SND_SEQ_EVFLG_FIXED 1170 | ;; SND_SEQ_EVFLG_VARIABLE 1171 | ;; SND_SEQ_EVFLG_VARUSR) 1172 | 1173 | ;; (defanonenum 1174 | ;; SND_SEQ_EVFLG_NOTE_ONEARG 1175 | ;; SND_SEQ_EVFLG_NOTE_TWOARG) 1176 | 1177 | ;; (defanonenum 1178 | ;; SND_SEQ_EVFLG_QUEUE_NOARG 1179 | ;; SND_SEQ_EVFLG_QUEUE_TICK 1180 | ;; SND_SEQ_EVFLG_QUEUE_TIME 1181 | ;; SND_SEQ_EVFLG_QUEUE_VALUE) 1182 | 1183 | (cffi:defcvar ("snd_seq_event_types" snd_seq_event_types) 1184 | :pointer) 1185 | 1186 | (cffi:defcfun ("snd_seq_control_queue" snd_seq_control_queue) :int 1187 | (seq :pointer) 1188 | (q :int) 1189 | (type :int) 1190 | (value :int) 1191 | (ev :pointer)) 1192 | 1193 | (cffi:defcfun ("snd_seq_create_simple_port" snd_seq_create_simple_port) :int 1194 | (seq :pointer) 1195 | (name :string) 1196 | (caps :unsigned-int) 1197 | (type :unsigned-int)) 1198 | 1199 | (cffi:defcfun ("snd_seq_delete_simple_port" snd_seq_delete_simple_port) :int 1200 | (seq :pointer) 1201 | (port :int)) 1202 | 1203 | (cffi:defcfun ("snd_seq_connect_from" snd_seq_connect_from) :int 1204 | (seq :pointer) 1205 | (my_port :int) 1206 | (src_client :int) 1207 | (src_port :int)) 1208 | 1209 | (cffi:defcfun ("snd_seq_connect_to" snd_seq_connect_to) :int 1210 | (seq :pointer) 1211 | (my_port :int) 1212 | (dest_client :int) 1213 | (dest_port :int)) 1214 | 1215 | (cffi:defcfun ("snd_seq_disconnect_from" snd_seq_disconnect_from) :int 1216 | (seq :pointer) 1217 | (my_port :int) 1218 | (src_client :int) 1219 | (src_port :int)) 1220 | 1221 | (cffi:defcfun ("snd_seq_disconnect_to" snd_seq_disconnect_to) :int 1222 | (seq :pointer) 1223 | (my_port :int) 1224 | (dest_client :int) 1225 | (dest_port :int)) 1226 | 1227 | (cffi:defcfun ("snd_seq_set_client_name" snd_seq_set_client_name) :int 1228 | (seq :pointer) 1229 | (name :string)) 1230 | 1231 | (cffi:defcfun ("snd_seq_set_client_event_filter" snd_seq_set_client_event_filter) :int 1232 | (seq :pointer) 1233 | (event_type :int)) 1234 | 1235 | (cffi:defcfun ("snd_seq_set_client_pool_output" snd_seq_set_client_pool_output) :int 1236 | (seq :pointer) 1237 | (size :pointer)) 1238 | 1239 | (cffi:defcfun ("snd_seq_set_client_pool_output_room" snd_seq_set_client_pool_output_room) :int 1240 | (seq :pointer) 1241 | (size :pointer)) 1242 | 1243 | (cffi:defcfun ("snd_seq_set_client_pool_input" snd_seq_set_client_pool_input) :int 1244 | (seq :pointer) 1245 | (size :pointer)) 1246 | 1247 | (cffi:defcfun ("snd_seq_sync_output_queue" snd_seq_sync_output_queue) :int 1248 | (seq :pointer)) 1249 | 1250 | (cffi:defcfun ("snd_seq_parse_address" snd_seq_parse_address) :int 1251 | (seq :pointer) 1252 | (addr :pointer) 1253 | (str :string)) 1254 | 1255 | (cffi:defcfun ("snd_seq_reset_pool_output" snd_seq_reset_pool_output) :int 1256 | (seq :pointer)) 1257 | 1258 | (cffi:defcfun ("snd_seq_reset_pool_input" snd_seq_reset_pool_input) :int 1259 | (seq :pointer)) 1260 | 1261 | (cffi:defcfun ("snd_midi_event_new" snd_midi_event_new) :int 1262 | (bufsize :pointer) 1263 | (rdev :pointer)) 1264 | 1265 | (cffi:defcfun ("snd_midi_event_resize_buffer" snd_midi_event_resize_buffer) :int 1266 | (dev :pointer) 1267 | (bufsize :pointer)) 1268 | 1269 | (cffi:defcfun ("snd_midi_event_free" snd_midi_event_free) :void 1270 | (dev :pointer)) 1271 | 1272 | (cffi:defcfun ("snd_midi_event_init" snd_midi_event_init) :void 1273 | (dev :pointer)) 1274 | 1275 | (cffi:defcfun ("snd_midi_event_reset_encode" snd_midi_event_reset_encode) :void 1276 | (dev :pointer)) 1277 | 1278 | (cffi:defcfun ("snd_midi_event_reset_decode" snd_midi_event_reset_decode) :void 1279 | (dev :pointer)) 1280 | 1281 | (cffi:defcfun ("snd_midi_event_no_status" snd_midi_event_no_status) :void 1282 | (dev :pointer) 1283 | (on :int)) 1284 | 1285 | (cffi:defcfun ("snd_midi_event_encode" snd_midi_event_encode) :long 1286 | (dev :pointer) 1287 | (buf :pointer) 1288 | (count :long) 1289 | (ev :pointer)) 1290 | 1291 | (cffi:defcfun ("snd_midi_event_encode_byte" snd_midi_event_encode_byte) :int 1292 | (dev :pointer) 1293 | (c :int) 1294 | (ev :pointer)) 1295 | 1296 | (cffi:defcfun ("snd_midi_event_decode" snd_midi_event_decode) :long 1297 | (dev :pointer) 1298 | (buf :pointer) 1299 | (count :long) 1300 | (ev :pointer)) 1301 | -------------------------------------------------------------------------------- /driver/cl-alsaseq.lisp: -------------------------------------------------------------------------------- 1 | (in-package #:cl-alsaseq) 2 | 3 | (load-foreign-library '(:or "libasound.so.2" "libasound.so")) 4 | 5 | (defun open-seq (client-name) 6 | "return a new alsa sequencer object named " 7 | (let ((seq (foreign-alloc :pointer))) 8 | (snd_seq_open seq "default" SND_SEQ_OPEN_DUPLEX 0) 9 | (snd_seq_set_client_name (mem-ref seq :pointer) client-name) 10 | seq)) 11 | 12 | (defun close-seq (seq) 13 | "close alsa sequencer object " 14 | (snd_seq_close (mem-ref seq :pointer)) 15 | (foreign-free seq) 16 | (setf seq nil)) 17 | 18 | (defun open-port (name seq &optional (direction :duplex)) 19 | "create a new port on the alsa sequencer object named " 20 | (snd_seq_create_simple_port seq name 21 | (apply #'logior 22 | (append 23 | (match direction 24 | ((or :duplex :input) 25 | (list SND_SEQ_PORT_CAP_WRITE 26 | SND_SEQ_PORT_CAP_SUBS_WRITE))) 27 | (match direction 28 | ((or :duplex :output) 29 | (list SND_SEQ_PORT_CAP_READ 30 | SND_SEQ_PORT_CAP_SUBS_READ))))) 31 | (logior SND_SEQ_PORT_TYPE_MIDI_GENERIC 32 | SND_SEQ_PORT_TYPE_APPLICATION))) 33 | (defun close-port (seq port) 34 | "close port on alsa sequencer object " 35 | (snd_seq_delete_simple_port seq port)) 36 | 37 | (defmacro! with-seq ((seq &key (name "Common Lisp")) &body body) 38 | "open an alsa sequencer connection , named with lexical scope in " 39 | `(let* ((,g!seq (open-seq ,name)) 40 | (,seq (mem-ref ,g!seq :pointer))) 41 | (unwind-protect 42 | (progn ,@body) 43 | (close-seq ,g!seq)))) 44 | 45 | (defun ev-key-int (key) 46 | "convert alsa event-type keyword to cffi int" 47 | (foreign-enum-value 'snd_seq_event_type key)) 48 | 49 | (defun ev-int-key (int) 50 | "convert alsa event-type cffi int to keyword" 51 | (foreign-enum-keyword 'snd_seq_event_type int)) 52 | 53 | (defun cond-lookup-test (event-type-key) 54 | "Helper function for debugging cond-lookup macro e.g 55 | (cond-lookup-test :snd_seq_event_noteon)" 56 | (let ((event-type (ev-key-int event-type-key))) 57 | (cond-lookup))) 58 | 59 | (defun midi-data (*data event-type) 60 | "Mapping event-type and data pointer to lisp-readable midi data" 61 | (let ((type (cond-lookup))) 62 | (if type 63 | (cffi:mem-ref *data type) 64 | (warn "Received unknown data of type ~A" 65 | (ev-int-key type))))) 66 | 67 | (defun describe-event (event) 68 | "take a raw cffi midi event and return plist representation" 69 | (with-foreign-slots ((type (:pointer data) queue (:pointer source) (:pointer dest)) event (:struct snd_seq_event_t)) 70 | (list ;; :pointer event 71 | :event-type 72 | (ev-int-key type) 73 | :event-data 74 | (midi-data data type) 75 | :source 76 | (list ;; source 77 | (mem-ref source '(:struct snd_seq_addr_t))) 78 | :dest 79 | (list ;; dest 80 | (mem-ref dest '(:struct snd_seq_addr_t)))))) 81 | 82 | (defcvar "errno" :int) 83 | 84 | (defun recv (*seq) 85 | "poll the alsa midi port at *seq and my-port, block until there is a midi event to read, then return that event" 86 | (cffi:with-foreign-object (*event '(:struct snd_seq_event_t)) 87 | (snd_seq_event_input *seq *event) 88 | (describe-event (mem-ref *event :pointer)))) 89 | 90 | (defcfun "memset" :pointer 91 | (*dest :pointer) 92 | (val :int) 93 | (*n :uchar)) 94 | 95 | (defun clear-foreign-type (*ev type) 96 | (memset *ev 0 (foreign-type-size type))) 97 | 98 | ;; (defcvar "errno" :int) 99 | 100 | (defun set-addr-slots (addr *port *client) 101 | (with-foreign-slots (((:pointer port) (:pointer client)) 102 | addr (:struct snd_seq_addr_t)) 103 | (setf (mem-ref port :uchar) *port) 104 | (setf (mem-ref client :uchar) *client ))) 105 | 106 | (defmacro with-midi-event ((var data type 107 | &key (queue snd_seq_queue_direct) (flags 0)) 108 | &body body) 109 | `(let ((,var (convert-to-foreign (list 110 | 'type ,type 111 | 'queue ,queue 112 | 'flags ,flags 113 | ) 114 | '(:struct snd_seq_event_t)))) 115 | (with-foreign-slots (((:pointer data)) 116 | ,var (:struct snd_seq_event_t)) 117 | (let ((,data data)) 118 | ,@body)))) 119 | 120 | (defmacro! with-midi-ctrl-event ((var type channel param value) &body body) 121 | `(with-midi-event (,var ,g!data (ev-key-int ,type)) 122 | (let ((,g!channel ,channel) 123 | (,g!param ,param) 124 | (,g!value ,value)) 125 | (with-foreign-slots (((:pointer channel) 126 | (:pointer param) 127 | (:pointer value)) 128 | ,g!data (:struct snd_seq_ev_ctrl_t)) 129 | (setf (mem-ref channel :uchar) ,g!channel) 130 | (setf (mem-ref param :uint) ,g!param) 131 | (setf (mem-ref value :int) ,g!value))) 132 | ,@body)) 133 | 134 | (defmacro! with-midi-note-event ((var type channel note velocity 135 | off_velocity duration) &body body) 136 | `(with-midi-event (,var ,g!data (ev-key-int ,type)) 137 | (let ((,g!channel ,channel) 138 | (,g!note ,note) 139 | (,g!velocity ,velocity) 140 | (,g!off_velocity ,off_velocity) 141 | (,g!duration ,duration)) 142 | (with-foreign-slots (((:pointer channel) 143 | (:pointer note) 144 | (:pointer velocity) 145 | (:pointer off_velocity) 146 | (:pointer duration)) 147 | ,g!data (:struct snd_seq_ev_note_t)) 148 | (setf (mem-ref channel :uchar) ,g!channel) 149 | (setf (mem-ref note :uchar) ,g!note) 150 | (setf (mem-ref velocity :uchar) ,g!velocity) 151 | (setf (mem-ref off_velocity :uchar) ,g!off_velocity) 152 | (setf (mem-ref duration :uint) ,g!duration) 153 | )) 154 | ,@body)) 155 | 156 | (defmacro! with-midi-queue-event ((var type queue unused param) &body body) 157 | `(with-midi-event (,var ,g!data (ev-key-int ,type)) 158 | (let ((,g!queue ,queue) 159 | (,g!unused ,unused) 160 | (,g!param ,param)) 161 | (with-foreign-slots (((:pointer queue) 162 | (:pointer unused) 163 | (:pointer param)) 164 | ,g!data (:struct snd_seq_ev_queue_control_t)) 165 | (setf (mem-ref queue :uchar) ,g!queue) 166 | (setf (mem-ref unused :pointer) ,g!unused) 167 | (setf (mem-ref param :pointer) ,g!param))) 168 | ,@body)) 169 | 170 | (defun send-midi (*seq my-port event) 171 | (with-foreign-slots (((:pointer source) (:pointer dest)) 172 | event (:struct snd_seq_event_t)) 173 | (set-addr-slots source my-port 0) 174 | (set-addr-slots dest SND_SEQ_ADDRESS_UNKNOWN SND_SEQ_ADDRESS_SUBSCRIBERS) 175 | (snd_seq_event_output *seq event) 176 | (snd_seq_drain_output *seq))) 177 | 178 | (defun event-type-assert (type type-min type-max) 179 | "check that keyword 'type' is a valid event type keyword" 180 | (let ((type-value (ev-key-int type))) 181 | (assert (and (>= type-value (ev-key-int type-min)) 182 | (< type-value (ev-key-int type-max)))))) 183 | 184 | (defun send-note (velocity note channel note-type 185 | *seq my-port) 186 | (event-type-assert note-type :SND_SEQ_EVENT_NOTE :SND_SEQ_EVENT_CONTROLLER) 187 | (with-midi-note-event (event note-type channel note velocity 0 0) 188 | (send-midi *seq my-port event))) 189 | 190 | (defun send-ctrl (channel param value ctrl-type 191 | *seq my-port) 192 | (event-type-assert ctrl-type :SND_SEQ_EVENT_CONTROLLER :SND_SEQ_EVENT_SONGPOS) 193 | (with-midi-ctrl-event (event ctrl-type channel param value) 194 | (send-midi *seq my-port event))) 195 | 196 | (defun send-queue-ctrl (queue queue-ctrl-type 197 | *seq my-port) 198 | (event-type-assert queue-ctrl-type :SND_SEQ_EVENT_START :SND_SEQ_EVENT_TUNE_REQUEST) 199 | (with-midi-queue-event (event queue-ctrl-type queue (null-pointer) (null-pointer)) 200 | (send-midi *seq my-port event))) 201 | -------------------------------------------------------------------------------- /driver/event-lookup.lisp: -------------------------------------------------------------------------------- 1 | (in-package :cl-alsaseq) 2 | (defmacro lookup-table () 3 | `(list 4 | :SND_SEQ_EVENT_SYSTEM nil 5 | :SND_SEQ_EVENT_NOTE '(:struct snd_seq_ev_note_t) 6 | :SND_SEQ_EVENT_CONTROLLER '(:struct snd_seq_ev_ctrl_t) 7 | :SND_SEQ_EVENT_START '(:struct snd_seq_ev_queue_control_t) 8 | :SND_SEQ_EVENT_TUNE_REQUEST nil 9 | :SND_SEQ_EVENT_CLIENT_START '(:struct snd_seq_addr_t) 10 | :SND_SEQ_EVENT_USR0 nil 11 | :SND_SEQ_EVENT_SYSEX '(:struct snd_seq_ev_ext_t) 12 | :SND_SEQ_EVENT_USR_VAR0 nil)) 13 | 14 | (defun snd-seq-condition (key val) 15 | `((>= event-type (foreign-enum-value 'snd_seq_event_type ,key)) 16 | ',val)) 17 | 18 | (defmacro cond-lookup () 19 | (labels ((lookup (rest) 20 | (if rest 21 | (cons (snd-seq-condition (car rest) 22 | (cadr rest)) 23 | (lookup (cddr rest)))))) 24 | `(cond ,@(reverse (lookup (lookup-table)))))) 25 | -------------------------------------------------------------------------------- /easy-api.lisp: -------------------------------------------------------------------------------- 1 | (in-package :cl-alsaseq.quick) 2 | 3 | (defmacro def-event-func (event args &body body) 4 | `(defun ,(intern (format nil "SEND-~A" event)) 5 | ,args ,@body)) 6 | 7 | (eval-when (:load-toplevel :compile-toplevel :execute) 8 | (mapcar 9 | (lambda (event-type) 10 | (let ((ctrl-type (intern (format nil "SND_SEQ_EVENT_~A" event-type) :keyword))) 11 | (compile (intern (format nil "SEND-~A" event-type)) 12 | `(lambda (channel param value 13 | *seq my-port) 14 | (send-ctrl channel param value ,ctrl-type *seq my-port))))) 15 | '(:PGMCHANGE 16 | :CHANPRESS 17 | :PITCHBEND 18 | :CONTROL 19 | :NONREGPARAM 20 | :REGPARAM))) 21 | 22 | 23 | (defun send-note-on (velocity note channel 24 | *seq my-port) 25 | (send-note velocity note channel :SND_SEQ_EVENT_NOTEON *seq my-port)) 26 | 27 | (defun send-note-off (velocity note channel 28 | *seq my-port) 29 | (send-note velocity note channel :SND_SEQ_EVENT_NOTEOFF *seq my-port)) 30 | -------------------------------------------------------------------------------- /midihelper/clock.lisp: -------------------------------------------------------------------------------- 1 | (in-package :midihelper) 2 | 3 | (defvar *clock-ctrl-chan* (make-nonblock-buf-channel)) 4 | 5 | (defvar *clock-ochan* (make-nonblock-buf-channel)) 6 | 7 | (defvar *tick-time* 0.015) 8 | 9 | (defun set-master-bpm (bpm) 10 | (setf *tick-time* (/ (/ 60 24) bpm))) 11 | 12 | (let ((songpos 0) 13 | (ticker-state :stopped) 14 | (last (get-internal-real-time)) 15 | (next (get-internal-real-time))) 16 | 17 | (defun hires-tick (tick-chan microtick-intvl) 18 | (! tick-chan (ev-tick songpos)) 19 | (incf songpos) 20 | (sleep microtick-intvl) 21 | (dotimes (n 3) 22 | (! tick-chan (ev-microtick songpos)) 23 | (incf songpos) 24 | (sleep microtick-intvl))) 25 | 26 | (defun hires-semiquaver (tick-chan tick-intvl) 27 | (dotimes (n 6) 28 | (hires-tick tick-chan (/ tick-intvl 4)))) 29 | 30 | (defun lores-semiquaver (tick-chan tick-intvl) 31 | (dotimes (n 6) 32 | (! tick-chan (ev-tick songpos)) 33 | (incf songpos 4) 34 | (sleep tick-intvl))) 35 | 36 | (defun measure-tick-time () 37 | (assert (>= next last)) 38 | (let ((intvl (/ (- next last) 1000 ))) 39 | (setf last next) 40 | (setf next (get-internal-real-time)) 41 | (if (> intvl 1/8);; 1/8 second => 20bpm - lower limit 42 | 0.005 ;;0.005 ms per tick => 500bpm - upper limit 43 | intvl))) 44 | 45 | (defun set-songpos (ticks) 46 | "Set song position, specified in 1/4 beats (same units as songpos pointer)" 47 | (setf songpos (* ticks 24))) 48 | 49 | (defun get-songpos () 50 | "Get song position, in semiquavers" 51 | (/ songpos 24)) 52 | 53 | (defun stopped-handler (tick-chan ctrl-chan) 54 | (match (? ctrl-chan) 55 | ((property :event-type :snd_seq_event_continue) 56 | (! tick-chan (ev-songpos songpos)) 57 | (! tick-chan (ev-continue)) 58 | (setf ticker-state :running)) 59 | ((property :event-type :snd_seq_event_start) 60 | (setf songpos 0) 61 | (! tick-chan (ev-songpos songpos)) 62 | (! tick-chan (ev-start)) 63 | (setf ticker-state :running)) 64 | ((property :EVENT-TYPE :SND_SEQ_EVENT_CLOCK) 65 | ;; (warn "received clock signal before control signal whilst in stopped state, ignoring") 66 | ))) 67 | 68 | (defun ticker (tick-chan ctrl-chan master-slave ppqn) 69 | "optional master clock" 70 | (multiple-value-bind (semiquavers rem) 71 | (floor songpos 24) 72 | ;; (assert (= 0 rem)) 73 | semiquavers 74 | ;; (print master-slave) 75 | ;; (print ppqn) 76 | ;; (if (= 0 rem) 77 | ;; (print semiquavers)) 78 | ) 79 | (match (list ticker-state master-slave) 80 | ((list :stopped _) 81 | (stopped-handler tick-chan ctrl-chan)) 82 | ((list :running :master) 83 | (pri-alt ((? ctrl-chan ctrl) 84 | (match ctrl 85 | ((property :EVENT-TYPE :SND_SEQ_EVENT_STOP) 86 | (setf ticker-state :stopped)))) 87 | (otherwise 88 | (match ppqn 89 | (24 (lores-semiquaver tick-chan *tick-time*)) 90 | (96 (hires-semiquaver tick-chan *tick-time*)))))) 91 | ((list :running :slave) 92 | (match (? ctrl-chan) 93 | ((property :EVENT-TYPE :SND_SEQ_EVENT_STOP) 94 | (setf ticker-state :stopped)) 95 | ((property :EVENT-TYPE :SND_SEQ_EVENT_CLOCK) 96 | (match ppqn 97 | (24 (! tick-chan (ev-tick songpos)) 98 | (incf songpos 4)) 99 | (96 (hires-tick tick-chan (/ (measure-tick-time) 24)))))))))) 100 | 101 | (defvar *clock-thread* nil) 102 | 103 | (defun bpm-test (&optional (ppqn 96) (clock-chan *clock-ochan*)) 104 | ;; (drain-channel clock-chan) 105 | ;; clear buffer of stale ticks 106 | (? clock-chan) 107 | (let ((start-time) 108 | (end-time) 109 | (reps (* ppqn 5))) 110 | (setf start-time (get-internal-real-time)) 111 | (loop repeat reps do 112 | (? clock-chan 0.1)) 113 | (setf end-time (get-internal-real-time)) 114 | (format t "counted ~A ticks in ~A ms. (~F bpm)~%~%" 115 | reps 116 | (- end-time start-time) 117 | (/ (* reps 60 1000) 118 | (* ppqn (- end-time start-time)))))) 119 | 120 | (defun start-clock (ctrl-chan master-slave ppqn) 121 | (assert (null *clock-thread*)) 122 | (setf *clock-thread* 123 | (bt:make-thread 124 | (lambda () 125 | (loop 126 | (restart-case 127 | (ticker *clock-ochan* ctrl-chan master-slave ppqn) 128 | (carry-on-ticking ())))) 129 | :name "midihelper clock"))) 130 | 131 | (defun stop-clock () 132 | (bt:destroy-thread *clock-thread*) 133 | (setf *clock-thread* nil)) 134 | 135 | (defun ev-noteon (channel note velocity) 136 | (list :EVENT-TYPE :SND_SEQ_EVENT_NOTEON 137 | :EVENT-DATA `(VELOCITY ,velocity NOTE ,note CHANNEL ,channel))) 138 | 139 | (defun ev-noteoff (channel note velocity) 140 | (list :EVENT-TYPE :SND_SEQ_EVENT_NOTEOFF 141 | :EVENT-DATA `(VELOCITY ,velocity NOTE ,note CHANNEL ,channel))) 142 | 143 | (defun ev-pgmchange (channel program) 144 | (list :EVENT-TYPE :SND_SEQ_EVENT_PGMCHANGE 145 | :EVENT-DATA `(PARAM 0 VALUE ,program CHANNEL ,channel))) 146 | 147 | (defun ev-tick (&optional songpos) 148 | `(:EVENT-TYPE :SND_SEQ_EVENT_CLOCK ,@(if songpos 149 | (list :songpos 150 | songpos)))) 151 | 152 | (defun ev-microtick (&optional songpos) 153 | `(:EVENT-TYPE :MICROTICK ,@(if songpos 154 | (list :songpos 155 | songpos)))) 156 | 157 | (defun ev-start () 158 | '(:EVENT-TYPE :SND_SEQ_EVENT_START)) 159 | 160 | (defun ev-stop () 161 | '(:EVENT-TYPE :SND_SEQ_EVENT_STOP)) 162 | 163 | (defun ev-continue () 164 | '(:EVENT-TYPE :SND_SEQ_EVENT_CONTINUE)) 165 | 166 | (defun ev-songpos (songpos) 167 | (list :EVENT-TYPE :SND_SEQ_EVENT_SONGPOS 168 | :EVENT-DATA `(VALUE ,songpos PARAM 0 CHANNEL 0))) 169 | 170 | (defun ev-cc (channel param value) 171 | (list :EVENT-TYPE :SND_SEQ_EVENT_CONTROLLER 172 | :EVENT-DATA `(VALUE ,value PARAM ,param CHANNEL ,channel))) 173 | 174 | (defun ev-pitchbend (channel value) 175 | (list :EVENT-TYPE :SND_SEQ_EVENT_PITCHBEND 176 | :EVENT-DATA `(VALUE ,value PARAM 0 CHANNEL ,channel))) 177 | -------------------------------------------------------------------------------- /midihelper/midihelper.lisp: -------------------------------------------------------------------------------- 1 | (in-package :midihelper) 2 | (defun inspect-midihelper () 3 | (list '*reader-thread* *reader-thread* 4 | '*clock-thread* *clock-thread* 5 | '*writer-thread* *writer-thread*)) 6 | 7 | (defun start-midihelper (&optional 8 | (master-slave :master) 9 | (ppqn 96) (reader-map #'identity)) 10 | (assert (or (= ppqn 96) 11 | (= ppqn 24))) 12 | (assert (or (eq master-slave :master) 13 | (eq master-slave :slave))) 14 | (alexandria:doplist (key val (inspect-midihelper)) 15 | (when val 16 | (warn "At least one midihelper thread already appears to be running; to restart, run #'stop-midihelper first") 17 | (return-from start-midihelper nil))) 18 | (drain-channel *clock-ochan*) 19 | (drain-channel *clock-ctrl-chan*) 20 | (start-reader *clock-ctrl-chan* reader-map) 21 | (start-clock *clock-ctrl-chan* master-slave ppqn) 22 | (start-writer-thread)) 23 | 24 | (defun check-midihelper () 25 | (alexandria:doplist 26 | (key val (inspect-midihelper)) 27 | (if (null val) 28 | (warn "Helper ~A not running" key)))) 29 | 30 | (defun stop-midihelper () 31 | (check-midihelper) 32 | (ignore-errors (stop-reader)) 33 | (setf *reader-thread* nil) 34 | (ignore-errors (stop-writer-thread)) 35 | (setf *writer-thread* nil) 36 | (ignore-errors (stop-clock)) 37 | (setf *clock-thread* nil) 38 | (inspect-midihelper)) 39 | -------------------------------------------------------------------------------- /midihelper/reader.lisp: -------------------------------------------------------------------------------- 1 | (in-package :midihelper) 2 | 3 | (defun make-nonblock-buf-channel (&optional (queue 100)) 4 | (make-instance 'calispel:channel 5 | :buffer (MAKE-INSTANCE 6 | 'jpl-queues:LOSSY-BOUNDED-FIFO-QUEUE 7 | :CAPACITY queue) 8 | )) 9 | 10 | (defun drain-channel (chan) 11 | (loop (pri-alt ((? chan res) 12 | (print res)) 13 | (otherwise 14 | (return-from drain-channel))))) 15 | 16 | (define-condition stop-thread (error) 17 | ()) 18 | 19 | (defvar *reader-ochan* (make-nonblock-buf-channel)) 20 | 21 | (defmacro if-gesture (&body body) 22 | `((plist :EVENT-TYPE (guard event-type (or (equal event-type :snd_seq_event_noteoff) 23 | (equal event-type :snd_seq_event_noteon) 24 | (equal event-type 25 | :snd_seq_event_controller) 26 | (equal event-type 27 | :snd_seq_event_pgmchange) 28 | (equal event-type 29 | :snd_seq_event_chanpress) 30 | (equal event-type 31 | :snd_seq_event_pitchbend) 32 | (equal event-type 33 | :snd_seq_event_control14) 34 | (equal event-type 35 | :snd_seq_event_nonregparam) 36 | (equal event-type 37 | :snd_seq_event_regparam)))) 38 | ,@body)) 39 | 40 | (defmacro if-clock (&body body) 41 | `((plist :EVENT-TYPE (guard event-type (or (equal event-type 42 | :snd_seq_event_clock) 43 | (equal event-type 44 | :snd_seq_event_start) 45 | (equal event-type 46 | :snd_seq_event_stop) 47 | (equal event-type 48 | :snd_seq_event_continue) 49 | (equal event-type 50 | :snd_seq_event_songpos)))) 51 | ,@body)) 52 | 53 | (defmacro macromatch (arg &body clauses) 54 | `(match ,arg 55 | ,@(mapcar #'macroexpand 56 | clauses))) 57 | 58 | (defun midi-input (seq clock-ichan reader-ochan reader-map) 59 | (let ((mess (recv seq))) 60 | (macromatch mess 61 | (if-gesture 62 | (mapcar 63 | (lambda (mapped-mess) 64 | (! reader-ochan mapped-mess)) 65 | (funcall reader-map 66 | (list mess)))) 67 | (if-clock 68 | (! clock-ichan mess))))) 69 | 70 | (defvar *reader-thread* nil) 71 | 72 | (defun start-reader (clock-ichan &optional (reader-map #'identity)) 73 | (assert (null *reader-thread*)) 74 | (setf *reader-thread* 75 | (bt:make-thread (lambda () 76 | (sleep 1) 77 | (unwind-protect 78 | (handler-case 79 | (with-seq (seq :name "CL") 80 | (open-port "in" seq :input) 81 | (loop 82 | (restart-case 83 | (midi-input seq 84 | clock-ichan 85 | *reader-ochan* 86 | reader-map) 87 | (carry-on-reading ())))) 88 | (stop-thread ())) 89 | (setf *reader-thread* nil))) 90 | :name "simple-midi-reader"))) 91 | 92 | (defun stop-reader () 93 | (bt:interrupt-thread 94 | *reader-thread* (lambda () 95 | (error 'stop-thread)))) 96 | -------------------------------------------------------------------------------- /midihelper/slime-bindings.el: -------------------------------------------------------------------------------- 1 | (global-unset-key (kbd "M-m")) 2 | 3 | (defun clock-start () 4 | (interactive) 5 | (slime-interactive-eval "(calispel:! midihelper:*clock-ctrl-chan* (midihelper:ev-start))")) 6 | (defun clock-stop () 7 | (interactive) 8 | (slime-interactive-eval "(calispel:! midihelper:*clock-ctrl-chan* (midihelper:ev-stop))")) 9 | (defun clock-continue () 10 | (interactive) 11 | (slime-interactive-eval "(calispel:! midihelper:*clock-ctrl-chan* (midihelper:ev-continue))")) 12 | (global-set-key (kbd "M-m M-m") 'clock-stop) 13 | (global-set-key (kbd "M-m M-k") 'clock-continue) 14 | (global-set-key (kbd "M-m M-l") 'clock-start) 15 | 16 | (defun group1 () 17 | (interactive) 18 | (slime-interactive-eval "(calispel:! midihelper:*clock-ctrl-chan* (mloops::global-ctrl (lambda () (mloops::loop-group 1))))")) 19 | (defun loop1 () 20 | (interactive) 21 | (slime-interactive-eval "(setf mloops::*active-loop* 1)")) 22 | (defun group2 () 23 | (interactive) 24 | (slime-interactive-eval "(calispel:! midihelper:*clock-ctrl-chan* (mloops::global-ctrl (lambda () (mloops::loop-group 2))))")) 25 | (defun loop2 () 26 | (interactive) 27 | (slime-interactive-eval "(setf mloops::*active-loop* 2)")) 28 | (defun group3 () 29 | (interactive) 30 | (slime-interactive-eval "(calispel:! midihelper:*clock-ctrl-chan* (mloops::global-ctrl (lambda () (mloops::loop-group 3))))")) 31 | (defun loop3 () 32 | (interactive) 33 | (slime-interactive-eval "(setf mloops::*active-loop* 3)")) 34 | (defun group4 () 35 | (interactive) 36 | (slime-interactive-eval "(calispel:! midihelper:*clock-ctrl-chan* (mloops::global-ctrl (lambda () (mloops::loop-group 4))))")) 37 | (defun loop4 () 38 | (interactive) 39 | (slime-interactive-eval "(setf mloops::*active-loop* 4)")) 40 | (global-set-key (kbd "M-m 1") 'loop1) 41 | (global-set-key (kbd "M-m M-1") 'group1) 42 | (global-set-key (kbd "M-m 2") 'loop2) 43 | (global-set-key (kbd "M-m M-2") 'group2) 44 | (global-set-key (kbd "M-m 3") 'loop3) 45 | (global-set-key (kbd "M-m M-3") 'group3) 46 | (global-set-key (kbd "M-m 4") 'loop4) 47 | (global-set-key (kbd "M-m M-4") 'group4) 48 | 49 | (defun notekick () 50 | (interactive) 51 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (midihelper:ev-noteon 0 36 127))")) 52 | (defun notesnare () 53 | (interactive) 54 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (midihelper:ev-noteon 0 38 127))")) 55 | (defun noteclap () 56 | (interactive) 57 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (midihelper:ev-noteon 0 39 127))")) 58 | (defun note3 () 59 | (interactive) 60 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (midihelper:ev-noteon 0 43 127))")) 61 | (global-set-key (kbd "M-n") 'note3) 62 | (global-set-key (kbd "M-j") 'notekick) 63 | (global-set-key (kbd "M-k") 'notesnare) 64 | (global-set-key (kbd "M-l") 'noteclap) 65 | 66 | (defun toggle-metronome () 67 | (interactive) 68 | (slime-interactive-eval "(mloops::global-ctrl #'mloops::toggle-metronome)")) 69 | (global-set-key (kbd "M-m 0") 'toggle-metronome) 70 | 71 | (defun midi-loop-cycle () 72 | (interactive) 73 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (mloops::loop-ctrl #'mloops::loop-cycle))")) 74 | (global-set-key (kbd "M-SPC") 'midi-loop-cycle) 75 | 76 | (defun loop-play () 77 | (interactive) 78 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (mloops::loop-ctrl #'mloops::loop-play))")) 79 | (defun loop-play-push-extend () 80 | (interactive) 81 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (mloops::loop-ctrl #'mloops::loop-push-extend))")) 82 | (defun loop-stop () 83 | (interactive) 84 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (mloops::loop-ctrl #'mloops::loop-stop))")) 85 | (defun loop-erase () 86 | (interactive) 87 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (mloops::loop-ctrl #'mloops::loop-erase))")) 88 | (defun loop-overwrite () 89 | (interactive) 90 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (mloops::loop-ctrl #'mloops::loop-overwrite))")) 91 | (defun loop-overdub () 92 | (interactive) 93 | (slime-interactive-eval "(calispel:! midihelper:*reader-ochan* (mloops::loop-ctrl #'mloops::loop-overdub))")) 94 | 95 | (global-set-key (kbd "M-m m") 'loop-stop) 96 | (global-set-key (kbd "M-m k") 'loop-continue) 97 | (global-set-key (kbd "M-m l") 'loop-play) 98 | (global-set-key (kbd "M-m d") 'loop-erase) 99 | (global-set-key (kbd "M-m O") 'loop-overwrite) 100 | (global-set-key (kbd "M-m o") 'loop-overdub) 101 | (global-set-key (kbd "M-m l") 'loop-play-push-extend) 102 | (global-set-key (kbd "M-m k") 'loop-play) 103 | 104 | 105 | ;; (define-derived-mode 106 | ;; (ido 107 | ;; (smex 108 | ;; smart parens 109 | ;; cider mode 110 | ;; redshank refactoring library 111 | -------------------------------------------------------------------------------- /midihelper/writer.lisp: -------------------------------------------------------------------------------- 1 | (in-package :midihelper) 2 | 3 | (defvar *seq* nil);;sequence struct 4 | (defvar **seq nil);;pointer to sequence struct (for memory deallocation) 5 | (defvar *my-ports* nil) 6 | 7 | (defun %send-event (description &optional (port (car *my-ports*)) (seq *seq*)) 8 | (match description 9 | ((plist :EVENT-TYPE (guard event-type (or (equal event-type :snd_seq_event_noteoff) 10 | (equal event-type :snd_seq_event_noteon))) 11 | :EVENT-DATA (plist ;; DURATION duration OFF_VELOCITY off_velocity 12 | VELOCITY velocity NOTE note CHANNEL channel)) 13 | (send-note velocity note channel event-type seq port)) 14 | ((plist :EVENT-TYPE (guard event-type (or (equal event-type 15 | :snd_seq_event_controller) 16 | (equal event-type 17 | :snd_seq_event_songpos) 18 | (equal event-type 19 | :snd_seq_event_pgmchange) 20 | (equal event-type 21 | :snd_seq_event_chanpress) 22 | (equal event-type 23 | :snd_seq_event_pitchbend) 24 | (equal event-type 25 | :snd_seq_event_control14) 26 | (equal event-type 27 | :snd_seq_event_nonregparam) 28 | (equal event-type 29 | :snd_seq_event_regparam))) 30 | :EVENT-DATA (plist VALUE value PARAM param CHANNEL channel)) 31 | (send-ctrl channel param value event-type seq port)) 32 | ((plist :EVENT-TYPE (guard event-type (or (equal event-type 33 | :snd_seq_event_clock) 34 | (equal event-type 35 | :snd_seq_event_start) 36 | (equal event-type 37 | :snd_seq_event_stop) 38 | (equal event-type 39 | :snd_seq_event_continue)))) 40 | (send-queue-ctrl 0 event-type seq port)) 41 | (_ (format t "unknown event ~S~%" description)))) 42 | 43 | (defun start-writer () 44 | (assert (null **seq)) 45 | (assert (null *seq*)) 46 | (assert (null *my-ports*)) 47 | (setf **seq (open-seq "CL")) 48 | (setf *seq* (mem-ref **seq :pointer)) 49 | (setf *my-ports* 50 | (list (open-port (format nil "Output") 51 | *seq* 52 | :output)))) 53 | 54 | (defun stop-writer () 55 | (assert **seq) 56 | (close-seq **seq) 57 | (setf *seq* nil) 58 | (setf **seq nil) 59 | (setf *my-ports* nil)) 60 | 61 | (defvar *writer-thread* nil) 62 | (defvar *writer-ichan* (make-nonblock-buf-channel)) 63 | 64 | (defun start-writer-thread () 65 | (assert (null *writer-thread*)) 66 | (setf *writer-thread* 67 | (bt:make-thread 68 | (lambda () 69 | (declare (optimize (debug 3))) 70 | (with-seq (thread-seq :name "CL") 71 | (unwind-protect 72 | (progn 73 | (let ((port (open-port "port0" thread-seq :output))) 74 | (handler-case 75 | (loop 76 | (let ((message (? *writer-ichan*))) 77 | (restart-case 78 | (%send-event message 79 | port 80 | thread-seq) 81 | (carry-on-writing ())))) 82 | (stop-thread ())))) 83 | (setf *writer-thread* nil)))) 84 | :name "midihelper writer"))) 85 | 86 | (defun stop-writer-thread () 87 | (bt:interrupt-thread 88 | *writer-thread* (lambda () 89 | (error 'stop-thread)))) 90 | 91 | (defun send-event (event) 92 | (! *writer-ichan* event)) 93 | -------------------------------------------------------------------------------- /midiloops.lisp: -------------------------------------------------------------------------------- 1 | (in-package :midiloops) 2 | 3 | (defconstant +n-loops+ 4) 4 | (defconstant +default-loop-res+ 96) 5 | (defconstant +default-loop-len+ 1500) 6 | 7 | (defun null-trigger () 8 | (lambda (event) 9 | (declare (ignore event)) 10 | nil)) 11 | 12 | (defun new-m-loop () 13 | (list 14 | :seq (make-array (* +default-loop-res+ 15 | +default-loop-len+) 16 | :initial-element nil 17 | :fill-pointer 0) 18 | :off 0;;loop start time clock microticks 19 | :play nil;; nil :push-extend :repeat 20 | :rec nil;; nil :overwrite or :overdub 21 | :trans #'identity;;this function is applied at read time 22 | :rec-tones nil;;list of active rec notes to prevent stuck notes 23 | :play-tones nil;;list of active play notes to prevent stuck notes 24 | )) 25 | 26 | (defvar *loop-stacks* 27 | (make-array 4 28 | :initial-contents 29 | (loop for i from 1 to 4 30 | collect (let ((looplist 31 | `(,@(loop for i from 1 to +n-loops+ 32 | collect (append `(:loop-id ,i) 33 | (new-m-loop)))))) 34 | (make-array (length looplist) 35 | :initial-contents looplist 36 | :fill-pointer (length looplist)))))) 37 | 38 | (defvar *loop-stack* (aref *loop-stacks* 0)) 39 | (defvar *songpos* 0) 40 | 41 | (defun pos (mloop) 42 | "Return a loops read-head position (loop frame of reference), calculated from offset, play state and *songpos*. Also handles push-extend behaviour" 43 | (or 44 | (match mloop 45 | ((plist :play play 46 | :off off 47 | ;;:rec rec 48 | :seq seq) 49 | (symbol-macrolet ((fill (fill-pointer seq))) 50 | (if (>= *songpos* off) 51 | (match play 52 | (:push-extend 53 | (let ((pos (- *songpos* off))) 54 | (if (>= *songpos* (+ off fill)) 55 | (setf fill (+ pos 1)) 56 | pos))) 57 | (:repeat 58 | (if (>= fill 1) 59 | (nth-value 1 (floor (- *songpos* off) 60 | fill))))))))) 61 | 0)) 62 | 63 | (defvar *sync* :beat) 64 | 65 | (defun sync-intvl () 66 | (case *sync* 67 | (:beat 96) 68 | (:free 1) 69 | (:loop1 (max (length (getf (aref *loop-stack* 0) 70 | :seq)) 71 | 1)))) 72 | 73 | (defun nearest-beat (&optional (songpos *songpos*)) 74 | (* (sync-intvl) 75 | (round songpos 76 | (sync-intvl)))) 77 | 78 | (defun make-fixed-loop (bars &key (major 4) (minor 4) (res +default-loop-res+)) 79 | (let ((newloop (new-m-loop))) 80 | (setf (getf newloop :seq) 81 | (make-array (/ (* bars major 4 res) minor) 82 | :initial-element nil 83 | :fill-pointer 0)) 84 | newloop)) 85 | 86 | (defparameter *default-tick-ev* 87 | (list (ev-noteon 0 43 127))) 88 | 89 | (defparameter *default-tock-ev* 90 | (list (ev-noteon 0 43 67))) 91 | 92 | (defun make-simple-metro (bars 93 | &rest rest 94 | &key (tick-ev *default-tick-ev*) 95 | (tock-ev *default-tock-ev*) 96 | (major 4) (minor 4) (res +default-loop-res+)) 97 | (let* ((newloop (apply #'make-fixed-loop `(,bars ,@rest))) 98 | (seq (getf newloop :seq)) 99 | (beatlen (* res (/ minor 4))) 100 | (barlen (* major beatlen)) 101 | (looplen (* barlen bars))) 102 | (setf (fill-pointer seq) looplen) 103 | (setf (getf newloop :play) :repeat) 104 | (loop for i below looplen 105 | do (match (multiple-value-list (floor i beatlen)) 106 | ((list beats 0) 107 | (match (multiple-value-list (floor beats major)) 108 | ((list _ 0) 109 | (setf (aref seq i) tick-ev)) 110 | ((list _ _) 111 | (setf (aref seq i) tock-ev)))))) 112 | newloop)) 113 | 114 | (defun make-jazz-metro (bars 115 | &rest rest 116 | &key (tick-ev *default-tick-ev*) 117 | (major 4) (minor 4) (res +default-loop-res+)) 118 | (let* ((newloop (apply #'make-fixed-loop `(,bars ,@rest))) 119 | (seq (getf newloop :seq)) 120 | (beatlen (* res (/ minor 4))) 121 | (barlen (* major beatlen)) 122 | (looplen (* barlen bars))) 123 | (setf (fill-pointer seq) looplen) 124 | (setf (getf newloop :play) nil) 125 | (loop for i below looplen 126 | do (match (multiple-value-list (floor i beatlen)) 127 | ((list beats 0) 128 | (match (multiple-value-list (floor beats major)) 129 | ((list _ (guard barbeat (oddp barbeat))) 130 | (setf (aref seq i) tick-ev)))))) 131 | newloop)) 132 | 133 | (defvar *metronome* 134 | (make-simple-metro 2) 135 | ;;(make-jazz-metro 2) 136 | ) 137 | 138 | 139 | (defun toggle-metronome () 140 | (symbol-macrolet ((tog (getf *metronome* :play))) 141 | (setf tog (and (not tog) 142 | :repeat)))) 143 | 144 | (defun redraw-loop-status () 145 | (loop for i below 4 146 | do (if (= 0 (fill-pointer (getf (aref *loop-stack* i) 147 | :seq))) 148 | (send-event (ev-noteoff 15 (+ (* i 2) 149 | 37) 150 | 127)) 151 | (send-event (ev-noteon 15 (+ (* i 2) 152 | 37) 153 | 127))) 154 | (send-event (ev-noteoff 15 (+ (* i 2) 155 | 36) 156 | 127))) 157 | (send-event (ev-noteon 15 (+ (* (position *loop-stack* *loop-stacks*) 158 | 2) 159 | 36) 160 | 127))) 161 | 162 | (defun loop-group (group-id) 163 | (setf *loop-stack* 164 | (aref *loop-stacks* (- group-id 1))) 165 | (redraw-loop-status)) 166 | 167 | (defun loop-overdub (mloop) 168 | (symbol-macrolet ((rec (getf mloop :rec))) 169 | (setf rec 170 | (match rec 171 | (:overdub 172 | nil) 173 | ((or :overwrite nil) 174 | :overdub)))) 175 | (print mloop)) 176 | 177 | ;; (defun loop-overwrite (mloop) 178 | ;; (symbol-macrolet ((rec (getf mloop :rec))) 179 | ;; (setf rec 180 | ;; (match rec 181 | ;; (:overwrite 182 | ;; nil) 183 | ;; ((or :overdub nil) 184 | ;; :overwrite)))) 185 | ;; (print mloop)) 186 | 187 | (defun drain-hanging-play-tones (mloop) 188 | (symbol-macrolet ((tones (getf mloop :play-tones))) 189 | (mapcar #'send-event 190 | tones) 191 | (setf tones nil))) 192 | 193 | (defun drain-hanging-rec-tones (mloop) 194 | (symbol-macrolet ((slot (aref (getf mloop :seq) 195 | (pos mloop))) 196 | (tones (getf mloop :rec-tones))) 197 | (setf slot 198 | (append tones slot)) 199 | (setf tones nil))) 200 | 201 | (defun loop-play (mloop) 202 | (setf (getf mloop :play) :repeat) 203 | (symbol-macrolet ((off (getf mloop :off))) 204 | (setf off (nearest-beat)) 205 | (loop for i from off to (- *last-songpos* 1) 206 | do 207 | (mapcar #'send-event 208 | (aref (getf mloop :seq) 209 | (- i off))))) 210 | (print mloop) 211 | (redraw-loop-status)) 212 | 213 | (defun loop-continue (mloop) 214 | (setf (getf mloop :play) :repeat) 215 | (redraw-loop-status)) 216 | 217 | (defun loop-push-extend (mloop) 218 | (setf (getf mloop :play) :push-extend) 219 | (print mloop) 220 | (redraw-loop-status)) 221 | 222 | (defun loop-stop (mloop) 223 | (setf (getf mloop :play) nil) 224 | (setf (getf mloop :rec) nil) 225 | (drain-hanging-rec-tones mloop) 226 | (drain-hanging-play-tones mloop) 227 | (print mloop) 228 | (redraw-loop-status)) 229 | 230 | (defun loop-erase (mloop) 231 | (let ((seq (getf mloop :seq))) 232 | (setf (getf mloop :play) nil) 233 | (loop for i below (length seq) 234 | do (setf (aref seq i) nil)) 235 | (setf (fill-pointer seq) 236 | 0)) 237 | (setf (getf mloop :rec-tones) nil) 238 | (setf (getf mloop :play-tones) nil) 239 | (print mloop) 240 | (redraw-loop-status)) 241 | 242 | (defparameter +look-back-intvl-divisor+ 5);;Anything under a quintuplet is considered 'in time' 243 | 244 | (defun loop-cycle (mloop &optional (songpos *songpos*)) 245 | (symbol-macrolet ((play (getf mloop :play)) 246 | (rec (getf mloop :rec)) 247 | (seq (getf mloop :seq)) 248 | (fp (fill-pointer (getf mloop :seq))) 249 | (off (getf mloop :off))) 250 | (match mloop 251 | ((plist :play nil 252 | :seq (guard seq 253 | (= 0 (fill-pointer seq))));;Empty loop start recording 254 | (setf play :push-extend) 255 | (setf rec :overdub) 256 | (setf off (nearest-beat)) 257 | (loop 258 | for i 259 | from 0 260 | to (/ (sync-intvl) +look-back-intvl-divisor+) 261 | do (mapcar (lambda (event) 262 | (store-gesture event mloop)) 263 | (nth i (car *last-beat*))))) 264 | 265 | ;;FIXME don't think this actually works... 266 | ;;UNTESTED this loop should prevent dropping events which are recorded just 267 | ;;before loop-cycle received. 268 | ((plist :play :push-extend 269 | :rec :overdub) 270 | (setf play :repeat) 271 | (setf fp 272 | (nearest-beat (- songpos off))) 273 | ;;UNTESTED This loop should prevent dropping events which are recorded 274 | ;;just before loop-cycle received, when loop-cycle received 275 | ;;behind the beat. 276 | (loop for i from fp to (- songpos off) 277 | do (mapcar (lambda (event) 278 | (store-gesture event mloop i)) 279 | (aref seq i))) 280 | (setf rec nil) 281 | ;;FIXME IF loop-cycle is received ahead of the beat, instead of 282 | ;;setting rec to nil, we should set rec to some intermediate state, 283 | ;;which will schedule the loop to stop recording on the beat 284 | (drain-hanging-rec-tones mloop)) 285 | ((plist :play :repeat) 286 | (loop-stop mloop)) 287 | ((plist :play (or :push-extend 288 | nil)) 289 | (setf play :repeat)))) 290 | (print mloop) 291 | (redraw-loop-status)) 292 | 293 | (defun note-pop (tones note channel) 294 | (if tones 295 | (match (car tones) 296 | ((plist :event-data 297 | (plist NOTE (eq note) CHANNEL (eq channel))) 298 | (note-pop (cdr tones) note channel)) 299 | (otherwise (cons (car tones) 300 | (note-pop (cdr tones) note channel)))))) 301 | 302 | (defun skip-1st-if-future (event mloop) 303 | "Ensure events recorded 'into the future' are marked to skip 1st play, e.g quantised recording or when the rec button is pressed slightly ahead of time. Avoids repeated notes which would otherwise 'stick' the synth (noteon with no noteoff)" 304 | (let ((event-copy (copy-tree event))) 305 | (if (> (+ (getf mloop :off) 306 | (pos mloop)) 307 | *songpos*) 308 | (setf (getf event-copy :skip-1st) 309 | t)) 310 | event-copy)) 311 | 312 | (defmacro hang-tones () 313 | `(match event 314 | ((plist :event-type :SND_SEQ_EVENT_NOTEON) 315 | (let ((event-copy (copy-tree event))) 316 | (setf (getf event-copy :event-type) 317 | :SND_SEQ_EVENT_NOTEOFF) 318 | (push event-copy tones))) 319 | ((plist :event-type :SND_SEQ_EVENT_NOTEOFF 320 | :event-data (plist NOTE note CHANNEL channel)) 321 | (setf tones 322 | (note-pop tones note channel))))) 323 | 324 | (defun store-gesture (event mloop 325 | &optional (loop-pos (pos mloop))) 326 | (match mloop 327 | ((plist :play _ 328 | :rec (not nil)) 329 | (symbol-macrolet ((tones (getf mloop :rec-tones)) 330 | (seq (getf mloop :seq))) 331 | (push (skip-1st-if-future event mloop) 332 | (aref seq 333 | loop-pos)) 334 | (hang-tones);;caution - very 'unhygienic' macro! 335 | )))) 336 | 337 | (defun read-gestures (mloop songpos) 338 | (match mloop 339 | ((plist :play (not nil) 340 | :off (guard off (>= songpos off))) 341 | (mapcar (lambda (event) 342 | (if (getf event :skip-1st) 343 | (setf (getf event :skip-1st) nil) 344 | (symbol-macrolet ((tones (getf mloop :play-tones))) 345 | (hang-tones);;caution - very 'unhygienic' macro! 346 | (send-event event)))) 347 | (aref (funcall (getf mloop :trans) 348 | (getf mloop :seq)) 349 | (pos mloop)))))) 350 | 351 | (defvar *last-songpos* 0) 352 | (defun dispatch-event (event mloop) 353 | (macromatch event 354 | ((plist :event-type (guard type 355 | (or (equal type :microtick) 356 | (equal type :snd_seq_event_clock))) 357 | :songpos songpos) 358 | (read-gestures mloop songpos)) 359 | ((plist :event-type (guard type 360 | (or (equal type :microtick) 361 | (equal type :snd_seq_event_clock)))) 362 | (error "loop received clock data with no songpos")) 363 | ((plist :event-type :loop-ctrl 364 | :function function) 365 | (funcall function mloop)) 366 | (if-gesture 367 | (store-gesture event mloop)))) 368 | 369 | (defvar *send-clock* nil) 370 | 371 | (defun make-queue (n) 372 | (let ((my-list (loop for i below n collect nil))) 373 | (cons my-list (last my-list)))) 374 | 375 | (defun pop-queue (queue) 376 | (pop (car queue))) 377 | 378 | (defun push-queue (queue el) 379 | (if (car queue) 380 | (progn 381 | (rplacd (cdr queue) (list el)) 382 | (rplacd queue (cddr queue))) 383 | (let ((new-list (list el))) 384 | (rplaca queue new-list) 385 | (rplacd queue new-list)))) 386 | 387 | (defvar *last-beat* (make-queue 96)) 388 | 389 | (defun handle-tick (songpos event) 390 | (setf *last-songpos* *songpos*) 391 | (setf *songpos* songpos) 392 | (read-gestures *metronome* songpos) 393 | (push-queue *last-beat* nil) 394 | (pop-queue *last-beat*) 395 | (match event 396 | ((plist :event-type :snd_seq_event_clock) 397 | (if *send-clock* (send-event event))))) 398 | 399 | (defun handle-gesture (event) 400 | (push event (cdr *last-beat*)) 401 | (send-event event)) 402 | 403 | (defun run-loop-stack () 404 | (let ((event (pri-alt ((? *clock-ochan* ev) ev) 405 | ((? *reader-ochan* ev) ev)))) 406 | (macromatch event 407 | ((plist :event-type :toggle-metronome) 408 | (toggle-metronome)) 409 | ((plist :event-type :global-ctrl 410 | :function function) 411 | (funcall function)) 412 | ((plist :event-type (guard type 413 | (or (equal type :microtick) 414 | (equal type :snd_seq_event_clock))) 415 | :songpos songpos) 416 | (handle-tick songpos event));;send clock 417 | 418 | (if-gesture 419 | (handle-gesture event)));;echo gestures 420 | 421 | (loop for idx below (length *loop-stack*) 422 | do 423 | (match (list event (aref *loop-stack* idx)) 424 | ((or (not (list (plist :loop-id _) 425 | _));;dispatch events with no loop-id info 426 | (list (plist :loop-id (guard ev-loop-id 427 | (or (equal ev-loop-id :all) 428 | (equal ev-loop-id loop-id)))) 429 | (plist :loop-id loop-id)));;dispatch events where loop-ids match 430 | (dispatch-event event (aref *loop-stack* idx))))))) 431 | 432 | (defvar *midiloops-thread* nil) 433 | 434 | (defun start-midiloops (&optional (master-slave :master)) 435 | (start-midihelper master-slave 436 | 96 #'quneo-reader) 437 | (sleep 0.1) 438 | (setf *midiloops-thread* (bt:make-thread (lambda () 439 | (loop 440 | (restart-case (run-loop-stack) 441 | (carry-on-looping ())))) 442 | :name "loopstack"))) 443 | 444 | (defun stop-midiloops () 445 | (ignore-errors (bt:destroy-thread *midiloops-thread*)) 446 | (stop-midihelper)) 447 | -------------------------------------------------------------------------------- /package.lisp: -------------------------------------------------------------------------------- 1 | ;;;; package.lisp 2 | 3 | (defpackage :cl-alsaseq 4 | (:use :cl :cffi :calispel :optima :optima.extra) 5 | (:import-from :let-over-lambda 6 | :g!-symbol-p 7 | :defmacro/g! 8 | :o!-symbol-p 9 | :o!-symbol-to-g!-symbol 10 | :defmacro!) 11 | (:export :open-port 12 | :close-port 13 | :open-seq 14 | :close-seq 15 | :with-seq 16 | :send-queue-ctrl 17 | :send-ctrl 18 | :send-note 19 | :recv 20 | :velocity 21 | :note 22 | :channel 23 | :param 24 | )) 25 | 26 | (defpackage :cl-alsaseq.quick 27 | (:use :cl :cl-alsaseq) 28 | (:export :send-note-on 29 | :send-note-off 30 | :send-pgmchange 31 | :send-chanpress 32 | :send-pitchbend 33 | :send-control 34 | )) 35 | 36 | (defpackage :midihelper 37 | (:use :cl :cffi :cl-alsaseq :optima :optima.extra :calispel) 38 | (:export :*clock-ochan* 39 | :*clock-ctrl-chan* 40 | :*reader-ichan* 41 | :*reader-ochan* 42 | :set-master-bpm 43 | :inspect-midihelper 44 | :start-midihelper 45 | :stop-midihelper 46 | :check-midihelper 47 | :if-gesture 48 | :if-clock 49 | :macromatch 50 | :drain-channel 51 | :send-event 52 | :ev-noteon 53 | :ev-noteoff 54 | :ev-pgmchange 55 | :ev-tick 56 | :ev-microtick 57 | :ev-start 58 | :ev-stop 59 | :ev-continue 60 | :ev-songpos 61 | :ev-cc 62 | :ev-pitchbend)) 63 | 64 | (defpackage #:midiloops 65 | (:use :cl :cl-alsaseq :midihelper :optima :optima.extra :calispel) 66 | (:import-from :let-over-lambda 67 | :g!-symbol-p 68 | :defmacro/g! 69 | :o!-symbol-p 70 | :o!-symbol-to-g!-symbol 71 | :defmacro!) 72 | (:nicknames :mloops)) 73 | -------------------------------------------------------------------------------- /readtable.lisp: -------------------------------------------------------------------------------- 1 | (in-package :midiloops) 2 | 3 | (defparameter +quneo-chan+ 15) 4 | (defparameter +quneo-led-chan+ 15) 5 | 6 | (defmacro quneo-note (note &body body) 7 | `((plist :EVENT-TYPE :SND_SEQ_EVENT_NOTEON 8 | :EVENT-DATA (plist NOTE ,note 9 | CHANNEL +quneo-chan+)) 10 | ,@body)) 11 | 12 | (defvar *active-loop* 1) 13 | (defvar *loop-group* 1) 14 | 15 | (defun loop-ctrl (function &optional (loop-id *active-loop*)) 16 | (list :event-type :loop-ctrl 17 | :loop-id loop-id 18 | :function function)) 19 | 20 | (defun global-ctrl (function) 21 | (list :event-type :global-ctrl 22 | :function function)) 23 | 24 | (defun quneo-map-event (in-event) 25 | (macromatch in-event 26 | ;;Transport buttons 27 | (quneo-note 26 28 | (list (loop-ctrl #'loop-play))) 29 | (quneo-note 25 30 | (list (loop-ctrl #'loop-stop))) 31 | (quneo-note 24 32 | (list (loop-ctrl #'loop-erase))) 33 | 34 | ;; odd numbers are loop groups, 35 | ;; even numbers are loops in group 36 | (quneo-note 11 37 | (list (global-ctrl (lambda () (loop-group 1))))) 38 | (quneo-note 12 39 | (setf *active-loop* 1) 40 | nil) 41 | 42 | (quneo-note 13 43 | (list (global-ctrl (lambda () (loop-group 2))))) 44 | (quneo-note 14 45 | (setf *active-loop* 2) 46 | nil) 47 | 48 | (quneo-note 15 49 | (list (global-ctrl (lambda () (loop-group 3))))) 50 | (quneo-note 16 51 | (setf *active-loop* 3) 52 | nil) 53 | 54 | (quneo-note 17 55 | (list (global-ctrl (lambda () (loop-group 4))))) 56 | (quneo-note 18 57 | (setf *active-loop* 4) 58 | nil) 59 | 60 | ;;toggle metronome 61 | (quneo-note 19 62 | (list (global-ctrl #'toggle-metronome))) 63 | 64 | ;;Left hand big circle for overdub toggle 65 | (quneo-note 4 66 | (list (loop-ctrl #'loop-overdub))) 67 | ;;Right hand big circle for usual loop-cycle 68 | (quneo-note 5 69 | (list (loop-ctrl #'loop-cycle))) 70 | 71 | ;;Horizontal slider for tempo control 72 | ((plist :EVENT-TYPE :SND_SEQ_EVENT_CONTROLLER 73 | :EVENT-DATA (plist VALUE control-val 74 | PARAM 10 75 | CHANNEL +quneo-chan+)) 76 | (set-master-bpm (+ 50 (* control-val 2))) 77 | nil) 78 | 79 | ;;Pass through any other events 80 | (_ (list in-event)))) 81 | 82 | (defun quneo-reader (in-events) 83 | (apply #'append 84 | (mapcar #'quneo-map-event 85 | in-events)));;monoidal space for in-events list-list 86 | 87 | ;; transport buttons: 33, 34, 35 88 | ;; left hand side bank buttons: 89 | ;; 36, 37 90 | ;; 38, 39 91 | ;; 40, 41 92 | ;; 42, 43 93 | -------------------------------------------------------------------------------- /swig/bindings.i: -------------------------------------------------------------------------------- 1 | %module bindings 2 | 3 | /* %feature("intern_function", "lispify"); */ 4 | 5 | %insert("lisphead") %{ 6 | (in-package :cl-alsaseq) 7 | %} 8 | 9 | /* %{ */ 10 | /* #include */ 11 | /* #include "stdlib.h" */ 12 | /* #include "string.h" */ 13 | /* #include "signal.h" */ 14 | /* #include "getopt.h" */ 15 | /* #include "sys/poll.h" */ 16 | /* #include "alsa/asoundlib.h" */ 17 | /* #include "aconfig.h" */ 18 | /* #include "version.h" */ 19 | /* %} */ 20 | 21 | %include "stdint.i" 22 | /* %include "stl.i" */ 23 | /* %include "cstring.i" */ 24 | /* %include "signal.h" */ 25 | /* %include "getopt.h" */ 26 | %include "poll.h" 27 | %include "bits.poll.h" 28 | /* %include "/usr/include/alsa/mixer.h" */ 29 | %include "seq_event.h" 30 | %include "/usr/include/alsa/seq.h" 31 | /* %include "/usr/include/alsa/mixer.h" */ 32 | %include "/usr/include/alsa/seqmid.h" 33 | %include "/usr/include/alsa/seq_midi_event.h" 34 | 35 | -------------------------------------------------------------------------------- /swig/bits.poll.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1997, 2001, 2006, 2009 Free Software Foundation, Inc. 2 | This file is part of the GNU C Library. 3 | 4 | The GNU C Library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | The GNU C Library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with the GNU C Library; if not, write to the Free 16 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 17 | 02111-1307 USA. */ 18 | 19 | #ifndef _SYS_POLL_H 20 | # error "Never use directly; include instead." 21 | #endif 22 | 23 | /* Event types that can be polled for. These bits may be set in `events' 24 | to indicate the interesting event types; they will appear in `revents' 25 | to indicate the status of the file descriptor. */ 26 | #define POLLIN 0x001 /* There is data to read. */ 27 | #define POLLPRI 0x002 /* There is urgent data to read. */ 28 | #define POLLOUT 0x004 /* Writing now will not block. */ 29 | 30 | #if defined __USE_XOPEN || defined __USE_XOPEN2K8 31 | /* These values are defined in XPG4.2. */ 32 | # define POLLRDNORM 0x040 /* Normal data may be read. */ 33 | # define POLLRDBAND 0x080 /* Priority data may be read. */ 34 | # define POLLWRNORM 0x100 /* Writing now will not block. */ 35 | # define POLLWRBAND 0x200 /* Priority data may be written. */ 36 | #endif 37 | 38 | #ifdef __USE_GNU 39 | /* These are extensions for Linux. */ 40 | # define POLLMSG 0x400 41 | # define POLLREMOVE 0x1000 42 | # define POLLRDHUP 0x2000 43 | #endif 44 | 45 | /* Event types always implicitly polled for. These bits need not be set in 46 | `events', but they will appear in `revents' to indicate the status of 47 | the file descriptor. */ 48 | #define POLLERR 0x008 /* Error condition. */ 49 | #define POLLHUP 0x010 /* Hung up. */ 50 | #define POLLNVAL 0x020 /* Invalid polling request. */ 51 | -------------------------------------------------------------------------------- /swig/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # This script can be used to regenerate the bindings.lisp file using 5 | # SWIG. 6 | # 7 | 8 | swig -cffi -module bindings -noswig-lisp -o ../driver/bindings.lisp bindings.i 9 | # sed -i 's|(\([0-9]\+ [0-9]\+\))|\1|' bindings.lisp 10 | 11 | # # ------------------------------------------------------------------------------ 12 | # # make our exports 13 | # # ------------------------------------------------------------------------------ 14 | # echo -e "(in-package :nanomsg)\n" > exports.lisp 15 | # cat bindings.lisp | \ 16 | # grep -e '^(\(cffi\|cl\):' | \ 17 | # grep -v 'defcstruct' | \ 18 | # sed 's|^(cffi:defcfun.*" \(#.(lispify[^)]\+)\).*|\1|' | \ 19 | # sed 's|^(cffi:defcenum.*\(#.(lispify[^)]\+)\).*|\1|' | \ 20 | # sed 's|^(cffi:defcunion.*\(#.(lispify[^)]\+)\).*|\1|' | \ 21 | # sed 's|^(cl:defconstant.*\(#.(lispify[^)]\+)\).*|\1|' | \ 22 | # sed 's|^\(.*\)$|(export '"'"'\1)|' \ 23 | # >> exports.lisp 24 | 25 | # # ------------------------------------------------------------------------------ 26 | # # make our accessors 27 | # # ------------------------------------------------------------------------------ 28 | # cat <<-EOFMAC > accessors.lisp 29 | # (in-package :nanomsg.accessors) 30 | 31 | # (defmacro make-accessors (c-struct) 32 | # \`(progn 33 | # ,@(loop for slot-name in (foreign-slot-names (intern (string c-struct) :nanomsg)) 34 | # for accessor-name = (intern (concatenate 'string (symbol-name c-struct) 35 | # "-" 36 | # (symbol-name slot-name))) 37 | # append (list \`(defmacro ,accessor-name (ptr) 38 | # (list 'foreign-slot-value ptr '',(intern (string c-struct) :nanomsg) '',slot-name)) 39 | # \`(export ',accessor-name :nanomsg.accessors))))) 40 | 41 | # EOFMAC 42 | 43 | # cat bindings.lisp | \ 44 | # grep defcstruct | \ 45 | # sed 's|.*#\.(lispify|(make-accessors #.(nanomsg::lispify|g' | sed 's|$|)|' \ 46 | # >> accessors.lisp 47 | 48 | # sed -i -e s/unsigned-int/int/ bindings.lisp 49 | -------------------------------------------------------------------------------- /swig/poll.h: -------------------------------------------------------------------------------- 1 | /* Compatibility definitions for System V `poll' interface. 2 | Copyright (C) 1994,1996-2001,2004,2005,2006 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, write to the Free 17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 | 02111-1307 USA. */ 19 | 20 | #ifndef _SYS_POLL_H 21 | #define _SYS_POLL_H 1 22 | 23 | #include 24 | 25 | /* Get the platform dependent bits of `poll'. */ 26 | #include 27 | #ifdef __USE_GNU 28 | /* Get the __sigset_t definition. */ 29 | # include 30 | /* Get the timespec definition. */ 31 | # define __need_timespec 32 | # include 33 | #endif 34 | 35 | 36 | /* Type used for the number of file descriptors. */ 37 | typedef unsigned long int nfds_t; 38 | 39 | /* Data structure describing a polling request. */ 40 | struct pollfd 41 | { 42 | int fd; /* File descriptor to poll. */ 43 | short int events; /* Types of events poller cares about. */ 44 | short int revents; /* Types of events that actually occurred. */ 45 | }; 46 | 47 | 48 | 49 | /* Poll the file descriptors described by the NFDS structures starting at 50 | FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for 51 | an event to occur; if TIMEOUT is -1, block until an event occurs. 52 | Returns the number of file descriptors with events, zero if timed out, 53 | or -1 for errors. 54 | 55 | This function is a cancellation point and therefore not marked with 56 | __THROW. */ 57 | extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); 58 | 59 | #ifdef __USE_GNU 60 | /* Like poll, but before waiting the threads signal mask is replaced 61 | with that specified in the fourth parameter. For better usability, 62 | the timeout value is specified using a TIMESPEC object. 63 | 64 | This function is a cancellation point and therefore not marked with 65 | __THROW. */ 66 | extern int ppoll (struct pollfd *__fds, nfds_t __nfds, 67 | __const struct timespec *__timeout, 68 | __const __sigset_t *__ss); 69 | #endif 70 | 71 | 72 | #endif /* sys/poll.h */ 73 | -------------------------------------------------------------------------------- /swig/seq_event.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file include/seq_event.h 3 | * \brief Application interface library for the ALSA driver 4 | * \author Jaroslav Kysela 5 | * \author Abramo Bagnara 6 | * \author Takashi Iwai 7 | * \date 1998-2001 8 | * 9 | * Application interface library for the ALSA driver 10 | */ 11 | /* 12 | * This library is free software; you can redistribute it and/or modify 13 | * it under the terms of the GNU Lesser General Public License as 14 | * published by the Free Software Foundation; either version 2.1 of 15 | * the License, or (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU Lesser General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU Lesser General Public 23 | * License along with this library; if not, write to the Free Software 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 | * 26 | */ 27 | 28 | #ifndef __ALSA_SEQ_EVENT_H 29 | #define __ALSA_SEQ_EVENT_H 30 | 31 | /** 32 | * \defgroup SeqEvents Sequencer Event Definitions 33 | * Sequencer Event Definitions 34 | * \ingroup Sequencer 35 | * \{ 36 | */ 37 | 38 | /** 39 | * Sequencer event data type 40 | */ 41 | typedef unsigned char snd_seq_event_type_t; 42 | 43 | /** Sequencer event type */ 44 | enum snd_seq_event_type { 45 | /** system status; event data type = #snd_seq_result_t */ 46 | SND_SEQ_EVENT_SYSTEM = 0, 47 | /** returned result status; event data type = #snd_seq_result_t */ 48 | SND_SEQ_EVENT_RESULT, 49 | 50 | /** note on and off with duration; event data type = #snd_seq_ev_note_t */ 51 | SND_SEQ_EVENT_NOTE = 5, 52 | /** note on; event data type = #snd_seq_ev_note_t */ 53 | SND_SEQ_EVENT_NOTEON, 54 | /** note off; event data type = #snd_seq_ev_note_t */ 55 | SND_SEQ_EVENT_NOTEOFF, 56 | /** key pressure change (aftertouch); event data type = #snd_seq_ev_note_t */ 57 | SND_SEQ_EVENT_KEYPRESS, 58 | 59 | /** controller; event data type = #snd_seq_ev_ctrl_t */ 60 | SND_SEQ_EVENT_CONTROLLER = 10, 61 | /** program change; event data type = #snd_seq_ev_ctrl_t */ 62 | SND_SEQ_EVENT_PGMCHANGE, 63 | /** channel pressure; event data type = #snd_seq_ev_ctrl_t */ 64 | SND_SEQ_EVENT_CHANPRESS, 65 | /** pitchwheel; event data type = #snd_seq_ev_ctrl_t; data is from -8192 to 8191) */ 66 | SND_SEQ_EVENT_PITCHBEND, 67 | /** 14 bit controller value; event data type = #snd_seq_ev_ctrl_t */ 68 | SND_SEQ_EVENT_CONTROL14, 69 | /** 14 bit NRPN; event data type = #snd_seq_ev_ctrl_t */ 70 | SND_SEQ_EVENT_NONREGPARAM, 71 | /** 14 bit RPN; event data type = #snd_seq_ev_ctrl_t */ 72 | SND_SEQ_EVENT_REGPARAM, 73 | 74 | /** SPP with LSB and MSB values; event data type = #snd_seq_ev_ctrl_t */ 75 | SND_SEQ_EVENT_SONGPOS = 20, 76 | /** Song Select with song ID number; event data type = #snd_seq_ev_ctrl_t */ 77 | SND_SEQ_EVENT_SONGSEL, 78 | /** midi time code quarter frame; event data type = #snd_seq_ev_ctrl_t */ 79 | SND_SEQ_EVENT_QFRAME, 80 | /** SMF Time Signature event; event data type = #snd_seq_ev_ctrl_t */ 81 | SND_SEQ_EVENT_TIMESIGN, 82 | /** SMF Key Signature event; event data type = #snd_seq_ev_ctrl_t */ 83 | SND_SEQ_EVENT_KEYSIGN, 84 | 85 | /** MIDI Real Time Start message; event data type = #snd_seq_ev_queue_control_t */ 86 | SND_SEQ_EVENT_START = 30, 87 | /** MIDI Real Time Continue message; event data type = #snd_seq_ev_queue_control_t */ 88 | SND_SEQ_EVENT_CONTINUE, 89 | /** MIDI Real Time Stop message; event data type = #snd_seq_ev_queue_control_t */ 90 | SND_SEQ_EVENT_STOP, 91 | /** Set tick queue position; event data type = #snd_seq_ev_queue_control_t */ 92 | SND_SEQ_EVENT_SETPOS_TICK, 93 | /** Set real-time queue position; event data type = #snd_seq_ev_queue_control_t */ 94 | SND_SEQ_EVENT_SETPOS_TIME, 95 | /** (SMF) Tempo event; event data type = #snd_seq_ev_queue_control_t */ 96 | SND_SEQ_EVENT_TEMPO, 97 | /** MIDI Real Time Clock message; event data type = #snd_seq_ev_queue_control_t */ 98 | SND_SEQ_EVENT_CLOCK, 99 | /** MIDI Real Time Tick message; event data type = #snd_seq_ev_queue_control_t */ 100 | SND_SEQ_EVENT_TICK, 101 | /** Queue timer skew; event data type = #snd_seq_ev_queue_control_t */ 102 | SND_SEQ_EVENT_QUEUE_SKEW, 103 | /** Sync position changed; event data type = #snd_seq_ev_queue_control_t */ 104 | SND_SEQ_EVENT_SYNC_POS, 105 | 106 | /** Tune request; event data type = none */ 107 | SND_SEQ_EVENT_TUNE_REQUEST = 40, 108 | /** Reset to power-on state; event data type = none */ 109 | SND_SEQ_EVENT_RESET, 110 | /** Active sensing event; event data type = none */ 111 | SND_SEQ_EVENT_SENSING, 112 | 113 | /** Echo-back event; event data type = any type */ 114 | SND_SEQ_EVENT_ECHO = 50, 115 | /** OSS emulation raw event; event data type = any type */ 116 | SND_SEQ_EVENT_OSS, 117 | 118 | /** New client has connected; event data type = #snd_seq_addr_t */ 119 | SND_SEQ_EVENT_CLIENT_START = 60, 120 | /** Client has left the system; event data type = #snd_seq_addr_t */ 121 | SND_SEQ_EVENT_CLIENT_EXIT, 122 | /** Client status/info has changed; event data type = #snd_seq_addr_t */ 123 | SND_SEQ_EVENT_CLIENT_CHANGE, 124 | /** New port was created; event data type = #snd_seq_addr_t */ 125 | SND_SEQ_EVENT_PORT_START, 126 | /** Port was deleted from system; event data type = #snd_seq_addr_t */ 127 | SND_SEQ_EVENT_PORT_EXIT, 128 | /** Port status/info has changed; event data type = #snd_seq_addr_t */ 129 | SND_SEQ_EVENT_PORT_CHANGE, 130 | 131 | /** Ports connected; event data type = #snd_seq_connect_t */ 132 | SND_SEQ_EVENT_PORT_SUBSCRIBED, 133 | /** Ports disconnected; event data type = #snd_seq_connect_t */ 134 | SND_SEQ_EVENT_PORT_UNSUBSCRIBED, 135 | 136 | /** user-defined event; event data type = any (fixed size) */ 137 | SND_SEQ_EVENT_USR0 = 90, 138 | /** user-defined event; event data type = any (fixed size) */ 139 | SND_SEQ_EVENT_USR1, 140 | /** user-defined event; event data type = any (fixed size) */ 141 | SND_SEQ_EVENT_USR2, 142 | /** user-defined event; event data type = any (fixed size) */ 143 | SND_SEQ_EVENT_USR3, 144 | /** user-defined event; event data type = any (fixed size) */ 145 | SND_SEQ_EVENT_USR4, 146 | /** user-defined event; event data type = any (fixed size) */ 147 | SND_SEQ_EVENT_USR5, 148 | /** user-defined event; event data type = any (fixed size) */ 149 | SND_SEQ_EVENT_USR6, 150 | /** user-defined event; event data type = any (fixed size) */ 151 | SND_SEQ_EVENT_USR7, 152 | /** user-defined event; event data type = any (fixed size) */ 153 | SND_SEQ_EVENT_USR8, 154 | /** user-defined event; event data type = any (fixed size) */ 155 | SND_SEQ_EVENT_USR9, 156 | 157 | /** system exclusive data (variable length); event data type = #snd_seq_ev_ext_t */ 158 | SND_SEQ_EVENT_SYSEX = 130, 159 | /** error event; event data type = #snd_seq_ev_ext_t */ 160 | SND_SEQ_EVENT_BOUNCE, 161 | /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ 162 | SND_SEQ_EVENT_USR_VAR0 = 135, 163 | /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ 164 | SND_SEQ_EVENT_USR_VAR1, 165 | /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ 166 | SND_SEQ_EVENT_USR_VAR2, 167 | /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ 168 | SND_SEQ_EVENT_USR_VAR3, 169 | /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ 170 | SND_SEQ_EVENT_USR_VAR4, 171 | 172 | /** NOP; ignored in any case */ 173 | SND_SEQ_EVENT_NONE = 255 174 | }; 175 | 176 | 177 | /** Sequencer event address */ 178 | typedef struct snd_seq_addr { 179 | unsigned char client; /**< Client id */ 180 | unsigned char port; /**< Port id */ 181 | } snd_seq_addr_t; 182 | 183 | /** Connection (subscription) between ports */ 184 | typedef struct snd_seq_connect { 185 | snd_seq_addr_t sender; /**< sender address */ 186 | snd_seq_addr_t dest; /**< destination address */ 187 | } snd_seq_connect_t; 188 | 189 | 190 | /** Real-time data record */ 191 | typedef struct snd_seq_real_time { 192 | unsigned int tv_sec; /**< seconds */ 193 | unsigned int tv_nsec; /**< nanoseconds */ 194 | } snd_seq_real_time_t; 195 | 196 | /** (MIDI) Tick-time data record */ 197 | typedef unsigned int snd_seq_tick_time_t; 198 | 199 | /** unioned time stamp */ 200 | typedef union snd_seq_timestamp { 201 | snd_seq_tick_time_t tick; /**< tick-time */ 202 | struct snd_seq_real_time time; /**< real-time */ 203 | } snd_seq_timestamp_t; 204 | 205 | 206 | /** 207 | * Event mode flags 208 | * 209 | * NOTE: only 8 bits available! 210 | */ 211 | #define SND_SEQ_TIME_STAMP_TICK (0<<0) /**< timestamp in clock ticks */ 212 | #define SND_SEQ_TIME_STAMP_REAL (1<<0) /**< timestamp in real time */ 213 | #define SND_SEQ_TIME_STAMP_MASK (1<<0) /**< mask for timestamp bits */ 214 | 215 | #define SND_SEQ_TIME_MODE_ABS (0<<1) /**< absolute timestamp */ 216 | #define SND_SEQ_TIME_MODE_REL (1<<1) /**< relative to current time */ 217 | #define SND_SEQ_TIME_MODE_MASK (1<<1) /**< mask for time mode bits */ 218 | 219 | #define SND_SEQ_EVENT_LENGTH_FIXED (0<<2) /**< fixed event size */ 220 | #define SND_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /**< variable event size */ 221 | #define SND_SEQ_EVENT_LENGTH_VARUSR (2<<2) /**< variable event size - user memory space */ 222 | #define SND_SEQ_EVENT_LENGTH_MASK (3<<2) /**< mask for event length bits */ 223 | 224 | #define SND_SEQ_PRIORITY_NORMAL (0<<4) /**< normal priority */ 225 | #define SND_SEQ_PRIORITY_HIGH (1<<4) /**< event should be processed before others */ 226 | #define SND_SEQ_PRIORITY_MASK (1<<4) /**< mask for priority bits */ 227 | 228 | 229 | /** Note event */ 230 | typedef struct snd_seq_ev_note { 231 | unsigned char channel; /**< channel number */ 232 | unsigned char note; /**< note */ 233 | unsigned char velocity; /**< velocity */ 234 | unsigned char off_velocity; /**< note-off velocity; only for #SND_SEQ_EVENT_NOTE */ 235 | unsigned int duration; /**< duration until note-off; only for #SND_SEQ_EVENT_NOTE */ 236 | } snd_seq_ev_note_t; 237 | 238 | /** Controller event */ 239 | typedef struct snd_seq_ev_ctrl { 240 | unsigned char channel; /**< channel number */ 241 | unsigned char unused[3]; /**< reserved */ 242 | unsigned int param; /**< control parameter */ 243 | signed int value; /**< control value */ 244 | } snd_seq_ev_ctrl_t; 245 | 246 | /** generic set of bytes (12x8 bit) */ 247 | typedef struct snd_seq_ev_raw8 { 248 | unsigned char d[12]; /**< 8 bit value */ 249 | } snd_seq_ev_raw8_t; 250 | 251 | /** generic set of integers (3x32 bit) */ 252 | typedef struct snd_seq_ev_raw32 { 253 | unsigned int d[3]; /**< 32 bit value */ 254 | } snd_seq_ev_raw32_t; 255 | 256 | /** external stored data */ 257 | typedef struct snd_seq_ev_ext { 258 | unsigned int len; /**< length of data */ 259 | void *ptr; /**< pointer to data (note: can be 64-bit) */ 260 | } snd_seq_ev_ext_t; 261 | 262 | /** Result events */ 263 | typedef struct snd_seq_result { 264 | int event; /**< processed event type */ 265 | int result; /**< status */ 266 | } snd_seq_result_t; 267 | 268 | /** Queue skew values */ 269 | typedef struct snd_seq_queue_skew { 270 | unsigned int value; /**< skew value */ 271 | unsigned int base; /**< skew base */ 272 | } snd_seq_queue_skew_t; 273 | 274 | /** queue timer control */ 275 | typedef struct snd_seq_ev_queue_control { 276 | unsigned char queue; /**< affected queue */ 277 | unsigned char unused[3]; /**< reserved */ 278 | union { 279 | signed int value; /**< affected value (e.g. tempo) */ 280 | snd_seq_timestamp_t time; /**< time */ 281 | unsigned int position; /**< sync position */ 282 | snd_seq_queue_skew_t skew; /**< queue skew */ 283 | unsigned int d32[2]; /**< any data */ 284 | unsigned char d8[8]; /**< any data */ 285 | } param; /**< data value union */ 286 | } snd_seq_ev_queue_control_t; 287 | 288 | typedef union { 289 | snd_seq_ev_note_t note; /**< note information */ 290 | snd_seq_ev_ctrl_t control; /**< MIDI control information */ 291 | snd_seq_ev_raw8_t raw8; /**< raw8 data */ 292 | snd_seq_ev_raw32_t raw32; /**< raw32 data */ 293 | snd_seq_ev_ext_t ext; /**< external data */ 294 | snd_seq_ev_queue_control_t queue; /**< queue control */ 295 | snd_seq_timestamp_t time; /**< timestamp */ 296 | snd_seq_addr_t addr; /**< address */ 297 | snd_seq_connect_t connect; /**< connect information */ 298 | snd_seq_result_t result; /**< operation result code */ 299 | } snd_seq_event_data; 300 | 301 | /** Sequencer event */ 302 | typedef struct snd_seq_event { 303 | snd_seq_event_type_t type; /**< event type */ 304 | unsigned char flags; /**< event flags */ 305 | unsigned char tag; /**< tag */ 306 | 307 | unsigned char queue; /**< schedule queue */ 308 | snd_seq_timestamp_t time; /**< schedule time */ 309 | 310 | snd_seq_addr_t source; /**< source address */ 311 | snd_seq_addr_t dest; /**< destination address */ 312 | 313 | snd_seq_event_data data; /**< event data... */ 314 | } snd_seq_event_t; 315 | 316 | 317 | /** \} */ 318 | 319 | #endif /* __ALSA_SEQ_EVENT_H */ 320 | 321 | --------------------------------------------------------------------------------