void AtomWriter::delta(const Raul::URI& uri, const Resource::Properties& remove, const Resource::Properties& add) { LV2_Atom_Forge_Frame msg; forge_request(&msg, _uris.patch_Patch); lv2_atom_forge_key(&_forge, _uris.patch_subject); forge_uri(uri); lv2_atom_forge_key(&_forge, _uris.patch_remove); LV2_Atom_Forge_Frame remove_obj; lv2_atom_forge_object(&_forge, &remove_obj, 0, 0); forge_properties(remove); lv2_atom_forge_pop(&_forge, &remove_obj); lv2_atom_forge_key(&_forge, _uris.patch_add); LV2_Atom_Forge_Frame add_obj; lv2_atom_forge_object(&_forge, &add_obj, 0, 0); forge_properties(add); lv2_atom_forge_pop(&_forge, &add_obj); lv2_atom_forge_pop(&_forge, &msg); finish_msg(); }
/** ==== 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,n3] -------- [] 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, const float* data) { LV2_Atom_Forge_Frame frame; // Forge container object of type 'RawAudio' lv2_atom_forge_frame_time(forge, 0); lv2_atom_forge_object(forge, &frame, 0, uris->RawAudio); // Add integer 'channelID' property lv2_atom_forge_key(forge, uris->channelID); lv2_atom_forge_int(forge, channel); // Add vector of floats 'audioData' property lv2_atom_forge_key(forge, uris->audioData); lv2_atom_forge_vector( forge, sizeof(float), uris->atom_Float, n_samples, data); // Close off object lv2_atom_forge_pop(forge, &frame); }
void AtomWriter::forge_request(LV2_Atom_Forge_Frame* frame, LV2_URID type) { lv2_atom_forge_object(&_forge, frame, 0, type); if (_id) { lv2_atom_forge_key(&_forge, _uris.patch_sequenceNumber); lv2_atom_forge_int(&_forge, _id); } }
static LV2_Atom_Forge_Ref _trans_event(prog_t *prog, LV2_Atom_Forge *forge, int rolling, jack_position_t *pos) { LV2_Atom_Forge_Frame frame; LV2_Atom_Forge_Ref ref = lv2_atom_forge_frame_time(forge, 0); if(ref) ref = lv2_atom_forge_object(forge, &frame, 0, prog->time_position); { if(ref) ref = lv2_atom_forge_key(forge, prog->time_frame); if(ref) ref = lv2_atom_forge_long(forge, pos->frame); if(ref) ref = lv2_atom_forge_key(forge, prog->time_speed); if(ref) ref = lv2_atom_forge_float(forge, rolling ? 1.0 : 0.0); if(pos->valid & JackPositionBBT) { float bar_beat = pos->beat - 1 + (pos->tick / pos->ticks_per_beat); float bar = pos->bar - 1; if(ref) ref = lv2_atom_forge_key(forge, prog->time_barBeat); if(ref) ref = lv2_atom_forge_float(forge, bar_beat); if(ref) ref = lv2_atom_forge_key(forge, prog->time_bar); if(ref) ref = lv2_atom_forge_long(forge, bar); if(ref) ref = lv2_atom_forge_key(forge, prog->time_beatUnit); if(ref) ref = lv2_atom_forge_int(forge, pos->beat_type); if(ref) ref = lv2_atom_forge_key(forge, prog->time_beatsPerBar); if(ref) ref = lv2_atom_forge_float(forge, pos->beats_per_bar); if(ref) ref = lv2_atom_forge_key(forge, prog->time_beatsPerMinute); if(ref) ref = lv2_atom_forge_float(forge, pos->beats_per_minute); } } if(ref) lv2_atom_forge_pop(forge, &frame); return ref; }
void AtomWriter::forge_arc(const Raul::Path& tail, const Raul::Path& head) { LV2_Atom_Forge_Frame arc; lv2_atom_forge_object(&_forge, &arc, 0, _uris.ingen_Arc); lv2_atom_forge_key(&_forge, _uris.ingen_tail); forge_uri(Node::path_to_uri(tail)); lv2_atom_forge_key(&_forge, _uris.ingen_head); forge_uri(Node::path_to_uri(head)); lv2_atom_forge_pop(&_forge, &arc); }
/** generate a file path message, * send current state to GUI */ static void inform_ui (MidiMap* self) { if (!self->cfg_file_path) { return; } const MidiMapURIs* uris = &self->uris; lv2_atom_forge_frame_time (&self->forge, 0); LV2_Atom_Forge_Frame frame; lv2_atom_forge_object (&self->forge, &frame, 1, uris->patch_Set); lv2_atom_forge_property_head (&self->forge, uris->patch_property, 0); lv2_atom_forge_urid (&self->forge, uris->mem_cfgfile); lv2_atom_forge_property_head (&self->forge, uris->patch_value, 0); lv2_atom_forge_path (&self->forge, self->cfg_file_path, strlen (self->cfg_file_path)); lv2_atom_forge_pop (&self->forge, &frame); }
void AtomWriter::put(const Raul::URI& uri, const Resource::Properties& properties, Resource::Graph ctx) { LV2_Atom_Forge_Frame msg; forge_request(&msg, _uris.patch_Put); lv2_atom_forge_key(&_forge, _uris.patch_subject); forge_uri(uri); lv2_atom_forge_key(&_forge, _uris.patch_body); LV2_Atom_Forge_Frame body; lv2_atom_forge_object(&_forge, &body, 0, 0); forge_properties(properties); lv2_atom_forge_pop(&_forge, &body); lv2_atom_forge_pop(&_forge, &msg); finish_msg(); }
void AtomWriter::disconnect_all(const Raul::Path& graph, const Raul::Path& path) { LV2_Atom_Forge_Frame msg; forge_request(&msg, _uris.patch_Delete); lv2_atom_forge_key(&_forge, _uris.patch_subject); forge_uri(Node::path_to_uri(graph)); lv2_atom_forge_key(&_forge, _uris.patch_body); LV2_Atom_Forge_Frame arc; lv2_atom_forge_object(&_forge, &arc, 0, _uris.ingen_Arc); lv2_atom_forge_key(&_forge, _uris.ingen_incidentTo); forge_uri(Node::path_to_uri(path)); lv2_atom_forge_pop(&_forge, &arc); lv2_atom_forge_pop(&_forge, &msg); finish_msg(); }
/** Forge a blank object @param frame @param id @param otype */ inline ForgeRef write_blank (ForgeFrame& frame, uint32_t id, uint32_t otype) { return lv2_atom_forge_object (this, &frame, id, otype); }
/** ==== Run Method ==== */ static void run(LV2_Handle handle, uint32_t n_samples) { EgScope* self = (EgScope*)handle; /* Ensure notify port buffer is large enough to hold all audio-samples and configuration settings. A minimum size was requested in the .ttl file, but check here just to be sure. TODO: Explain these magic numbers. */ const size_t size = (sizeof(float) * n_samples + 64) * self->n_channels; const uint32_t space = self->notify->atom.size; if (space < size + 128) { /* Insufficient space, report error and do nothing. Note that a real-time production plugin mustn't call log functions in run(), but this can be useful for debugging and example purposes. */ lv2_log_error(&self->logger, "Buffer size is insufficient\n"); return; } // Prepare forge buffer and initialize atom-sequence lv2_atom_forge_set_buffer(&self->forge, (uint8_t*)self->notify, space); lv2_atom_forge_sequence_head(&self->forge, &self->frame, 0); /* Send settings to UI The plugin can continue to run while the UI is closed and re-opened. The state and settings of the UI are kept here and transmitted to the UI every time it asks for them or if the user initializes a 'load preset'. */ if (self->send_settings_to_ui && self->ui_active) { self->send_settings_to_ui = false; // Forge container object of type 'ui_state' LV2_Atom_Forge_Frame frame; lv2_atom_forge_frame_time(&self->forge, 0); lv2_atom_forge_object(&self->forge, &frame, 0, self->uris.ui_State); // Add UI state as properties lv2_atom_forge_key(&self->forge, self->uris.ui_spp); lv2_atom_forge_int(&self->forge, self->ui_spp); lv2_atom_forge_key(&self->forge, self->uris.ui_amp); lv2_atom_forge_float(&self->forge, self->ui_amp); lv2_atom_forge_key(&self->forge, self->uris.param_sampleRate); lv2_atom_forge_float(&self->forge, self->rate); lv2_atom_forge_pop(&self->forge, &frame); } // Process incoming events from GUI if (self->control) { const LV2_Atom_Event* ev = lv2_atom_sequence_begin( &(self->control)->body); // For each incoming message... while (!lv2_atom_sequence_is_end( &self->control->body, self->control->atom.size, ev)) { // If the event is an atom:Blank object if (ev->body.type == self->uris.atom_Blank) { const LV2_Atom_Object* obj = (const LV2_Atom_Object*)&ev->body; if (obj->body.otype == self->uris.ui_On) { // If the object is a ui-on, the UI was activated self->ui_active = true; self->send_settings_to_ui = true; } else if (obj->body.otype == self->uris.ui_Off) { // If the object is a ui-off, the UI was closed self->ui_active = false; } else if (obj->body.otype == self->uris.ui_State) { // If the object is a ui-state, it's the current UI settings const LV2_Atom* spp = NULL; const LV2_Atom* amp = NULL; lv2_atom_object_get(obj, self->uris.ui_spp, &spp, self->uris.ui_amp, &, 0); if (spp) { self->ui_spp = ((const LV2_Atom_Int*)spp)->body; } if (amp) { self->ui_amp = ((const LV2_Atom_Float*)amp)->body; } } } ev = lv2_atom_sequence_next(ev); } } // Process audio data for (uint32_t c = 0; c < self->n_channels; ++c) { if (self->ui_active) { // If UI is active, send raw audio data to UI tx_rawaudio(&self->forge, &self->uris, c, n_samples, self->input[c]); } // If not processing audio in-place, forward audio if (self->input[c] != self->output[c]) { memcpy(self->output[c], self->input[c], sizeof(float) * n_samples); } } // Close off sequence lv2_atom_forge_pop(&self->forge, &self->frame); }