changed async library. Flac conversion in C
This commit is contained in:
@@ -47,13 +47,12 @@
|
|||||||
(channels (hash-ref h 'channels))
|
(channels (hash-ref h 'channels))
|
||||||
(block-size (hash-ref h 'blocksize)))
|
(block-size (hash-ref h 'blocksize)))
|
||||||
(hash-set! h 'duration (flac-duration handle))
|
(hash-set! h 'duration (flac-duration handle))
|
||||||
(let ((buffers (ffi 'get-buffers buffer channels block-size)))
|
(set! last-buffer buffer)
|
||||||
(set! last-buffer buffers)
|
(set! last-buf-len block-size)
|
||||||
(set! last-buf-len (hash-ref h 'blocksize))
|
|
||||||
(hash-set! kinds type #t)
|
(hash-set! kinds type #t)
|
||||||
(when (procedure? cb-audio)
|
(when (procedure? cb-audio)
|
||||||
(cb-audio h buffers))
|
(cb-audio h buffer block-size))
|
||||||
))
|
)
|
||||||
#t
|
#t
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -15,22 +15,56 @@
|
|||||||
ao_bufsize_async
|
ao_bufsize_async
|
||||||
ao_clear_async
|
ao_clear_async
|
||||||
ao_pause_async
|
ao_pause_async
|
||||||
|
make-BufferInfo_t
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(define _BufferType_t
|
||||||
|
(_enum '(ao = 1
|
||||||
|
flac = 2
|
||||||
|
mpg123 = 3
|
||||||
|
ao_ogg = 4
|
||||||
|
)))
|
||||||
|
|
||||||
|
;#define AO_FMT_LITTLE 1
|
||||||
|
;#define AO_FMT_BIG 2
|
||||||
|
;#define AO_FMT_NATIVE 4
|
||||||
|
|
||||||
|
(define _Endian_t
|
||||||
|
(_enum '(little-endian = 1
|
||||||
|
big-endian = 2
|
||||||
|
native-endian = 4
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(define-cstruct _BufferInfo_t
|
||||||
|
(
|
||||||
|
[type _BufferType_t]
|
||||||
|
[sample_bits _int]
|
||||||
|
[sample_rate _int]
|
||||||
|
[channels _int]
|
||||||
|
[endiannes _Endian_t]
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
(define lib (get-lib '("ao-play-async" "libao-play-async") '(#f)))
|
(define lib (get-lib '("ao-play-async" "libao-play-async") '(#f)))
|
||||||
|
;(define lib (ffi-lib "/home/hans/src/racket/racket-sound-lib/lib/linux-x86_64/libao-play-async.so"))
|
||||||
(define-ffi-definer define-libao-async lib
|
(define-ffi-definer define-libao-async lib
|
||||||
#:default-make-fail make-not-available)
|
#:default-make-fail make-not-available)
|
||||||
|
|
||||||
(define _libao-async-handle-pointer (_cpointer 'ao-async-handle))
|
(define _libao-async-handle-pointer (_cpointer 'ao-async-handle))
|
||||||
|
|
||||||
|
;extern int ao_async_version()
|
||||||
|
(define-libao-async ao_async_version (_fun -> _int))
|
||||||
|
|
||||||
;extern void *ao_create_async(void *ao_device, );
|
;extern void *ao_create_async(void *ao_device, );
|
||||||
(define-libao-async ao_create_async(_fun _pointer _fpointer -> _libao-async-handle-pointer))
|
(define-libao-async ao_create_async(_fun _pointer _fpointer -> _libao-async-handle-pointer))
|
||||||
|
|
||||||
;extern void ao_stop_async(void *handle);
|
;extern void ao_stop_async(void *handle);
|
||||||
(define-libao-async ao_stop_async(_fun _libao-async-handle-pointer -> _void))
|
(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);
|
;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 -> _void))
|
(define-libao-async ao_play_async(_fun _libao-async-handle-pointer _double _double _uint32 _pointer _BufferInfo_t -> _void))
|
||||||
|
|
||||||
;extern double ao_is_at_second_async(void *handle);
|
;extern double ao_is_at_second_async(void *handle);
|
||||||
(define-libao-async ao_is_at_second_async(_fun _libao-async-handle-pointer -> _double))
|
(define-libao-async ao_is_at_second_async(_fun _libao-async-handle-pointer -> _double))
|
||||||
|
|||||||
@@ -14,6 +14,11 @@
|
|||||||
ao_bufsize_async
|
ao_bufsize_async
|
||||||
ao_clear_async
|
ao_clear_async
|
||||||
ao_pause_async
|
ao_pause_async
|
||||||
|
make-ao_buf_info
|
||||||
|
ao_buf_info-type
|
||||||
|
ao_buf_info-sample-bits
|
||||||
|
ao_buf_info-sample-rate
|
||||||
|
ao_buf_info-channels
|
||||||
)
|
)
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -35,6 +40,15 @@
|
|||||||
;; ao-player in os thread
|
;; ao-player in os thread
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(define-struct ao_buffer_info
|
||||||
|
(type
|
||||||
|
sample-bits
|
||||||
|
sample-rate
|
||||||
|
channels
|
||||||
|
)
|
||||||
|
#:transparent
|
||||||
|
)
|
||||||
|
|
||||||
(define-struct ao-shm
|
(define-struct ao-shm
|
||||||
(mutex
|
(mutex
|
||||||
device
|
device
|
||||||
@@ -86,6 +100,7 @@
|
|||||||
(duration (caddr elem))
|
(duration (caddr elem))
|
||||||
(buf-len (cadddr elem))
|
(buf-len (cadddr elem))
|
||||||
(buf (car (cddddr elem)))
|
(buf (car (cddddr elem)))
|
||||||
|
(buf-info (cadr (cddddr elem)))
|
||||||
)
|
)
|
||||||
(mutex-lock (ao-shm-mutex shm))
|
(mutex-lock (ao-shm-mutex shm))
|
||||||
(set-ao-shm-at-second! shm at-second)
|
(set-ao-shm-at-second! shm at-second)
|
||||||
@@ -130,7 +145,7 @@
|
|||||||
(define (ao_stop_async shm)
|
(define (ao_stop_async shm)
|
||||||
(mutex-lock (ao-shm-mutex shm))
|
(mutex-lock (ao-shm-mutex shm))
|
||||||
(ao_clear_async* shm)
|
(ao_clear_async* shm)
|
||||||
(enqueue! (ao-shm-queue shm) (list 'stop 0 0 #f #f))
|
(enqueue! (ao-shm-queue shm) (list 'stop 0 0 #f #f #f))
|
||||||
(os-semaphore-post (ao-shm-queue-sem shm))
|
(os-semaphore-post (ao-shm-queue-sem shm))
|
||||||
(mutex-unlock (ao-shm-mutex shm))
|
(mutex-unlock (ao-shm-mutex shm))
|
||||||
(let ((stopped (λ ()
|
(let ((stopped (λ ()
|
||||||
@@ -149,8 +164,8 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
(define (ao_play_async shm at-second music-duration buf-size buf)
|
(define (ao_play_async shm at-second music-duration buf-size buf buf-info)
|
||||||
(let ((item (list 'play at-second music-duration buf-size buf)))
|
(let ((item (list 'play at-second music-duration buf-size buf buf-info)))
|
||||||
(mutex-lock (ao-shm-mutex shm))
|
(mutex-lock (ao-shm-mutex shm))
|
||||||
(let ((bs (ao-shm-bufsize shm)))
|
(let ((bs (ao-shm-bufsize shm)))
|
||||||
(set-ao-shm-bufsize! shm (+ bs buf-size)))
|
(set-ao-shm-bufsize! shm (+ bs buf-size)))
|
||||||
|
|||||||
110
libao.rkt
110
libao.rkt
@@ -1,11 +1,8 @@
|
|||||||
#lang racket/base
|
#lang racket/base
|
||||||
|
|
||||||
(define libao-async-mode 'ffi) ; 'ffi or 'scheme
|
|
||||||
|
|
||||||
(require "libao-ffi.rkt"
|
(require "libao-ffi.rkt"
|
||||||
(prefix-in fin: finalizer)
|
(prefix-in fin: finalizer)
|
||||||
(prefix-in ffi: "libao-async-ffi.rkt")
|
(prefix-in ffi: "libao-async-ffi.rkt")
|
||||||
(prefix-in scm: "libao-async.rkt")
|
|
||||||
ffi/unsafe
|
ffi/unsafe
|
||||||
data/queue
|
data/queue
|
||||||
"private/utils.rkt"
|
"private/utils.rkt"
|
||||||
@@ -20,23 +17,12 @@
|
|||||||
ao-music-duration
|
ao-music-duration
|
||||||
ao-bufsize-async
|
ao-bufsize-async
|
||||||
ao-clear-async
|
ao-clear-async
|
||||||
ao-set-async-mode!
|
|
||||||
ao-async-mode
|
|
||||||
ao-pause
|
ao-pause
|
||||||
)
|
)
|
||||||
|
|
||||||
(define devices (make-hash))
|
(define devices (make-hash))
|
||||||
(define device-number 1)
|
(define device-number 1)
|
||||||
|
|
||||||
(define (ao-set-async-mode! mode)
|
|
||||||
(if (or (eq? mode 'ffi) (eq? mode 'scheme))
|
|
||||||
(set! libao-async-mode mode)
|
|
||||||
(error "mode must be 'ffi or 'scheme"))
|
|
||||||
mode)
|
|
||||||
|
|
||||||
(define (ao-async-mode)
|
|
||||||
libao-async-mode)
|
|
||||||
|
|
||||||
(define-struct ao-handle (handle-num
|
(define-struct ao-handle (handle-num
|
||||||
[bits #:auto #:mutable]
|
[bits #:auto #:mutable]
|
||||||
[bytes-per-sample #:auto #:mutable]
|
[bytes-per-sample #:auto #:mutable]
|
||||||
@@ -106,9 +92,7 @@
|
|||||||
(set-ao-handle-byte-format! handle endianness)
|
(set-ao-handle-byte-format! handle endianness)
|
||||||
(set-ao-handle-rate! handle rate)
|
(set-ao-handle-rate! handle rate)
|
||||||
(set-ao-handle-channels! handle channels)
|
(set-ao-handle-channels! handle channels)
|
||||||
(if (eq? libao-async-mode 'ffi)
|
|
||||||
(set-ao-handle-async-player! handle (ffi:ao_create_async ao-device ao_play_ptr))
|
(set-ao-handle-async-player! handle (ffi:ao_create_async ao-device ao_play_ptr))
|
||||||
(set-ao-handle-async-player! handle (scm:ao_create_async ao-device)))
|
|
||||||
(hash-set! devices handle-num ao-device)
|
(hash-set! devices handle-num ao-device)
|
||||||
(fin:register-finalizer handle
|
(fin:register-finalizer handle
|
||||||
(lambda (handle)
|
(lambda (handle)
|
||||||
@@ -136,15 +120,8 @@
|
|||||||
'warning-ao-device-already-closed
|
'warning-ao-device-already-closed
|
||||||
(begin
|
(begin
|
||||||
(set-ao-handle-closed! handle #t)
|
(set-ao-handle-closed! handle #t)
|
||||||
(if (eq? libao-async-mode 'ffi)
|
|
||||||
(begin
|
|
||||||
(ffi:ao_clear_async (ao-handle-async-player handle))
|
(ffi:ao_clear_async (ao-handle-async-player handle))
|
||||||
(ffi:ao_stop_async (ao-handle-async-player handle))
|
(ffi:ao_stop_async (ao-handle-async-player handle))
|
||||||
)
|
|
||||||
(begin
|
|
||||||
(scm:ao_clear_async (ao-handle-async-player handle))
|
|
||||||
(scm:ao_stop_async (ao-handle-async-player handle))
|
|
||||||
))
|
|
||||||
(if (eq? ao-device #f)
|
(if (eq? ao-device #f)
|
||||||
'error-ao-device-non-existent
|
'error-ao-device-non-existent
|
||||||
(let ((r (ao_close ao-device)))
|
(let ((r (ao_close ao-device)))
|
||||||
@@ -186,84 +163,67 @@
|
|||||||
(reverse bytes)
|
(reverse bytes)
|
||||||
bytes))))
|
bytes))))
|
||||||
|
|
||||||
(define (ao-play handle at-time-in-s music-duration-s buffer)
|
(define (ao-play handle at-time-in-s music-duration-s buffer buf-len buf-type)
|
||||||
(let* ((bytes-per-sample (ao-handle-bytes-per-sample handle))
|
(let* ((bytes-per-sample (ao-handle-bytes-per-sample handle))
|
||||||
(bits (ao-handle-bits handle))
|
(bits (ao-handle-bits handle))
|
||||||
|
(rate (ao-handle-rate handle))
|
||||||
(channels (ao-handle-channels handle))
|
(channels (ao-handle-channels handle))
|
||||||
(endianess (ao-handle-byte-format handle))
|
(endianess (ao-handle-byte-format handle))
|
||||||
(buf-len (vector-length (car buffer)))
|
;(audio-buf-len (* channels bytes-per-sample buf-len))
|
||||||
(audio-buf-len (* channels bytes-per-sample buf-len))
|
;(audio (malloc 'atomic audio-buf-len))
|
||||||
(audio (if (eq? libao-async-mode 'ffi)
|
;(get-sample (lambda (k channel)
|
||||||
(malloc 'atomic audio-buf-len)
|
; (let ((chan-buf (list-ref buffer channel)))
|
||||||
(malloc 'atomic audio-buf-len))) ; was: 'raw
|
; (vector-ref chan-buf k))))
|
||||||
(get-sample (lambda (k channel)
|
|
||||||
(let ((chan-buf (list-ref buffer channel)))
|
|
||||||
(vector-ref chan-buf k))))
|
|
||||||
)
|
)
|
||||||
(letrec ((i 0)
|
;(letrec ((i 0)
|
||||||
(fill (lambda (k channel)
|
; (fill (lambda (k channel)
|
||||||
(if (< k buf-len)
|
; (if (< k buf-len)
|
||||||
(if (< channel channels)
|
; (if (< channel channels)
|
||||||
(let* ((sample (get-sample k channel))
|
; (let* ((sample (get-sample k channel))
|
||||||
(bytes (make-sample-bytes sample bytes-per-sample endianess))
|
; (bytes (make-sample-bytes sample bytes-per-sample endianess))
|
||||||
)
|
; )
|
||||||
(for-each (lambda (byte)
|
; (for-each (lambda (byte)
|
||||||
(ptr-set! audio _byte i byte)
|
; (ptr-set! audio _byte i byte)
|
||||||
(set! i (+ i 1)))
|
; (set! i (+ i 1)))
|
||||||
bytes)
|
; bytes)
|
||||||
;; process sample
|
; ;; process sample
|
||||||
(fill k (+ channel 1)))
|
; (fill k (+ channel 1)))
|
||||||
(fill (+ k 1) 0))
|
; (fill (+ k 1) 0))
|
||||||
'filled))
|
; 'filled))
|
||||||
))
|
; ))
|
||||||
(fill 0 0)
|
; (fill 0 0)
|
||||||
(if (eq? libao-async-mode 'ffi)
|
|
||||||
|
(let ((buf-info (ffi:make-BufferInfo_t buf-type bits rate channels endianess)))
|
||||||
|
;(displayln "Calling ao_play_async")
|
||||||
(ffi:ao_play_async (ao-handle-async-player handle)
|
(ffi:ao_play_async (ao-handle-async-player handle)
|
||||||
(exact->inexact at-time-in-s)
|
(exact->inexact at-time-in-s)
|
||||||
(exact->inexact music-duration-s)
|
(exact->inexact music-duration-s)
|
||||||
audio-buf-len
|
buf-len
|
||||||
audio)
|
buffer
|
||||||
(scm:ao_play_async (ao-handle-async-player handle)
|
buf-info)
|
||||||
(exact->inexact at-time-in-s)
|
|
||||||
(exact->inexact music-duration-s)
|
|
||||||
audio-buf-len
|
|
||||||
audio)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
;(let* ((handle-num (ao-handle-handle-num handle))
|
|
||||||
; (ao-device (hash-ref devices handle-num #f)))
|
|
||||||
; (if (eq? ao-device #f)
|
|
||||||
; (error "No device for this handle")
|
|
||||||
; (ao_play ao-device audio audio-buf-len))) )
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
(define (ao-pause handle pause)
|
(define (ao-pause handle pause)
|
||||||
(if (eq? libao-async-mode 'ffi)
|
|
||||||
(ffi:ao_pause_async (ao-handle-async-player handle) (if (eq? pause #f) 0 1))
|
(ffi:ao_pause_async (ao-handle-async-player handle) (if (eq? pause #f) 0 1))
|
||||||
(scm:ao_pause_async (ao-handle-async-player handle) pause)
|
)
|
||||||
))
|
|
||||||
|
|
||||||
(define (ao-at-second handle)
|
(define (ao-at-second handle)
|
||||||
(if (eq? libao-async-mode 'ffi)
|
|
||||||
(ffi:ao_is_at_second_async (ao-handle-async-player handle))
|
(ffi:ao_is_at_second_async (ao-handle-async-player handle))
|
||||||
(scm:ao_is_at_second_async (ao-handle-async-player handle))))
|
)
|
||||||
|
|
||||||
(define (ao-music-duration handle)
|
(define (ao-music-duration handle)
|
||||||
(if (eq? libao-async-mode 'ffi)
|
|
||||||
(ffi:ao_music_duration_async (ao-handle-async-player handle))
|
(ffi:ao_music_duration_async (ao-handle-async-player handle))
|
||||||
(scm:ao_music_duration_async (ao-handle-async-player handle))))
|
)
|
||||||
|
|
||||||
(define (ao-bufsize-async handle)
|
(define (ao-bufsize-async handle)
|
||||||
(if (eq? libao-async-mode 'ffi)
|
|
||||||
(ffi:ao_bufsize_async (ao-handle-async-player handle))
|
(ffi:ao_bufsize_async (ao-handle-async-player handle))
|
||||||
(scm:ao_bufsize_async (ao-handle-async-player handle))))
|
)
|
||||||
|
|
||||||
(define (ao-clear-async handle)
|
(define (ao-clear-async handle)
|
||||||
(if (eq? libao-async-mode 'ffi)
|
|
||||||
(ffi:ao_clear_async (ao-handle-async-player handle))
|
(ffi:ao_clear_async (ao-handle-async-player handle))
|
||||||
(scm:ao_clear_async (ao-handle-async-player handle))))
|
)
|
||||||
|
|
||||||
|
|
||||||
;(let* ((handle-num (ao-handle-handle-num handle))
|
;(let* ((handle-num (ao-handle-handle-num handle))
|
||||||
; (ao-device (hash-ref devices handle-num #f)))
|
; (ao-device (hash-ref devices handle-num #f)))
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#lang racket/base
|
#lang racket/base
|
||||||
(require "libao.rkt"
|
(require "libao.rkt"
|
||||||
"flac-decoder.rkt"
|
"flac-decoder.rkt"
|
||||||
|
simple-log
|
||||||
;data/queue
|
;data/queue
|
||||||
;racket-sound
|
;racket-sound
|
||||||
)
|
)
|
||||||
@@ -15,14 +16,15 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
(ao-set-async-mode! 'ffi)
|
|
||||||
;(define fmt (ao-mk-format 24 48000 2 'big-endian))
|
;(define fmt (ao-mk-format 24 48000 2 'big-endian))
|
||||||
;(define ao-h (ao-open-live #f fmt))
|
;(define ao-h (ao-open-live #f fmt))
|
||||||
|
|
||||||
(define current-seconds 0)
|
(define current-seconds 0)
|
||||||
(define ao-h #f)
|
(define ao-h #f)
|
||||||
|
|
||||||
(define (flac-play frame buffer)
|
(sl-log-to-display)
|
||||||
|
|
||||||
|
(define (flac-play frame buffer buf-len)
|
||||||
(let* ((sample (hash-ref frame 'number))
|
(let* ((sample (hash-ref frame 'number))
|
||||||
(rate (hash-ref frame 'sample-rate))
|
(rate (hash-ref frame 'sample-rate))
|
||||||
(second (/ (* sample 1.0) (* rate 1.0)))
|
(second (/ (* sample 1.0) (* rate 1.0)))
|
||||||
@@ -35,8 +37,10 @@
|
|||||||
(when (eq? ao-h #f)
|
(when (eq? ao-h #f)
|
||||||
(let ((fmt (ao-mk-format bits-per-sample rate channels 'big-endian)))
|
(let ((fmt (ao-mk-format bits-per-sample rate channels 'big-endian)))
|
||||||
(set! ao-h (ao-open-live #f fmt))))
|
(set! ao-h (ao-open-live #f fmt))))
|
||||||
(ao-play ao-h second duration buffer)
|
;(displayln 'ao-play)
|
||||||
(let ((second-printer (λ ()
|
(ao-play ao-h second duration buffer buf-len 'flac)
|
||||||
|
;(displayln 'done)
|
||||||
|
(let ((second-printer (λ (buf-seconds)
|
||||||
(let ((s (inexact->exact (round (ao-at-second ao-h)))))
|
(let ((s (inexact->exact (round (ao-at-second ao-h)))))
|
||||||
(unless (= s current-seconds)
|
(unless (= s current-seconds)
|
||||||
(set! current-seconds s)
|
(set! current-seconds s)
|
||||||
@@ -45,13 +49,14 @@
|
|||||||
(tminutes (quotient duration 60))
|
(tminutes (quotient duration 60))
|
||||||
(tseconds (remainder duration 60))
|
(tseconds (remainder duration 60))
|
||||||
)
|
)
|
||||||
(displayln (format "At time: ~a:~a (~a:~a)"
|
(displayln (format "At time: ~a:~a (~a:~a) - ~a"
|
||||||
minutes seconds
|
minutes seconds
|
||||||
tminutes tseconds
|
tminutes tseconds
|
||||||
|
buf-seconds
|
||||||
))))))))
|
))))))))
|
||||||
(let* ((buf-size (ao-bufsize-async ao-h))
|
(let* ((buf-size (ao-bufsize-async ao-h))
|
||||||
(buf-seconds (exact->inexact (/ buf-size bytes-per-sample-all-channels rate))))
|
(buf-seconds (exact->inexact (/ buf-size bytes-per-sample-all-channels rate))))
|
||||||
(second-printer)
|
(second-printer buf-seconds)
|
||||||
(when (> buf-seconds 5)
|
(when (> buf-seconds 5)
|
||||||
(letrec ((waiter (λ ()
|
(letrec ((waiter (λ ()
|
||||||
(let ((buf-seconds-left (exact->inexact
|
(let ((buf-seconds-left (exact->inexact
|
||||||
@@ -62,7 +67,7 @@
|
|||||||
(displayln (format "Seconds in buffer left: ~a" buf-seconds-left))
|
(displayln (format "Seconds in buffer left: ~a" buf-seconds-left))
|
||||||
(begin
|
(begin
|
||||||
(sleep 0.5)
|
(sleep 0.5)
|
||||||
(second-printer)
|
(second-printer buf-seconds)
|
||||||
(waiter)))))
|
(waiter)))))
|
||||||
))
|
))
|
||||||
(waiter))))
|
(waiter))))
|
||||||
|
|||||||
Reference in New Issue
Block a user