From 8b1275387c758c1ee894647517e5fb30adaa3ea4 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 25 Dec 2013 17:59:16 +0000 Subject: Bookify examploscope documentation. Fix book generator to include single-star C comments in code blocks. --- plugins/README.txt | 2 +- plugins/eg01-amp.lv2/README.txt | 18 ++++---- plugins/eg01-amp.lv2/manifest.ttl.in | 30 ++++++------ plugins/eg04-sampler.lv2/sampler_ui.c | 4 -- plugins/eg05-scope.lv2/README.txt | 10 ++-- plugins/eg05-scope.lv2/examploscope.c | 82 ++++++++++++++++++++------------- plugins/eg05-scope.lv2/manifest.ttl.in | 3 ++ plugins/literasc.py | 22 +++++++-- waf | Bin 96114 -> 96933 bytes 9 files changed, 101 insertions(+), 70 deletions(-) diff --git a/plugins/README.txt b/plugins/README.txt index 7eb25d8..361460d 100644 --- a/plugins/README.txt +++ b/plugins/README.txt @@ -23,4 +23,4 @@ the first plugin describes the basics in detail. This book is compiled from plugin source code into a single document for pleasant reading and ease of reference. Each chapter corresponds to executable plugin code which can be found in the +plugins+ directory of the LV2 distribution. -If you prefer to read actual source code, all the content here is also available there, where the book text is included in comments. +If you prefer to read actual source code, all the content here is also available in the source code as comments. diff --git a/plugins/eg01-amp.lv2/README.txt b/plugins/eg01-amp.lv2/README.txt index f024a4d..41683d3 100644 --- a/plugins/eg01-amp.lv2/README.txt +++ b/plugins/eg01-amp.lv2/README.txt @@ -2,20 +2,18 @@ This plugin is a simple example of a basic LV2 plugin with no additional features. It has audio ports which contain an array of `float`, -and a control port which contain a single `float`. +and a control port which contains a single `float`. LV2 plugins are defined in two parts: code and data. The code is written in C, or any C compatible language such as C++. Static data is described separately in the human and machine friendly http://www.w3.org/TeamSubmission/turtle/[Turtle] syntax. -Turtle is a syntax for the RDF data model, -but familiarity with RDF is not required to understand this documentation. -Generally, code is kept minimal, -and all static information is described in the data. +Generally, the goal is to keep code minimal, +and describe as much as possible in the static data. There are several advantages to this approach: - * Hosts can discover and inspect plugins without loading or executing any plugin code - * It is simple to work with plugin data using scripting languages, command line tools, etc. - * The standard format allow the use of existing vocabularies to describe plugins and related information - * The data inherently integrates with the web, databases, etc. - * Labels and documentation are translatable, and available to hosts for display in user interfaces + * Hosts can discover and inspect plugins without loading or executing any plugin code. + * Plugin data can be used from a wide range of generic tools like scripting languages and command line utilities. + * The standard data model allows the use of existing vocabularies to describe plugins and related information. + * The language is extensible, so authors may describe any data without requiring changes to the LV2 specification. + * Labels and documentation are translatable, and available to hosts for display in user interfaces. diff --git a/plugins/eg01-amp.lv2/manifest.ttl.in b/plugins/eg01-amp.lv2/manifest.ttl.in index 0da78b0..8a1f696 100644 --- a/plugins/eg01-amp.lv2/manifest.ttl.in +++ b/plugins/eg01-amp.lv2/manifest.ttl.in @@ -1,27 +1,27 @@ -# LV2 Bundle Manifest +# ==== Bundles ==== # -# All LV2 plugins are installed as "bundles", a directory with a particular -# format. Inside the bundle, the entry point is a file called "manifest.ttl". -# This file lists what plugins are in this bundle, and which files are (.so, -# .ttl, etc.) are associated with those plugins. +# LV2 plugins are installed in ``bundles'', a directory with a particular +# format. Inside the bundle, the entry point is a file called `manifest.ttl`. +# The manifest lists the plugins (or other resources) that are in this bundle, +# and the files that contain further information. # -# Hosts read bundles' manifest.ttl to discover what plugins (and other -# resources) are available. Manifest files should be as small as possible for -# performance reasons. +# Hosts typically read the `manifest.ttl` of every bundle when starting up to +# discover what LV2 plugins and other resources are present. Accordingly, +# manifest files should be as small as possible for performance reasons. # # # ==== Namespace Prefixes ==== # -# Turtle files contain many URIs. To make this more readable, prefixes -# can be defined. For example, with the `lv2:` prefix below, instead of +# Turtle files contain many URIs. To make this more readable, prefixes can be +# defined. For example, with the `lv2:` prefix below, instead of # the shorter form `lv2:Plugin` can be -# used. This is just a shorthand for URIs within a file, the prefixes are not -# significant otherwise. +# used. This is just a shorthand for URIs within one file, the prefixes are +# not significant otherwise. @prefix lv2: . @prefix rdfs: . -# ==== Data ==== +# ==== A Plugin Entry ==== a lv2:Plugin ; @@ -36,8 +36,8 @@ # For reability, the following text will assume `.so` is the extension used. # # In short, this declares that the resource with URI -# "http://lv2plug.in/plugins/eg-amp" is an LV2 plugin, with executable code in -# the file "amp.so" and a full description in "amp.ttl". These paths are +# `http://lv2plug.in/plugins/eg-amp` is an LV2 plugin, with executable code in +# the file `amp.so` and a full description in `amp.ttl`. These paths are # relative to the bundle directory. # # There are 3 statements in this description: diff --git a/plugins/eg04-sampler.lv2/sampler_ui.c b/plugins/eg04-sampler.lv2/sampler_ui.c index 2184fbf..3eb1279 100644 --- a/plugins/eg04-sampler.lv2/sampler_ui.c +++ b/plugins/eg04-sampler.lv2/sampler_ui.c @@ -15,10 +15,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/** - @file ui.c Sampler Plugin UI -*/ - #include #include diff --git a/plugins/eg05-scope.lv2/README.txt b/plugins/eg05-scope.lv2/README.txt index ec3578b..122794c 100644 --- a/plugins/eg05-scope.lv2/README.txt +++ b/plugins/eg05-scope.lv2/README.txt @@ -1,17 +1,19 @@ == Simple Oscilloscope == -This plugin displays the wave-form of an incoming audio-signal using a simple +This plugin displays the waveform of an incoming audio signal using a simple GTK+Cairo GUI. This plugin illustrates: -- UI <==> Plugin communication via LV2 atom events -- LV2 Atom vector usage and resize-port extension +- UI <==> Plugin communication via http://lv2plug.in/ns/ext/atom/[LV2 Atom] events +- Atom vector usage and resize-port extension - Save/Restore UI state by communicating state to backend +- Saving simple key/value state via the http://lv2plug.in/ns/ext/state/[LV2 State] extension - Cairo drawing and partial exposure This plugin intends to outline the basics for building visualization plugins -that rely on Atom communication. The UI looks likean oscilloscope, but is not a real oscilloscope implementation: +that rely on atom communication. The UI looks like an oscilloscope, but is not +a real oscilloscope implementation: - There is no display synchronisation, results will depend on LV2 host. - It displays raw audio samples, which a proper scope must not do. diff --git a/plugins/eg05-scope.lv2/examploscope.c b/plugins/eg05-scope.lv2/examploscope.c index ff64866..31e757a 100644 --- a/plugins/eg05-scope.lv2/examploscope.c +++ b/plugins/eg05-scope.lv2/examploscope.c @@ -25,7 +25,14 @@ #include "./uris.h" -/** Private plugin instance structure. */ +/** + ==== Private Plugin Instance Structure ==== + + In addition to the usual port buffers and features, this plugin stores the + state of the UI here, so it can be opened and closed without losing the + current settings. The UI state is communicated between the plugin and the + UI using atom messages via a sequence port, similarly to MIDI I/O. +*/ typedef struct { // Port buffers float* input[2]; @@ -47,27 +54,24 @@ typedef struct { uint32_t n_channels; double rate; - /* The state of the UI is stored here, so that the GUI can be displayed and - closed without losing the current settings. It is communicated to the - UI using atom messages. - */ + // UI state bool ui_active; bool send_settings_to_ui; float ui_amp; uint32_t ui_spp; } EgScope; -/** Port indices. */ +/** ==== Port Indices ==== */ typedef enum { - SCO_CONTROL = 0, - SCO_NOTIFY = 1, - SCO_INPUT0 = 2, - SCO_OUTPUT0 = 3, - SCO_INPUT1 = 4, - SCO_OUTPUT1 = 5, + SCO_CONTROL = 0, // Event input + SCO_NOTIFY = 1, // Event output + SCO_INPUT0 = 2, // Audio input 0 + SCO_OUTPUT0 = 3, // Audio output 0 + SCO_INPUT1 = 4, // Audio input 1 (stereo variant) + SCO_OUTPUT1 = 5, // Audio input 2 (stereo variant) } PortIndex; -/** Create plugin instance. */ +/** ==== Instantiate Method ==== */ static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double rate, @@ -125,7 +129,7 @@ instantiate(const LV2_Descriptor* descriptor, return (LV2_Handle)self; } -/** Connect a port to a buffer. */ +/** ==== Connect Port Method ==== */ static void connect_port(LV2_Handle handle, uint32_t port, @@ -156,41 +160,49 @@ connect_port(LV2_Handle handle, } /** - Forge vector of raw data. - - @param forge Forge to use. - @param uris Mapped URI identifiers. - @param channel Channel ID to transmit. - @param n_samples Number of audio samples to transmit. - @param data Actual audio data. + ==== Utility Function: `tx_rawaudio` ==== + + This function forges a message for sending a vector of raw data. The object + is a http://lv2plug.in/ns/ext/atom#Blank[Blank] with a few properties, like: + [source,txt] + -------- + [] + a sco:RawAudio ; + sco:channelID 0 ; + sco:audioData [ 0.0, 0.0, ... ] . + -------- + + where the value of the `sco:audioData` property, `[ 0.0, 0.0, ... ]`, is a + http://lv2plug.in/ns/ext/atom#Vector[Vector] of + http://lv2plug.in/ns/ext/atom#Float[Float]. */ static void tx_rawaudio(LV2_Atom_Forge* forge, ScoLV2URIs* uris, const int32_t channel, const size_t n_samples, - void* data) + const float* data) { LV2_Atom_Forge_Frame frame; - // Forge container object of type 'rawaudio' + // Forge container object of type 'RawAudio' lv2_atom_forge_frame_time(forge, 0); lv2_atom_forge_blank(forge, &frame, 1, uris->RawAudio); - // Add integer attribute 'channelid' + // Add integer 'channelID' property lv2_atom_forge_property_head(forge, uris->channelID, 0); lv2_atom_forge_int(forge, channel); - // Add vector of floats raw 'audiodata' + // Add vector of floats 'audioData' property lv2_atom_forge_property_head(forge, uris->audioData, 0); lv2_atom_forge_vector( forge, sizeof(float), uris->atom_Float, n_samples, data); - // Close off atom-object + // Close off object lv2_atom_forge_pop(forge, &frame); } -/** Process a block of audio */ +/** ==== Run Method ==== */ static void run(LV2_Handle handle, uint32_t n_samples) { @@ -298,6 +310,16 @@ cleanup(LV2_Handle handle) free(handle); } + +/** + ==== State Methods ==== + + This plugin's state consists of two basic properties: one `int` and one + `float`. No files are used. Note these values are POD, but not portable, + since different machines may have a different integer endianness or floating + point format. However, since standard Atom types are used, a good host will + be able to save them portably as text anyway. +*/ static LV2_State_Status state_save(LV2_Handle instance, LV2_State_Store_Function store, @@ -310,11 +332,6 @@ state_save(LV2_Handle instance, return LV2_STATE_SUCCESS; } - /* Store state values. Note these values are POD, but not portable, since - different machines may have a different integer endianness or floating - point format. However, since standard Atom types are used, a good host - will be able to save them portably as text anyway. */ - store(handle, self->uris.ui_spp, (void*)&self->ui_spp, sizeof(uint32_t), self->uris.atom_Int, @@ -368,6 +385,7 @@ extension_data(const char* uri) return NULL; } +/** ==== Plugin Descriptors ==== */ static const LV2_Descriptor descriptor_mono = { SCO_URI "#Mono", instantiate, diff --git a/plugins/eg05-scope.lv2/manifest.ttl.in b/plugins/eg05-scope.lv2/manifest.ttl.in index 028a673..a64aff1 100644 --- a/plugins/eg05-scope.lv2/manifest.ttl.in +++ b/plugins/eg05-scope.lv2/manifest.ttl.in @@ -2,16 +2,19 @@ @prefix rdfs: . @prefix ui: . +# ==== Mono plugin variant ==== a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . +# ==== Stereo plugin variant ==== a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . +# ==== Gtk 2.0 UI ==== a ui:GtkUI ; ui:binary ; diff --git a/plugins/literasc.py b/plugins/literasc.py index b7b65cd..7638e6f 100755 --- a/plugins/literasc.py +++ b/plugins/literasc.py @@ -36,16 +36,30 @@ def format_c_source(filename, file): for line in file: code += line + # Skip initial license comment + if code[0:2] == '/*': + code = code[code.find('*/') + 2:] + for c in code: if prev_c == '/' and c == '*': - output += format_code('c', chunk[0:len(chunk)-1]) - in_comment = True in_comment_start = True n_stars = 1 - chunk = '' + elif in_comment_start: + if c == '*': + n_stars += 1 + else: + if n_stars > 1: + output += format_code('c', chunk[0:len(chunk)-1]) + chunk = '' + in_comment = True + else: + chunk += '*' + c + in_comment_start = False elif in_comment and prev_c == '*' and c == '/': - if n_stars > 2: + if n_stars > 1: output += format_text(chunk[0:len(chunk)-1]) + else: + output += format_code('c', '/* ' + chunk[0:len(chunk)-1] + '*/') in_comment = False in_comment_start = False chunk = '' diff --git a/waf b/waf index c825c3b..1945d42 100755 Binary files a/waf and b/waf differ -- cgit v1.2.1