(module libflac-ffi racket/base (require ffi/unsafe ffi/unsafe/define "private/utils.rkt" ) (provide mpg123-ffi-decoder-handler ) (define lib (get-lib '("libmpg123") '("0" #f))) (define-ffi-definer define-libmpg123 lib #:default-make-fail make-not-available) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Some MPG123 Constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define _size_t _size) (define SEEK_SET 0) (define SEEK_CUR 1) (define SEEK_END 2) (define _Seek_t (_enum '(seek-set = 0 seek-cur = 1 seek-end = 2 ) ) ) (define _MPG123_Result (_enum '(MPG123_DONE = -12 ;/**< Message: Track ended. Stop decoding. */ MPG123_NEW_FORMAT = -11 ;/**< Message: Output format will be different on next call. ; Note that some libmpg123 versions between 1.4.3 and 1.8.0 ; insist on you calling mpg123_getformat() after getting this ; message code. Newer verisons behave like advertised: ; You have the chance to call mpg123_getformat(), but you can ; also just continue decoding and get your data. */ MPG123_NEED_MORE = -10 ;/**< Message: For feed reader: "Feed me more!" (call ; mpg123_feed() or mpg123_decode() with some new input data). */ MPG123_ERR = -1 ;/**< Generic Error */ MPG123_OK=0 ;/**< Success */ MPG123_BAD_OUTFORMAT ;/**< Unable to set up output format! */ MPG123_BAD_CHANNEL ;/**< Invalid channel number specified. */ MPG123_BAD_RATE ;/**< Invalid sample rate specified. */ MPG123_ERR_16TO8TABLE ;/**< Unable to allocate memory for 16 to 8 converter table! */ MPG123_BAD_PARAM ;/**< Bad parameter id! */ MPG123_BAD_BUFFER ;/**< Bad buffer given -- invalid pointer or too small size. */ MPG123_OUT_OF_MEM ;/**< Out of memory -- some malloc() failed. */ MPG123_NOT_INITIALIZED ;/**< You didn't initialize the library! */ MPG123_BAD_DECODER ;/**< Invalid decoder choice. */ MPG123_BAD_HANDLE ;/**< Invalid mpg123 handle. */ MPG123_NO_BUFFERS ;/**< Unable to initialize frame buffers (out of memory?). */ MPG123_BAD_RVA ;/**< Invalid RVA mode. */ MPG123_NO_GAPLESS ;/**< This build doesn't support gapless decoding. */ MPG123_NO_SPACE ;/**< Not enough buffer space. */ MPG123_BAD_TYPES ;/**< Incompatible numeric data types. */ MPG123_BAD_BAND ;/**< Bad equalizer band. */ MPG123_ERR_NULL ;/**< Null pointer given where valid storage address needed. */ MPG123_ERR_READER ;/**< Error reading the stream. */ MPG123_NO_SEEK_FROM_END ;/**< Cannot seek from end (end is not known). */ MPG123_BAD_WHENCE ;/**< Invalid 'whence' for seek function.*/ MPG123_NO_TIMEOUT ;/**< Build does not support stream timeouts. */ MPG123_BAD_FILE ;/**< File access error. */ MPG123_NO_SEEK ;/**< Seek not supported by stream. */ MPG123_NO_READER ;/**< No stream opened or no reader callback setup. */ MPG123_BAD_PARS ;/**< Bad parameter handle. */ MPG123_BAD_INDEX_PAR ;/**< Bad parameters to MPG123_index() and MPG123_set_index() */ MPG123_OUT_OF_SYNC ;/**< Lost track in bytestream and did not try to resync. */ MPG123_RESYNC_FAIL ;/**< Resync failed to find valid MPEG data. */ MPG123_NO_8BIT ;/**< No 8bit encoding possible. */ MPG123_BAD_ALIGN ;/**< Stack aligmnent error */ MPG123_NULL_BUFFER ;/**< NULL input buffer with non-zero size... */ MPG123_NO_RELSEEK ;/**< Relative seek not possible (screwed up file offset) */ MPG123_NULL_POINTER ;/**< You gave a null pointer somewhere where you shouldn't have. */ MPG123_BAD_KEY ;/**< Bad key value given. */ MPG123_NO_INDEX ;/**< No frame index in this build. */ MPG123_INDEX_FAIL ;/**< Something with frame index went wrong. */ MPG123_BAD_DECODER_SETUP ;/**< Something prevents a proper decoder setup */ MPG123_MISSING_FEATURE ;/**< This feature has not been built into libmpg123. */ MPG123_BAD_VALUE ;/**< A bad value has been given somewhere. */ MPG123_LSEEK_FAILED ;/**< Low-level seek failed. */ MPG123_BAD_CUSTOM_IO ;/**< Custom I/O not prepared. */ MPG123_LFS_OVERFLOW ;/**< Offset value overflow during translation ; of large file API calls -- your client program ; cannot handle that large file. */ MPG123_INT_OVERFLOW ;/**< Some integer overflow. */ MPG123_BAD_FLOAT ;/**< Floating-point computations work not as expected. */ ) ) ) (define _mpg123_handle _pointer) ; MPG123_EXPORT int mpg123_init (void) (define-libmpg123 mpg123_init (_fun -> _MPG123_Result)) ; MPG123_EXPORT mpg123_handle *mpg123_new (const char *decoder, int *error) (define-libmpg123 mpg123_new (_fun _string/utf-8 (err : (_ptr o _int)) -> (h : _mpg123_handle) -> (values h err))) ; MPG123_EXPORT size_t mpg123_outblock ( mpg123_handle * mh ) (define-libmpg123 mpg123_outblock (_fun _mpg123_handle -> _size_t)) ; MPG123_EXPORT int mpg123_open (mpg123_handle *mh, const char *path) (define-libmpg123 mpg123_open (_fun _mpg123_handle _string/utf-8 -> _MPG123_Result)) ; MPG123_EXPORT int mpg123_close (mpg123_handle *mh) (define-libmpg123 mpg123_close (_fun _mpg123_handle -> _MPG123_Result)) ; MPG123_EXPORT int mpg123_getformat (mpg123_handle *mh, long *rate, int *channels, int *encoding) (define-libmpg123 mpg123_getformat (_fun _mpg123_handle (rate : (_ptr o _long)) (channels : (_ptr o _int)) (encoding : (_ptr o _int)) -> (r : _MPG123_Result) -> (values r rate channels encoding))) ; MPG123_EXPORT int mpg123_encsize ( int encoding ) (define-libmpg123 mpg123_encsize (_fun _int -> _int)) ; MPG123_EXPORT int mpg123_read (mpg123_handle *mh, void *outmemory, size_t outmemsize, size_t *done) (define-libmpg123 mpg123_read (_fun _mpg123_handle _pointer _size_t (done : (_ptr o _size_t)) -> (r : _MPG123_Result) -> (values r done))) ; MPG123_EXPORT int64_t mpg123_tell64 ( mpg123_handle * mh ) (define-libmpg123 mpg123_tell64 (_fun _mpg123_handle -> _int64)) ; MPG123_EXPORT int64_t mpg123_seek64(mpg123_handle * mh, int64_t sampleoff, int whence ) (define-libmpg123 mpg123_seek64 (_fun _mpg123_handle _int64 _Seek_t -> _int64)) ; MPG123_EXPORT int mpg123_scan ( mpg123_handle * mh ) (define-libmpg123 mpg123_scan (_fun _mpg123_handle -> _MPG123_Result)) ; MPG123_EXPORT off_t mpg123_length ( mpg123_handle * mh ) (define-libmpg123 mpg123_length64 (_fun _mpg123_handle -> _int64)) #| #include #include #define BITS 8 int main(int argc, char *argv[]) { mpg123_handle *mh; unsigned char *buffer; size_t buffer_size; size_t done; int err; int driver; ao_device *dev; ao_sample_format format; int channels, encoding; long rate; if(argc < 2) exit(0); /* initializations */ ao_initialize(); driver = ao_default_driver_id(); mpg123_init(); mh = mpg123_new(NULL, &err); buffer_size = mpg123_outblock(mh); buffer = (unsigned char*) malloc(buffer_size * sizeof(unsigned char)); /* open the file and get the decoding format */ mpg123_open(mh, argv[1]); mpg123_getformat(mh, &rate, &channels, &encoding); /* set the output format and open the output device */ format.bits = mpg123_encsize(encoding) * BITS; format.rate = rate; format.channels = channels; format.byte_format = AO_FMT_NATIVE; format.matrix = 0; dev = ao_open_live(driver, &format, NULL); /* decode and play */ while (mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK) ao_play(dev, buffer, done); /* clean up */ free(buffer); ao_close(dev); mpg123_close(mh); mpg123_delete(mh); mpg123_exit(); ao_shutdown(); return 0; } |# ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Our interface for decoding to racket ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define (mpg123-ffi-decoder-handler) #t #| (define write-data '()) (define meta-data '()) (define error-no -1) (define fl #f) (define flac-file #f) (define client-data #f) (define (write-callback fl frame buffer client-data) (set! write-data (append write-data (list (cons frame buffer)))) 0) (define (meta-callback fl meta client-data) (let ((meta-clone (FLAC__metadata_object_clone meta))) (unless (eq? meta-clone #f) (set! meta-data (append meta-data (list meta-clone)))))) (define (error-callback fl errno client-data) (set! error-no errno) ) (define (new) (set! fl (FLAC__stream_decoder_new)) fl) (define (init file) (let ((r (FLAC__stream_decoder_init_file fl file write-callback meta-callback error-callback client-data))) (set! flac-file file) r)) (define (process-single) (FLAC__stream_decoder_process_single fl)) (define (int-state) (FLAC__stream_decoder_get_state fl)) (define (state) (decoder-state (int-state))) (define (process-meta-data cb) (for-each (λ (meta-entry) (cb meta-entry) (FLAC__metadata_object_delete meta-entry)) meta-data) (set! meta-data '())) (define (process-write-data cb) (for-each (lambda (d) (cb (car d) (cdr d))) write-data) (set! write-data '())) (define (buffer->vectorlist buffer channels size) (letrec ((for-channels (lambda (channel) (if (< channel channels) (letrec ((v (make-vector size 0)) (p (ptr-ref buffer FLAC__int32-pointer channel)) (to-vec (lambda (i) (when (< i size) (vector-set! v i (ptr-ref p _int32 i)) (to-vec (+ i 1))))) ) (to-vec 0) (cons v (for-channels (+ channel 1)))) '()))) ) (for-channels 0))) (define (seek-to-sample sample) (FLAC__stream_decoder_seek_absolute fl sample)) (lambda (cmd . args) (cond [(eq? cmd 'write-data) write-data] [(eq? cmd 'meta-data) meta-data] [(eq? cmd 'new) (new)] [(eq? cmd 'init) (init (car args))] [(eq? cmd 'process-single) (process-single)] [(eq? cmd 'get-buffers) (buffer->vectorlist (car args) (cadr args) (caddr args))] [(eq? cmd 'int-state) (int-state)] [(eq? cmd 'state) (state)] [(eq? cmd 'has-write-data?) (not (null? write-data))] [(eq? cmd 'has-meta-data?) (not (null? meta-data))] [(eq? cmd 'has-errno?) (not (= error-no -1))] [(eq? cmd 'process-meta-data) (process-meta-data (car args))] [(eq? cmd 'process-write-data) (process-write-data (car args))] [(eq? cmd 'errno) error-no] [(eq? cmd 'seek-to-sample) (seek-to-sample (car args))] [(eq? cmd 'file) flac-file] [else (error (format "unknown command ~a" cmd))] )) |# ) ); end of module