Browse Source

fix sends being lost when moving tracks

cairo_optimizations
Alexandros Theodotou 3 years ago
parent
commit
5f1304255d
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 2
      data/meson.build
  2. 8
      inc/actions/move_tracks_action.h
  3. 4
      inc/audio/channel.h
  4. 6
      inc/audio/port_identifier.h
  5. 8
      inc/audio/tracklist.h
  6. 12
      meson.build
  7. 12
      src/audio/channel.c
  8. 66
      src/audio/port.c
  9. 3
      src/audio/track.c
  10. 15
      src/audio/track_processor.c
  11. 113
      src/audio/tracklist.c
  12. 153
      tests/actions/move_tracks.c
  13. 4
      tests/meson.build
  14. 10
      tests/test-instrument.lv2/README.txt
  15. 9
      tests/test-instrument.lv2/manifest.ttl.in
  16. 43
      tests/test-instrument.lv2/meson.build
  17. 144
      tests/test-instrument.lv2/test-instrument.c
  18. 38
      tests/test-instrument.lv2/test-instrument.ttl
  19. 54
      tests/test-instrument.lv2/uris.h

2
data/meson.build

@ -41,7 +41,7 @@ install_data ( @@ -41,7 +41,7 @@ install_data (
install_dir: samplesdir)
# install desktop file and launcher script
if os_linux or os_freebsd
if os_gnu or os_freebsd
zrythm_launcher_config = configuration_data ()
zrythm_launcher_config.set (
'SCHEMAS_DIR', schemasdir)

8
inc/actions/move_tracks_action.h

@ -78,19 +78,19 @@ move_tracks_action_new ( @@ -78,19 +78,19 @@ move_tracks_action_new (
int
move_tracks_action_do (
MoveTracksAction * self);
MoveTracksAction * self);
int
move_tracks_action_undo (
MoveTracksAction * self);
MoveTracksAction * self);
char *
move_tracks_action_stringize (
MoveTracksAction * self);
MoveTracksAction * self);
void
move_tracks_action_free (
MoveTracksAction * self);
MoveTracksAction * self);
/**
* @}

4
inc/audio/channel.h

@ -326,7 +326,7 @@ channel_append_all_ports ( @@ -326,7 +326,7 @@ channel_append_all_ports (
Channel * ch,
Port ** ports,
int * size,
int include_plugins);
bool include_plugins);
/**
* Exposes the channel's ports to the backend.
@ -337,6 +337,8 @@ channel_expose_ports_to_backend ( @@ -337,6 +337,8 @@ channel_expose_ports_to_backend (
/**
* Connects the channel's ports.
*
* This should only be called on new tracks.
*/
void
channel_connect (

6
inc/audio/port_identifier.h

@ -211,6 +211,11 @@ typedef enum PortFlags @@ -211,6 +211,11 @@ typedef enum PortFlags
/** MIDI automatable control, such as modwheel or
* pitch bend. */
PORT_FLAG_MIDI_AUTOMATABLE = 1 << 20,
/** Channels can send to this port (ie, this port
* is a track procesor midi/stereo in or a plugin
* sidechain in). */
PORT_FLAG_SENDABLE = 1 << 21,
} PortFlags;
static const cyaml_bitdef_t
@ -237,6 +242,7 @@ port_flags_bitvals[] = @@ -237,6 +242,7 @@ port_flags_bitvals[] =
{ .name = "channel_fader", .offset = 18, .bits = 1 },
{ .name = "automatable", .offset = 19, .bits = 1 },
{ .name = "midi_automatable", .offset = 20, .bits = 1 },
{ .name = "sendable", .offset = 21, .bits = 1 },
};
/**

8
inc/audio/tracklist.h

@ -184,10 +184,10 @@ void @@ -184,10 +184,10 @@ void
tracklist_remove_track (
Tracklist * self,
Track * track,
int rm_pl,
int free,
int publish_events,
int recalc_graph);
bool rm_pl,
bool free,
bool publish_events,
bool recalc_graph);
/**
* Moves a track from its current position to the

12
meson.build

@ -54,7 +54,7 @@ locales = [ @@ -54,7 +54,7 @@ locales = [
'ru', 'zh' ]
os_darwin = false
os_linux = false
os_gnu = false
os_freebsd = false
os_windows = false
bin_suffix = ''
@ -64,7 +64,7 @@ if host_machine.system() == 'darwin' @@ -64,7 +64,7 @@ if host_machine.system() == 'darwin'
os_darwin = true
lib_suffix = '.dylib'
elif host_machine.system() == 'linux'
os_linux = true
os_gnu = true
elif host_machine.system() == 'freebsd'
os_freebsd = true
elif host_machine.system() == 'windows'
@ -157,7 +157,7 @@ find_program ('gettext', required: true) @@ -157,7 +157,7 @@ find_program ('gettext', required: true)
dot_bin = find_program ('dot', required: false)
# find command to open a directory
if os_linux or os_freebsd
if os_gnu or os_freebsd
open_dir_cmd = 'xdg-open'
find_program (open_dir_cmd)
elif os_darwin
@ -531,7 +531,7 @@ if (carla_native_plugin_dep.found () and carla_standalone_dep.found () and carla @@ -531,7 +531,7 @@ if (carla_native_plugin_dep.found () and carla_standalone_dep.found () and carla
carla_bridge_native = find_program (
carla_libdir / 'carla-bridge-native',
required: false)
if carla_bridge_native.found() and (os_linux or os_freebsd)
if carla_bridge_native.found() and (os_gnu or os_freebsd)
install_data (
carla_bridge_native.path(),
install_dir: bindir)
@ -539,7 +539,7 @@ if (carla_native_plugin_dep.found () and carla_standalone_dep.found () and carla @@ -539,7 +539,7 @@ if (carla_native_plugin_dep.found () and carla_standalone_dep.found () and carla
carla_bridge_lv2_gtk2 = find_program (
carla_libdir / 'carla-bridge-lv2-gtk2',
required: false)
if carla_bridge_lv2_gtk2.found() and (os_linux or os_freebsd)
if carla_bridge_lv2_gtk2.found() and (os_gnu or os_freebsd)
install_data (
carla_bridge_lv2_gtk2.path(),
install_dir: bindir)
@ -642,7 +642,7 @@ else @@ -642,7 +642,7 @@ else
zrythm_deps += cc.find_library('fftw3f_threads')
endif
if os_linux
if os_gnu
zrythm_deps += cc.find_library('rt')
endif

12
src/audio/channel.c

@ -854,6 +854,8 @@ channel_reset_fader (Channel * self) @@ -854,6 +854,8 @@ channel_reset_fader (Channel * self)
/**
* Connects the channel's ports.
*
* This should only be called on new tracks.
*/
void
channel_connect (
@ -1076,7 +1078,7 @@ channel_append_all_ports ( @@ -1076,7 +1078,7 @@ channel_append_all_ports (
Channel * ch,
Port ** ports,
int * size,
int include_plugins)
bool include_plugins)
{
int j;
Track * tr = channel_get_track (ch);
@ -1936,7 +1938,7 @@ channel_update_track_pos ( @@ -1936,7 +1938,7 @@ channel_update_track_pos (
Port * ports[80000];
int num_ports = 0;
channel_append_all_ports (
self, ports, &num_ports, 1);
self, ports, &num_ports, true);
for (int i = 0; i < num_ports; i++)
{
@ -1974,6 +1976,12 @@ channel_update_track_pos ( @@ -1974,6 +1976,12 @@ channel_update_track_pos (
self->stereo_out->r, pos);
}
for (int i = 0; i < STRIP_SIZE; i++)
{
ChannelSend * send = &self->sends[i];
send->track_pos = pos;
}
fader_update_track_pos (&self->fader, pos);
passthrough_processor_update_track_pos (
&self->prefader, pos);

66
src/audio/port.c

@ -1313,7 +1313,7 @@ void @@ -1313,7 +1313,7 @@ void
port_update_identifier (
Port * self)
{
/* update in all sources/dests */
/* update in all sources */
for (int i = 0; i < self->num_srcs; i++)
{
Port * src = self->srcs[i];
@ -1324,6 +1324,8 @@ port_update_identifier ( @@ -1324,6 +1324,8 @@ port_update_identifier (
g_warn_if_fail (
src->dests[dest_idx] == self);
}
/* update in all dests */
for (int i = 0; i < self->num_dests; i++)
{
Port * dest = self->dests[i];
@ -1366,6 +1368,68 @@ port_update_track_pos ( @@ -1366,6 +1368,68 @@ port_update_track_pos (
Port * self,
int pos)
{
if (self->id.flags & PORT_FLAG_SENDABLE)
{
/* this could be a send receiver, so update
* the sending channel if matching */
for (int i = 0; i < self->num_srcs; i++)
{
Port * src = self->srcs[i];
if (src->id.owner_type ==
PORT_OWNER_TYPE_PREFADER ||
src->id.owner_type ==
PORT_OWNER_TYPE_FADER)
{
Track * src_track =
port_get_track (src, true);
Channel * src_ch =
track_get_channel (src_track);
for (int j = 0; j < STRIP_SIZE; j++)
{
ChannelSend * send =
&src_ch->sends[j];
if (send->is_empty)
continue;
switch (src_track->out_signal_type)
{
case TYPE_EVENT:
if (port_identifier_is_equal (
&send->dest_midi_id,
&self->id))
{
send->dest_midi_id.track_pos =
pos;
g_message ("updating midi send");
}
break;
case TYPE_AUDIO:
if (port_identifier_is_equal (
&send->dest_l_id,
&self->id))
{
send->dest_l_id.track_pos =
pos;
g_message ("updating audio L send");
}
else if (port_identifier_is_equal (
&send->dest_r_id,
&self->id))
{
send->dest_r_id.track_pos =
pos;
g_message ("updating audio R send");
}
break;
default:
break;
}
}
}
}
}
self->id.track_pos = pos;
port_update_identifier (self);
}

3
src/audio/track.c

@ -1051,6 +1051,9 @@ track_set_pos ( @@ -1051,6 +1051,9 @@ track_set_pos (
Track * track,
int pos)
{
g_message (
"%s: %s (%d) to %d",
__func__, track->name, track->pos, pos);
track->pos = pos;
for (int i = 0; i < track->num_lanes; i++)

15
src/audio/track_processor.c

@ -117,12 +117,11 @@ init_midi_port ( @@ -117,12 +117,11 @@ init_midi_port (
PortFlow flow = in ? FLOW_INPUT : FLOW_OUTPUT;
*port =
port_new_with_type (
TYPE_EVENT,
flow,
str);
port_new_with_type (TYPE_EVENT, flow, str);
port_set_owner_track_processor (*port, self);
if (in)
(*port)->id.flags |= PORT_FLAG_SENDABLE;
}
static void
@ -221,6 +220,12 @@ init_stereo_out_ports ( @@ -221,6 +220,12 @@ init_stereo_out_ports (
*sp =
stereo_ports_new_from_existing (l, r);
if (in)
{
l->id.flags |= PORT_FLAG_SENDABLE;
r->id.flags |= PORT_FLAG_SENDABLE;
}
}
/**

113
src/audio/tracklist.c

@ -514,10 +514,10 @@ void @@ -514,10 +514,10 @@ void
tracklist_remove_track (
Tracklist * self,
Track * track,
int rm_pl,
int free,
int publish_events,
int recalc_graph)
bool rm_pl,
bool free,
bool publish_events,
bool recalc_graph)
{
g_message ("removing %s",
track->name);
@ -589,8 +589,7 @@ tracklist_remove_track ( @@ -589,8 +589,7 @@ tracklist_remove_track (
mixer_recalc_graph (MIXER);
if (publish_events)
EVENTS_PUSH (ET_TRACKS_REMOVED,
NULL);
EVENTS_PUSH (ET_TRACKS_REMOVED, NULL);
}
/**
@ -609,23 +608,99 @@ tracklist_move_track ( @@ -609,23 +608,99 @@ tracklist_move_track (
int publish_events,
int recalc_graph)
{
tracklist_remove_track (
self,
track,
F_NO_REMOVE_PL,
F_NO_FREE,
F_NO_PUBLISH_EVENTS,
F_NO_RECALC_GRAPH);
g_message (
"%s: %s from %d to %d",
__func__, track->name, track->pos, pos);
bool move_higher = pos < track->pos;
tracklist_insert_track (
self,
track,
pos,
F_NO_PUBLISH_EVENTS,
recalc_graph);
Track * prev_visible =
tracklist_get_prev_visible_track (
TRACKLIST, track);
Track * next_visible =
tracklist_get_next_visible_track (
TRACKLIST, track);
/* clear the editor region if it exists and
* belongs to this track */
ZRegion * region =
clip_editor_get_region (CLIP_EDITOR);
if (region &&
arranger_object_get_track (
(ArrangerObject *) region) == track)
{
clip_editor_set_region (CLIP_EDITOR, NULL);
}
/* remove/deselect all objects */
track_clear (track);
int idx =
array_index_of (
self->tracks, self->num_tracks, track);
g_warn_if_fail (
track->pos == idx);
tracklist_selections_remove_track (
TRACKLIST_SELECTIONS, track, publish_events);
/* if it was the only track selected, select
* the next one */
if (TRACKLIST_SELECTIONS->num_tracks == 0 &&
(prev_visible || next_visible))
{
tracklist_selections_add_track (
TRACKLIST_SELECTIONS,
next_visible ? next_visible : prev_visible,
publish_events);
}
if (move_higher)
{
/* move all other tracks 1 track further */
for (int i = track->pos - 1; i >= pos; i--)
{
track_set_pos (self->tracks[i], i + 1);
}
}
else
{
/* move all other tracks 1 track earlier */
for (int i = track->pos + 1; i <= pos; i++)
{
track_set_pos (self->tracks[i], i - 1);
}
}
array_delete (
self->tracks, self->num_tracks, track);
/* if adding at the end, append it, otherwise
* insert it */
if (pos == self->num_tracks)
{
array_append (
self->tracks, self->num_tracks, track);
}
else
{
array_insert (
self->tracks, self->num_tracks,
pos, track);
}
track_set_pos (track, pos);
/* make the track the only selected track */
tracklist_selections_select_single (
TRACKLIST_SELECTIONS, track);
if (recalc_graph)
mixer_recalc_graph (MIXER);
if (publish_events)
EVENTS_PUSH (ET_TRACKS_MOVED, NULL);
g_message ("%s: finished moving track", __func__);
}
/**

153
tests/actions/move_tracks.c

@ -0,0 +1,153 @@ @@ -0,0 +1,153 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Zrythm
*
* Zrythm is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Zrythm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
*/
#include "actions/arranger_selections.h"
#include "actions/undoable_action.h"
#include "audio/audio_region.h"
#include "audio/automation_region.h"
#include "audio/chord_region.h"
#include "audio/master_track.h"
#include "audio/midi_note.h"
#include "audio/region.h"
#include "project.h"
#include "utils/flags.h"
#include "zrythm.h"
#include "tests/helpers/project.h"
#include <glib.h>
/**
* Bootstraps the test with test data.
*/
static void
rebootstrap (void)
{
char path_str[6000];
sprintf (
path_str, "file://%s/%s/",
TESTS_BUILDDIR, "test-instrument.lv2");
g_message ("path is %s", path_str);
plugin_manager_init (PLUGIN_MANAGER);
LilvNode * path =
lilv_new_uri (LILV_WORLD, path_str);
lilv_world_load_bundle (
LILV_WORLD, path);
lilv_node_free (path);
plugin_manager_scan_plugins (
PLUGIN_MANAGER, 1.0, NULL);
g_assert_cmpint (
PLUGIN_MANAGER->num_plugins, ==, 1);
/* for some reason it gets labeled as a plugin,
* force instrument */
PLUGIN_MANAGER->plugin_descriptors[0]->category =
PC_INSTRUMENT;
PLUGIN_MANAGER->plugin_descriptors[0]->category_str =
g_strdup ("Instrument");
}
static void
test_move_tracks ()
{
rebootstrap ();
/* create a track with an instrument */
UndoableAction * action =
create_tracks_action_new (
TRACK_TYPE_INSTRUMENT,
PLUGIN_MANAGER->plugin_descriptors[0], NULL,
3, 1);
undo_manager_perform (UNDO_MANAGER, action);
Track * ins_track = TRACKLIST->tracks[3];
g_assert_true (
ins_track->type == TRACK_TYPE_INSTRUMENT);
/* create an fx track and send to it */
action =
create_tracks_action_new (
TRACK_TYPE_AUDIO_BUS, NULL, NULL,
4, 1);
undo_manager_perform (UNDO_MANAGER, action);
Track * fx_track = TRACKLIST->tracks[4];
g_assert_true (
fx_track->type == TRACK_TYPE_AUDIO_BUS);
ChannelSend * send = &ins_track->channel->sends[0];
StereoPorts * stereo_in =
fx_track->processor.stereo_in;
channel_send_connect_stereo (
send, fx_track->processor.stereo_in);
/* check that the sends are correct */
g_assert_true (!send->is_empty);
g_assert_true (
port_identifier_is_equal (
&send->dest_l_id, &stereo_in->l->id) &&
port_identifier_is_equal (
&send->dest_r_id, &stereo_in->r->id));
/* swap tracks */
track_select (ins_track, true, true, false);
action =
move_tracks_action_new (
TRACKLIST_SELECTIONS, 4);
undo_manager_perform (UNDO_MANAGER, action);
/* check that ids are updated */
ins_track = TRACKLIST->tracks[4];
fx_track = TRACKLIST->tracks[3];
g_assert_true (
ins_track->type == TRACK_TYPE_INSTRUMENT);
g_assert_true (
fx_track->type == TRACK_TYPE_AUDIO_BUS);
send = &ins_track->channel->sends[0];
stereo_in =
fx_track->processor.stereo_in;
g_assert_cmpint (
stereo_in->l->id.track_pos, ==, 3);
g_assert_cmpint (
stereo_in->r->id.track_pos, ==, 3);
g_assert_cmpint (send->track_pos, ==, 4);
g_assert_true (!send->is_empty);
g_assert_true (
port_identifier_is_equal (
&send->dest_l_id, &stereo_in->l->id) &&
port_identifier_is_equal (
&send->dest_r_id, &stereo_in->r->id));
}
int
main (int argc, char *argv[])
{
g_test_init (&argc, &argv, NULL);
test_helper_zrythm_init ();
#define TEST_PREFIX "/actions/move_tracks/"
g_test_add_func (
TEST_PREFIX "test move tracks",
(GTestFunc) test_move_tracks);
return g_test_run ();
}

4
tests/meson.build

@ -19,6 +19,7 @@ if get_option ('enable-tests') @@ -19,6 +19,7 @@ if get_option ('enable-tests')
subdir('eg-amp.lv2')
subdir('eg-fifths.lv2')
subdir('test-instrument.lv2')
test_env = environment ()
test_env.set (
@ -65,9 +66,10 @@ if get_option ('enable-tests') @@ -65,9 +66,10 @@ if get_option ('enable-tests')
['utils/string', true],
]
if os_linux
if os_gnu
tests += [
['actions/mixer_selections', true],
['actions/move_tracks', true],
]
endif

10
tests/test-instrument.lv2/README.txt

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
This is not part of Zrythm, but is used with Zrythm.
This was taken from the lv2 repository and the
following is the original README.txt.
----
== Fifths ==
This plugin demonstrates simple MIDI event reading and writing.

9
tests/test-instrument.lv2/manifest.ttl.in

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
<https://lv2.zrythm.org/test-instrument>
a lv2:Plugin,
lv2:InstrumentPlugin ;
lv2:binary <test-instrument@LIB_EXT@> ;
rdfs:seeAlso <test-instrument.ttl> .

43
tests/test-instrument.lv2/meson.build

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
# Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
#
# This file is part of Zrythm
#
# Zrythm is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Zrythm is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
test_instrument_cdata = configuration_data ()
if os_windows
test_instrument_cdata.set ('LIB_EXT', '.dll')
else
test_instrument_cdata.set ('LIB_EXT', '.so')
endif
manifest_ttl = configure_file (
input: 'manifest.ttl.in',
output: 'manifest.ttl',
configuration: test_instrument_cdata,
)
test_instrument_ttl = configure_file (
input: 'test-instrument.ttl',
output: 'test-instrument.ttl',
configuration: test_instrument_cdata,
)
test_instrument_lv2 = shared_library (
'test-instrument',
name_prefix: '',
sources: [
'test-instrument.c',
],
dependencies: [ lv2_dep, libm ],
install: false,
)

144
tests/test-instrument.lv2/test-instrument.c

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
/*
LV2 Fifths Example Plugin
Copyright 2014-2016 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef __cplusplus
# include <stdbool.h>
#endif
#include "lv2/atom/atom.h"
#include "lv2/atom/util.h"
#include "lv2/core/lv2.h"
#include "lv2/core/lv2_util.h"
#include "lv2/log/log.h"
#include "lv2/log/logger.h"
#include "lv2/midi/midi.h"
#include "lv2/urid/urid.h"
#include "./uris.h"
enum {
FIFTHS_IN = 0,
FIFTHS_OUT = 1
};
typedef struct {
// Features
LV2_URID_Map* map;
LV2_Log_Logger logger;
// Ports
const LV2_Atom_Sequence* in_port;
float * out_port;
// URIs
FifthsURIs uris;
} Fifths;
static void
connect_port(LV2_Handle instance,
uint32_t port,
void* data)
{
Fifths* self = (Fifths*)instance;
switch (port) {
case FIFTHS_IN:
self->in_port = (const LV2_Atom_Sequence*)data;
break;
case FIFTHS_OUT:
self->out_port = (float *) data;
break;
default:
break;
}
}
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor,
double rate,
const char* path,
const LV2_Feature* const* features)
{
// Allocate and initialise instance structure.
Fifths* self = (Fifths*)calloc(1, sizeof(Fifths));
if (!self) {
return NULL;
}
// Scan host features for URID map
const char* missing = lv2_features_query(
features,
LV2_LOG__log, &self->logger.log, false,
LV2_URID__map, &self->map, true,
NULL);
lv2_log_logger_set_map(&self->logger, self->map);
if (missing) {
lv2_log_error(&self->logger, "Missing feature <%s>\n", missing);
free(self);
return NULL;
}
map_fifths_uris(self->map, &self->uris);
return (LV2_Handle)self;
}
static void
cleanup(LV2_Handle instance)
{
free(instance);
}
static void
run(LV2_Handle instance,
uint32_t sample_count)
{
Fifths* self = (Fifths*)instance;
memset (
self->out_port, 0, sample_count * sizeof (float));
}
static const void*
extension_data(const char* uri)
{
return NULL;
}
static const LV2_Descriptor descriptor = {
EG_FIFTHS_URI,
instantiate,
connect_port,
NULL, // activate,
run,
NULL, // deactivate,
cleanup,
extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor* lv2_descriptor(uint32_t index)
{
switch (index) {
case 0:
return &descriptor;
default:
return NULL;
}
}

38
tests/test-instrument.lv2/test-instrument.ttl

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
<https://lv2.zrythm.org/test-instrument>
a lv2:Plugin,
lv2:InstrumentPlugin ;
doap:name "Test Instrument" ;
doap:license <http://opensource.org/licenses/isc> ;
lv2:project <https://lv2.zrythm.org> ;
lv2:requiredFeature urid:map ;
lv2:optionalFeature lv2:hardRTCapable ;
lv2:port [
a lv2:InputPort ,
atom:AtomPort ;
atom:bufferType atom:Sequence ;
atom:supports midi:MidiEvent ;
lv2:index 0 ;
lv2:symbol "in" ;
lv2:name "In"
] , [
a lv2:OutputPort ,
lv2:AudioPort ;
lv2:index 1 ;
lv2:symbol "mono_out" ;
lv2:name "Mono Out"
] , [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 2 ;
lv2:symbol "test" ;
lv2:name "Test param" ;
lv2:default 0.0 ;
lv2:minimum -90.0 ;
lv2:maximum 24.0
] .

54
tests/test-instrument.lv2/uris.h

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
/*
LV2 Fifths Example Plugin
Copyright 2014-2015 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef FIFTHS_URIS_H
#define FIFTHS_URIS_H
#include "lv2/log/log.h"
#include "lv2/midi/midi.h"
#include "lv2/patch/patch.h"
#include "lv2/state/state.h"
#define EG_FIFTHS_URI "https://lv2.zrythm.org/test-instrument"
typedef struct {
LV2_URID atom_Path;
LV2_URID atom_Resource;
LV2_URID atom_Sequence;
LV2_URID atom_URID;
LV2_URID atom_eventTransfer;
LV2_URID midi_Event;
LV2_URID patch_Set;
LV2_URID patch_property;
LV2_URID patch_value;
} FifthsURIs;
static inline void
map_fifths_uris(LV2_URID_Map* map, FifthsURIs* uris)
{
uris->atom_Path = map->map(map->handle, LV2_ATOM__Path);
uris->atom_Resource = map->map(map->handle, LV2_ATOM__Resource);
uris->atom_Sequence = map->map(map->handle, LV2_ATOM__Sequence);
uris->atom_URID = map->map(map->handle, LV2_ATOM__URID);
uris->atom_eventTransfer = map->map(map->handle, LV2_ATOM__eventTransfer);
uris->midi_Event = map->map(map->handle, LV2_MIDI__MidiEvent);
uris->patch_Set = map->map(map->handle, LV2_PATCH__Set);
uris->patch_property = map->map(map->handle, LV2_PATCH__property);
uris->patch_value = map->map(map->handle, LV2_PATCH__value);
}
#endif /* FIFTHS_URIS_H */
Loading…
Cancel
Save