#lang racket/base
(require ffi/vector
ffi/unsafe
(rename-in racket/contract [-> c->])
racket/runtime-path
racket/place
"mzrt-sema.rkt"
"signalling.rkt"
"portaudio.rkt")
(define-runtime-path lib "lib/")
(define (frames? n)
(and (exact-integer? n)
(<= 0 n)))
(define nat? exact-nonnegative-integer?)
(define false? not)
(provide/contract
[make-copying-info (c-> s16vector? nat? (or/c false? nat?) cpointer?)]
[copying-callback cpointer?]
[copying-info-free cpointer?]
[make-streaming-info (c-> integer? (list/c cpointer? place?))]
[buffer-if-waiting (c-> cpointer? (or/c false? (list/c cpointer?
integer?
integer?
procedure?)))]
[streaming-callback cpointer?]
[stream-fails (c-> cpointer? integer?)]
[streaming-info-free cpointer?])
(define channels 2)
(define s16max 32767)
(define s16-bytes 2)
(define-cstruct _copying-rec
([sound _pointer]
[cur-sample _ulong]
[num-samples _ulong]))
(define (make-copying-info s16vec start-frame maybe-stop-frame)
(define stop-frame (or maybe-stop-frame
(/ (s16vector-length s16vec) channels)))
(define frames-to-copy (- stop-frame start-frame))
(define copied-sound (dll-malloc (* (ctype-sizeof _sint16) (* channels frames-to-copy))))
(define src-ptr (ptr-add (s16vector->cpointer s16vec)
(* channels start-frame)
_sint16))
(memcpy copied-sound src-ptr (* channels frames-to-copy) _sint16)
(define copying-info (cast (dll-malloc (ctype-sizeof _copying-rec))
_pointer
_copying-rec-pointer))
(set-copying-rec-sound! copying-info copied-sound)
(set-copying-rec-cur-sample! copying-info 0)
(set-copying-rec-num-samples! copying-info (* frames-to-copy channels))
copying-info)
(define-cstruct _array-hack
([a _pointer]
[b _pointer]
[c _pointer]
[d _pointer]))
(define-cstruct _array-hack-2
([a _int]
[b _int]
[c _int]
[d _int]))
(define (hack-array-ref array idx)
(define array-reffer
(case idx
[(0) array-hack-a]
[(1) array-hack-b]
[(2) array-hack-c]
[(3) array-hack-d]))
(array-reffer array))
(define (hack-array-ref-2 array idx)
(define array-reffer
(case idx
[(0) array-hack-2-a]
[(1) array-hack-2-b]
[(2) array-hack-2-c]
[(3) array-hack-2-d]))
(array-reffer array))
(define streambufs 4)
(define-cstruct _stream-rec
([buffer-frames _int]
[buffers _array-hack (_array _pointer streambufs)]
[buf-numbers _array-hack-2 (_array _int streambufs)]
[last-used _int]
[fault-count _int]
[buffer-needed-sema _pointer]))
(define (stream-fails stream-rec)
(stream-rec-fault-count stream-rec))
(define (make-streaming-info buffer-frames)
(define mzrt-sema (mzrt-sema-create 0))
(define info (cast (dll-malloc (ctype-sizeof _stream-rec))
_pointer
_stream-rec-pointer))
(set-stream-rec-buffer-frames! info buffer-frames)
(define buffers (stream-rec-buffers info))
(define buffer-nums (stream-rec-buf-numbers info))
(for ([i (in-range streambufs)])
(array-set! buffers
i
(dll-malloc (* (ctype-sizeof _sint16) (* buffer-frames channels))))
(array-set! buffer-nums i -1))
(set-array-hack-a! buffers
(dll-malloc (* (ctype-sizeof _sint16) buffer-frames channels)))
(set-array-hack-b! buffers
(dll-malloc (* (ctype-sizeof _sint16) buffer-frames channels)))
(set-array-hack-c! buffers
(dll-malloc (* (ctype-sizeof _sint16) buffer-frames channels)))
(set-array-hack-d! buffers
(dll-malloc (* (ctype-sizeof _sint16) buffer-frames channels)))
(set-array-hack-2-a! buffer-nums -1)
(set-array-hack-2-b! buffer-nums -1)
(set-array-hack-2-c! buffer-nums -1)
(set-array-hack-2-d! buffer-nums -1)
(set-stream-rec-last-used! info -1)
(set-stream-rec-fault-count! info 0)
(set-stream-rec-buffer-needed-sema! info mzrt-sema)
(define listening-place (mzrt-sema-listener mzrt-sema))
(list info listening-place))
(define (buffer-if-waiting stream-info)
(define next-to-be-used (add1 (stream-rec-last-used stream-info)))
(define buf-numbers (stream-rec-buf-numbers stream-info))
(define buffer-index (modulo next-to-be-used streambufs))
(cond [(= (hack-array-ref-2 buf-numbers buffer-index)
next-to-be-used)
#f]
[else (list
(hack-array-ref (stream-rec-buffers stream-info)
buffer-index)
(stream-rec-buffer-frames stream-info)
next-to-be-used
(lambda ()
(array-set! buf-numbers
buffer-index
next-to-be-used)
(define updater!
(case buffer-index
[(0) set-array-hack-2-a!]
[(1) set-array-hack-2-b!]
[(2) set-array-hack-2-c!]
[(3) set-array-hack-2-d!]))
(updater! buf-numbers next-to-be-used)))]))
(define callbacks-lib (ffi-lib (build-path lib
(system-library-subpath)
"callbacks")))
(define-cstruct _bogus-struct
([datum _uint16]))
(define copying-callback
(cast
(get-ffi-obj "copyingCallback" callbacks-lib _bogus-struct)
_bogus-struct-pointer
_pa-stream-callback))
(define streaming-callback
(cast
(get-ffi-obj "streamingCallback" callbacks-lib _bogus-struct)
_bogus-struct-pointer
_pa-stream-callback))
(define copying-info-free
(cast
(get-ffi-obj "freeCopyingInfo" callbacks-lib _bogus-struct)
_bogus-struct-pointer
_pa-stream-finished-callback))
(define streaming-info-free
(cast
(get-ffi-obj "freeStreamingInfo" callbacks-lib _bogus-struct)
_bogus-struct-pointer
_pa-stream-finished-callback))
(define dll-malloc
(get-ffi-obj "dll_malloc" callbacks-lib (_fun _uint -> _pointer)))