diff --git a/info.rkt b/info.rkt index 06d12d0..1854ac6 100644 --- a/info.rkt +++ b/info.rkt @@ -8,30 +8,7 @@ (define scribblings '( - ;; Main package overview. - ;; The negative sort number makes this document appear before the - ;; other racket-audio manuals in the library documentation listing. - ("scrbl/racket-audio.scrbl" () (library -100)) - - ;; High-level user-facing APIs. - ("scrbl/audio-player.scrbl" () (library -90)) - ("scrbl/taglib.scrbl" () (library -80)) - ("scrbl/play-test.scrbl" () (library -70)) - - ;; Format detection and decoder layer. - ("scrbl/audio-sniffer.scrbl" () (library -60)) - ("scrbl/audio-decoder.scrbl" () (library -50)) - ("scrbl/mp3-decoder.scrbl" () (library -40)) - ("scrbl/flac-decoder.scrbl" () (library -30)) - ("scrbl/ffmpeg-decoder.scrbl" () (library -20)) - - ;; Lower-level playback and FFI modules. - ("scrbl/audio-placed-player.scrbl" () (library 10)) - ("scrbl/libao.scrbl" () (library 20)) - ("scrbl/libao-async-ffi-racket.scrbl" () (library 30)) - ("scrbl/ffmpeg-c-backend.scrbl" () (library 40)) - ("scrbl/ffmpeg-ffi.scrbl" () (library 50)) - ("scrbl/ffmpeg-definitions.scrbl" () (library 60)) + ("scrbl/racket-audio.scrbl" (multi-page) (library 0)) )) (define deps diff --git a/scrbl/intro.scrbl b/scrbl/intro.scrbl new file mode 100644 index 0000000..4d55518 --- /dev/null +++ b/scrbl/intro.scrbl @@ -0,0 +1,96 @@ +#lang scribble/manual + +@(require racket/runtime-path + scribble/core + scribble/html-properties + (for-label racket/base + racket/path + "../audio-player.rkt" + "../taglib.rkt" + "../audio-sniffer.rkt" + "../audio-decoder.rkt" + "../audio-placed-player.rkt" + "../libao.rkt" + "../mp3-decoder.rkt" + "../flac-decoder.rkt" + "../ffmpeg-decoder.rkt")) + +@(define-runtime-path rktplayer-logo "rktplayer.svg") + +@(define title-logo-style + (style #f + (list (attributes + '((style . "float: right; margin-left: 1.5em; margin-bottom: 0.5em;")))))) + +@elem[#:style title-logo-style]{@image[#:scale 0.25 rktplayer-logo]} + +@title{@elem{Introduction racket-audio}} + + +@;;title{racket-audio} +@author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]] + +@racketmodname[racket-audio] is a small audio playback toolkit for Racket. It +combines high-level asynchronous playback, optional metadata reading, file type +sniffing, decoder backends, and libao based output. Most applications should +start with the high-level player API and only use the lower-level modules when +they need to add a decoder, inspect the playback pipeline, or debug the native +FFI boundary. + +@section{APIs for normal users} + +For ordinary playback, use @racketmodname[racket-audio/audio-player]. It +creates an audio player, starts the worker side, and exposes procedures such as +@racket[make-audio-player], @racket[audio-play!], @racket[audio-pause!], +@racket[audio-stop!], @racket[audio-seek!], and @racket[audio-quit!]. The +player is asynchronous: commands return after they have been accepted, while +state updates and end-of-stream notifications are delivered through callbacks. + +Use @racketmodname[racket-audio/taglib] when an application needs metadata such +as title, artist, album, duration-related properties, generic TagLib properties, +or embedded cover art. The module reads metadata into a Racket-side snapshot +and does not keep the native TagLib file handle open. + +Use @racketmodname[racket-audio/audio-sniffer] when file type detection should +be based on file contents rather than only on extensions. The sniffer is useful +before choosing a decoder, validating input, or presenting a likely media type +to the user. + +The @racketmodname[racket-audio/play-test] module is not a library API, but it +is a useful integration example. In particular, its queue mode, selected with +@racket[(set-test 'queue)], shows how an EOF callback can start the next item +in a simple playback queue. + +@section{Lower-level modules for geeks} + +The modules below are normally used by the player implementation rather than by +application code. They are documented because they are useful when extending, +debugging, or replacing parts of the pipeline. + +@itemlist[#:style 'compact + @item{@racketmodname[racket-audio/audio-placed-player] implements the worker + side of the high-level player. It is normally run in a Racket place, so + the timing-sensitive audio feeder runs in a separate VM, but it can also + be run in a thread with async channels for easier debugging.} + @item{@racketmodname[racket-audio/audio-decoder] provides the decoder registry + and a uniform open/read/seek/stop interface over concrete decoder + backends.} + @item{@racketmodname[racket-audio/mp3-decoder], + @racketmodname[racket-audio/flac-decoder], and + @racketmodname[racket-audio/ffmpeg-decoder] are concrete decoder + frontends. The FFmpeg path is the general-purpose fallback for formats + not handled by the specialised decoders.} + @item{@racketmodname[racket-audio/libao] and + @racketmodname[racket-audio/libao-async-ffi-racket] form the output side: + they open the native audio device, queue PCM buffers, apply volume, and + feed libao asynchronously.} + @item{@racketmodname[racket-audio/ffmpeg-ffi], + @racketmodname[racket-audio/ffmpeg-definitions], and the FFmpeg C backend + documentation describe the native FFmpeg boundary, the direct FFI + definitions, version-sensitive structures, and the fixed PCM format used + by the decoder pipeline.}] + +In short: applications should usually combine +@racketmodname[racket-audio/audio-player] with @racketmodname[racket-audio/taglib]. +The other modules document the machinery underneath: format detection, decoder +selection, place-based playback, buffering, native output, and FFmpeg access. diff --git a/scrbl/racket-audio.scrbl b/scrbl/racket-audio.scrbl index 736cf50..09135aa 100644 --- a/scrbl/racket-audio.scrbl +++ b/scrbl/racket-audio.scrbl @@ -2,18 +2,7 @@ @(require racket/runtime-path scribble/core - scribble/html-properties - (for-label racket/base - racket/path - "../audio-player.rkt" - "../taglib.rkt" - "../audio-sniffer.rkt" - "../audio-decoder.rkt" - "../audio-placed-player.rkt" - "../libao.rkt" - "../mp3-decoder.rkt" - "../flac-decoder.rkt" - "../ffmpeg-decoder.rkt")) + scribble/html-properties) @(define-runtime-path rktplayer-logo "rktplayer.svg") @@ -26,71 +15,20 @@ @title{@elem{racket-audio}} +@table-of-contents[] -@;;title{racket-audio} -@author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]] - -@racketmodname[racket-audio] is a small audio playback toolkit for Racket. It -combines high-level asynchronous playback, optional metadata reading, file type -sniffing, decoder backends, and libao based output. Most applications should -start with the high-level player API and only use the lower-level modules when -they need to add a decoder, inspect the playback pipeline, or debug the native -FFI boundary. - -@section{APIs for normal users} - -For ordinary playback, use @racketmodname[racket-audio/audio-player]. It -creates an audio player, starts the worker side, and exposes procedures such as -@racket[make-audio-player], @racket[audio-play!], @racket[audio-pause!], -@racket[audio-stop!], @racket[audio-seek!], and @racket[audio-quit!]. The -player is asynchronous: commands return after they have been accepted, while -state updates and end-of-stream notifications are delivered through callbacks. - -Use @racketmodname[racket-audio/taglib] when an application needs metadata such -as title, artist, album, duration-related properties, generic TagLib properties, -or embedded cover art. The module reads metadata into a Racket-side snapshot -and does not keep the native TagLib file handle open. - -Use @racketmodname[racket-audio/audio-sniffer] when file type detection should -be based on file contents rather than only on extensions. The sniffer is useful -before choosing a decoder, validating input, or presenting a likely media type -to the user. - -The @racketmodname[racket-audio/play-test] module is not a library API, but it -is a useful integration example. In particular, its queue mode, selected with -@racket[(set-test 'queue)], shows how an EOF callback can start the next item -in a simple playback queue. - -@section{Lower-level modules for geeks} - -The modules below are normally used by the player implementation rather than by -application code. They are documented because they are useful when extending, -debugging, or replacing parts of the pipeline. - -@itemlist[#:style 'compact - @item{@racketmodname[racket-audio/audio-placed-player] implements the worker - side of the high-level player. It is normally run in a Racket place, so - the timing-sensitive audio feeder runs in a separate VM, but it can also - be run in a thread with async channels for easier debugging.} - @item{@racketmodname[racket-audio/audio-decoder] provides the decoder registry - and a uniform open/read/seek/stop interface over concrete decoder - backends.} - @item{@racketmodname[racket-audio/mp3-decoder], - @racketmodname[racket-audio/flac-decoder], and - @racketmodname[racket-audio/ffmpeg-decoder] are concrete decoder - frontends. The FFmpeg path is the general-purpose fallback for formats - not handled by the specialised decoders.} - @item{@racketmodname[racket-audio/libao] and - @racketmodname[racket-audio/libao-async-ffi-racket] form the output side: - they open the native audio device, queue PCM buffers, apply volume, and - feed libao asynchronously.} - @item{@racketmodname[racket-audio/ffmpeg-ffi], - @racketmodname[racket-audio/ffmpeg-definitions], and the FFmpeg C backend - documentation describe the native FFmpeg boundary, the direct FFI - definitions, version-sensitive structures, and the fixed PCM format used - by the decoder pipeline.}] - -In short: applications should usually combine -@racketmodname[racket-audio/audio-player] with @racketmodname[racket-audio/taglib]. -The other modules document the machinery underneath: format detection, decoder -selection, place-based playback, buffering, native output, and FFmpeg access. +@include-section["intro.scrbl"] +@include-section["audio-player.scrbl"] +@include-section["audio-sniffer.scrbl"] +@include-section["taglib.scrbl"] +@include-section["play-test.scrbl"] +@include-section["audio-placed-player.scrbl"] +@include-section["ffmpeg-decoder.scrbl"] +@include-section["ffmpeg-definitions.scrbl"] +@include-section["ffmpeg-ffi.scrbl"] +@include-section["flac-decoder.scrbl"] +@include-section["libao.scrbl"] +@include-section["libao-async-ffi-racket.scrbl"] +@include-section["mp3-decoder.scrbl"] +' +@index-section[] \ No newline at end of file