osc/devices/transmitter.lisp
2022-08-24 18:25:04 +02:00

99 lines
3.8 KiB
Common Lisp

(cl:in-package #:osc)
;; Only UDP devices can be transmitters.
(defun make-osc-transmitter (&key debug-mode cleanup-fun)
(make-instance 'osc-transmitter-udp
:debug-mode debug-mode
:cleanup-fun cleanup-fun))
(defgeneric connect (osc-transmitter host-port &key host-address
host-name port)
(:method-combination progn :most-specific-last))
(defmethod connect progn ((transmitter osc-transmitter) host-port
&key (host-address nil addr)
(host-name "localhost" name) port)
(when (and addr name)
(error "Supplied both :host-address and :host-name to connect"))
(cond (addr
(when (typep host-address 'string)
(setf host-address
(sb-bsd-sockets:make-inet-address host-address))))
(t
(setf host-address
(sb-bsd-sockets:host-ent-address
(sb-bsd-sockets:get-host-by-name
host-name)))))
(if (not (device-active-p transmitter))
(progn
(let ((socket (make-socket (protocol transmitter))))
(if port
(socket-bind socket #(127 0 0 1) port)
(socket-bind socket))
(socket-connect socket host-address host-port)
(socket-make-stream socket
:input nil :output t
:element-type '(unsigned-byte 8)
:buffering :full)
(set-socket socket transmitter))
(when (debug-mode transmitter)
(format t "~%Device connected: ~A~%~A -> ~A~%"
(name transmitter) #\Tab
(make-addr+port-string (peer-address transmitter)
(peer-port transmitter)))))
(warn "Already connected"))
transmitter)
(defmethod quit ((transmitter osc-transmitter-udp))
(if (device-active-p transmitter)
(osc-device-cleanup transmitter)
(warn "Not connected: ~A" (name transmitter))))
;;;=====================================================================
;;; Sending functions
;;;=====================================================================
(defmacro osc-write-to-stream (stream &body msg)
`(progn (write-sequence ,@msg ,stream)
(finish-output ,stream)))
(defgeneric send (transmitter data)
(:method ((transmitter osc-transmitter) data)
(let ((bytes (encode-osc-data data)))
(osc-write-to-stream
(slot-value (socket transmitter) 'stream) bytes))))
(defgeneric send-msg (transmitter command &rest args)
(:method ((transmitter osc-transmitter) command &rest args)
(let ((message (make-message command args)))
(send transmitter message))))
(defgeneric send-bundle (transmitter timetag command &rest args)
(:method ((transmitter osc-transmitter) timetag command &rest args)
(let ((bundle (bundle timetag
(make-message command args))))
(send transmitter bundle))))
;; Unconnected sending (UDP only)
(defgeneric send-to (transmitter address port data)
(:method ((transmitter osc-transmitter-udp) address port data)
(socket-send (socket transmitter)
(encode-osc-data data) nil
:address (list address port))))
(defgeneric send-msg-to (transmitter address port command &rest args)
(:method ((transmitter osc-transmitter-udp) address port command
&rest args)
(let ((message (make-message command args)))
(send-to transmitter address port message))))
(defgeneric send-bundle-to (transmitter address port timetag command
&rest args)
(:method ((transmitter osc-transmitter-udp) address port timetag
command &rest args)
(let ((bundle (bundle timetag
(make-message command args))))
(send-to transmitter address port bundle))))