structured documentation

This commit is contained in:
2026-05-16 09:16:13 +02:00
parent ba087f07f1
commit 475f7230b5
3 changed files with 114 additions and 103 deletions
+1 -24
View File
@@ -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
+96
View File
@@ -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.
+17 -79
View File
@@ -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[]