diff options
Diffstat (limited to 'plugins/eg05-scope.lv2')
-rw-r--r-- | plugins/eg05-scope.lv2/README.txt | 10 | ||||
-rw-r--r-- | plugins/eg05-scope.lv2/examploscope.c | 82 | ||||
-rw-r--r-- | plugins/eg05-scope.lv2/manifest.ttl.in | 3 |
3 files changed, 59 insertions, 36 deletions
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: <http://www.w3.org/2000/01/rdf-schema#> . @prefix ui: <http://lv2plug.in/ns/extensions/ui#> . +# ==== Mono plugin variant ==== <http://lv2plug.in/plugins/eg-scope#Mono> a lv2:Plugin ; lv2:binary <examploscope@LIB_EXT@> ; rdfs:seeAlso <examploscope.ttl> . +# ==== Stereo plugin variant ==== <http://lv2plug.in/plugins/eg-scope#Stereo> a lv2:Plugin ; lv2:binary <examploscope@LIB_EXT@> ; rdfs:seeAlso <examploscope.ttl> . +# ==== Gtk 2.0 UI ==== <http://lv2plug.in/plugins/eg-scope#ui> a ui:GtkUI ; ui:binary <examploscope_ui@LIB_EXT@> ; |