diff --git a/libao-async-ffi.rkt b/libao-async-ffi.rkt index 983c2ca..6734c35 100644 --- a/libao-async-ffi.rkt +++ b/libao-async-ffi.rkt @@ -21,8 +21,8 @@ (define _BufferType_t (_enum '(ao = 1 flac = 2 - mpg123 = 3 - ao_ogg = 4 + mp3 = 3 + ogg = 4 ))) ;#define AO_FMT_LITTLE 1 @@ -63,12 +63,15 @@ ;extern void ao_stop_async(void *handle); (define-libao-async ao_stop_async(_fun _libao-async-handle-pointer -> _void)) -;extern void ao_play_async(void *handle, double at_second, double music_duration, int buf_size, void *mem, BufferInfo_t info); -(define-libao-async ao_play_async(_fun _libao-async-handle-pointer _double _double _uint32 _pointer _BufferInfo_t -> _void)) +;extern void ao_play_async(void *handle, int music_id, double at_second, double music_duration, int buf_size, void *mem, BufferInfo_t info); +(define-libao-async ao_play_async(_fun _libao-async-handle-pointer _integer _double _double _uint32 _pointer _BufferInfo_t -> _void)) ;extern double ao_is_at_second_async(void *handle); (define-libao-async ao_is_at_second_async(_fun _libao-async-handle-pointer -> _double)) +;extern int ao_is_at_music_id_async(void *handle); +(define-libao-async ao_is_at_music_id_async (_fun _libao-async-handle-pointer -> _integer)) + ;extern double ao_music_duration_async(void *handle); (define-libao-async ao_music_duration_async(_fun _libao-async-handle-pointer -> _double)) diff --git a/libao.rkt b/libao.rkt index b92d610..f4f0af7 100644 --- a/libao.rkt +++ b/libao.rkt @@ -6,6 +6,7 @@ ffi/unsafe/custodian data/queue "private/utils.rkt" + (prefix-in rc: racket/contract) ) (provide ao-open-live @@ -13,10 +14,17 @@ ao-close ao-at-second ao-music-duration + ao-at-music-id ao-bufsize-async ao-clear-async ao-pause - ao-valid? + ao-valid? + ao-valid-bits? + ao-valid-rate? + ao-valid-channels? + ao-valid-format? + ao-handle? + ao-supported-music-format? ) (define device-number 1) @@ -34,10 +42,42 @@ ) +(define (ao-supported-music-format? f) + (and (symbol? f) + (or (eq? f 'flac) + (eq? f 'mp3) + (eq? f 'ao)))) + + (define (bytes-for-bits bits) (/ bits 8)) -(define (ao-open-live bits rate channels byte-format) +(define (ao-valid-bits? bits) + (and (integer? bits) (or + (= bits 8) + (= bits 16) + (= bits 24) + (= bits 32)) + ) + ) + +(define (ao-valid-rate? rate) + (and (integer? rate) + (not (eq? (memq rate '(8000 11025 16000 22050 44100 + 48000 88200 96000 1764000 + 192000 352800 384000)) #f)))) + +(define (ao-valid-channels? c) + (and (integer? c) + (>= 1 c))) + +(define (ao-valid-format? f) + (or (eq? f 'little-endian) + (eq? f 'big-endian) + (eq? f 'native-endian))) + +(rc:define/contract (ao-open-live bits rate channels byte-format) + (rc:-> ao-valid-bits? ao-valid-rate? ao-valid-channels? ao-valid-format? ao-handle?) (let ((handle (make-ao-handle device-number))) (fin:register-finalizer handle @@ -69,18 +109,27 @@ ) ) -(define (ao-close handle) - (unless (eq? (ao-handle-async-player handle) #f) - (info-sound "ao-close - closing handle") - (ffi:ao_stop_async (ao-handle-async-player handle)) - (set-ao-handle-async-player! handle #f) - ) +(rc:define/contract (ao-close handle) + (rc:-> ao-handle? void?) + (void + (unless (eq? (ao-handle-async-player handle) #f) + (info-sound "ao-close - closing handle") + (ffi:ao_stop_async (ao-handle-async-player handle)) + (set-ao-handle-async-player! handle #f) + ) + ) ) (define (ao-valid? handle) - (not (eq? (ao-handle-async-player handle) #f))) + (and (ao-handle? handle) + (not (eq? (ao-handle-async-player handle) #f))) + ) -(define (ao-play handle at-time-in-s music-duration-s buffer buf-len buf-type) +(define (any? x) + #t) + +(rc:define/contract (ao-play handle music-id at-time-in-s music-duration-s buffer buf-len buf-type) + (rc:-> ao-handle? integer? number? number? any? integer? ao-supported-music-format? void?) (let* ((bytes-per-sample (ao-handle-bytes-per-sample handle)) (bits (ao-handle-bits handle)) (rate (ao-handle-rate handle)) @@ -88,37 +137,48 @@ (endianess (ao-handle-byte-format handle)) (buf-info (ffi:make-BufferInfo_t buf-type bits rate channels endianess)) ) - ;(dbg-sound "ao-play ~a ~a" at-time-in-s music-duration-s) (unless (ao-valid? handle) (err-sound "Cannot play on an invalid ao-device") (error "Cannot play on an invalid ao-device")) (ffi:ao_play_async (ao-handle-async-player handle) + music-id (exact->inexact at-time-in-s) (exact->inexact music-duration-s) buf-len buffer buf-info) + ) ) -(define (ao-pause handle pause) +(rc:define/contract (ao-pause handle pause) + (rc:-> ao-handle? boolean? void?) (dbg-sound "ao-pause ~a" pause) (ffi:ao_pause_async (ao-handle-async-player handle) (if (eq? pause #f) 0 1)) ) -(define (ao-at-second handle) +(rc:define/contract (ao-at-second handle) + (rc:-> ao-handle? number?) (ffi:ao_is_at_second_async (ao-handle-async-player handle)) ) + +(rc:define/contract (ao-at-music-id handle) + (rc:-> ao-handle? integer?) + (ffi:ao_is_at_music_id_async (ao-handle-async-player handle)) + ) -(define (ao-music-duration handle) +(rc:define/contract (ao-music-duration handle) + (rc:-> ao-handle? number?) (ffi:ao_music_duration_async (ao-handle-async-player handle)) ) -(define (ao-bufsize-async handle) +(rc:define/contract (ao-bufsize-async handle) + (rc:-> ao-handle? integer?) (ffi:ao_bufsize_async (ao-handle-async-player handle)) ) (define (ao-clear-async handle) + (rc:-> ao-handle? void?) (ffi:ao_clear_async (ao-handle-async-player handle)) )