lv2 midi input

Programming applications for making music on Linux.

Moderators: MattKingUSA, khz

User avatar
skei
Established Member
Posts: 103
Joined: Sun May 18, 2014 4:24 pm

lv2 midi input

Postby skei » Thu Jun 21, 2018 11:07 am

i'm currently adding lv2 support to my plugin framework.. but the documentation isn't the best i've seen, and i have a few problems.. i started with the midi gate example here: http://lv2plug.in/book/#_midi_gate, and modified it so that it just prints out the raw midi bytes when there's a midi event.. this works in qtractor and ardour, but not in carla.. which is a bit unfortunate, since carla is the only lv2-supporting host i use myself.. with carla, if i print out the supported extensions (the 'features' thing) during instantiation, i don't see any mention of anything resembling midi.. but then, qtractor tells me it only supports one feature ('http://lv2plug.in/ns/ext/urid#map'), but still it works.. hmm.. i'm getting confused..

so, concretely.. what do i do to receive midi from carla?

and also, is there a 'canonical' list of extensions i can expect all hosts to support?

- tor-helge

User avatar
skei
Established Member
Posts: 103
Joined: Sun May 18, 2014 4:24 pm

Re: lv2 midi input

Postby skei » Fri Jun 22, 2018 4:27 am

i've been looking through a bunch of examples on github, and trying the event extension stuff, but still the same results..
there's obviously something i don't understand.. :-/ maybe i should put lv2 away for a while, and focus on vst3, and then (possibly) return to it a little later..

ventosus
Established Member
Posts: 23
Joined: Sat Jun 27, 2015 6:29 pm
Contact:

Re: lv2 midi input

Postby ventosus » Fri Jun 22, 2018 7:10 am

this works in qtractor and ardour, but not in carla..


Some hosts route/eat/drop standard output/error from plugins. Don't know whether carla is one of them. You can try to write to a file instead...

Or even better, use LV2's log extension (if carla supports it).

so, concretely.. what do i do to receive midi from carla?


You just mention in your plugin metadata (the strange RDF turtle file) that your atom event port support MIDI, and the host will send the MIDI to that port.

and also, is there a 'canonical' list of extensions i can expect all hosts to support?


No, that's why they are called extensions. It works like this: If a plugin needs an extension, it mentions that in its plugin metadata and if the host does not support that extension, it simply won't support that plugin, e.g. don't show it as a selection to the user.
Last edited by ventosus on Fri Jun 22, 2018 7:11 am, edited 1 time in total.

ventosus
Established Member
Posts: 23
Joined: Sat Jun 27, 2015 6:29 pm
Contact:

Re: lv2 midi input

Postby ventosus » Fri Jun 22, 2018 7:11 am

Here a MIDI-only plugin bundle with lots of examples:

https://github.com/x42/midifilter.lv2

ventosus
Established Member
Posts: 23
Joined: Sat Jun 27, 2015 6:29 pm
Contact:

Re: lv2 midi input

Postby ventosus » Fri Jun 22, 2018 7:15 am

qtractor tells me it only supports one feature ('http://lv2plug.in/ns/ext/urid#map')


MIDI plugins (or more general event plugins) need that extension. So the plugin you've looked at lists it as required in its plugin metadata.

Some hosts list all their supported extensions in the features list. Other hosts only list the required (by the plugin) extensions in the features list. The latter is most probably what you saw in qtractor (I'm pretty sure that it supports more extensions...)

User avatar
skei
Established Member
Posts: 103
Joined: Sun May 18, 2014 4:24 pm

Re: lv2 midi input

Postby skei » Fri Jun 22, 2018 7:29 am

ventosus wrote:Some hosts route/eat/drop standard output/error from plugins. Don't know whether carla is one of them. You can try to write to a file instead...
Or even better, use LV2's log extension (if carla supports it).


i know.. (and yes, carla drops stdout, it seems).. in my framework, i have a bunch of "debug outputs", selectable with some #ifdefs, like stdout, logfile, socket, gui/window, etc.. when coding plugins, i usually push all debug output through a socket, and print it out in another terminal.. all other debug info is printed correctly, so this works quite well..

ventosus wrote:You just mention in your plugin metadata (the strange RDF turtle file) that your atom event port support MIDI, and the host will send the MIDI to that port.


i thought i did.. i followed the examples rigorously, and double- and triple-checked everything.. but obviously there's something i missed, or whatever..

ventosus wrote:If a plugin needs an extension, it mentions that in its plugin metadata and if the host does not support that extension, it simply won't support that plugin, e.g. don't show it as a selection to the user.


yeah, i have understood that now..

User avatar
skei
Established Member
Posts: 103
Joined: Sun May 18, 2014 4:24 pm

Re: lv2 midi input

Postby skei » Fri Jun 22, 2018 7:31 am

ventosus wrote:Here a MIDI-only plugin bundle with lots of examples:

https://github.com/x42/midifilter.lv2


thanks!

User avatar
skei
Established Member
Posts: 103
Joined: Sun May 18, 2014 4:24 pm

Re: lv2 midi input

Postby skei » Fri Jun 22, 2018 7:35 am

ventosus wrote:
qtractor tells me it only supports one feature ('http://lv2plug.in/ns/ext/urid#map')


MIDI plugins (or more general event plugins) need that extension. So the plugin you've looked at lists it as required in its plugin metadata.

Some hosts list all their supported extensions in the features list. Other hosts only list the required (by the plugin) extensions in the features list. The latter is most probably what you saw in qtractor (I'm pretty sure that it supports more extensions...)


ok..

User avatar
falkTX
Established Member
Posts: 6646
Joined: Sat Jan 09, 2010 3:04 pm

Re: lv2 midi input

Postby falkTX » Fri Jun 22, 2018 9:40 am

Carla captures the stdout/stderr so it can be shown on the GUI, it is useful to get some debug output out of plugins from users that do not start Carla from a terminal.
Disabling this is quite easy, it is right on the first page of Carla settings.

User avatar
skei
Established Member
Posts: 103
Joined: Sun May 18, 2014 4:24 pm

Re: lv2 midi input

Postby skei » Fri Jun 22, 2018 10:18 am

falkTX wrote:Carla captures the stdout/stderr so it can be shown on the GUI, it is useful to get some debug output out of plugins from users that do not start Carla from a terminal.
Disabling this is quite easy, it is right on the first page of Carla settings.


yeah.. i see it now.. :-) no idea why i overlooked that before..
but since i have this socket thing up and running (i initially needed it to test and debug vst plugins in bitwig), it's not an issue, actually..

User avatar
skei
Established Member
Posts: 103
Joined: Sun May 18, 2014 4:24 pm

Re: lv2 midi input

Postby skei » Sat Jun 23, 2018 4:43 pm

so, the problem i'm having is getting midi input from carla.. the code below works in qtractor and ardour (haven't tested much else).. in carla, the light/led lights up when i press a midi key, but my plugin doesn't seem to receive the midi events..

i tried to extract the minimal code needed to show what i do.. let's hope it still understandable :?

i separate plugins into two classes, the main plugin class which handles/manages the plugin/.so itself, and the descriptors, etc, and an instance class for each, well, instance.. the plugin class is a static class (object?), mainly to have automatic cleanup via the destructor when the .so is unloaded.. MLV2* prefixed variables are part of the plugin (or instance) class, on_instance_midiEvent() is a virtual function that individual plugins override if they want midi input.. and also, most of this is wrapped in #ifdef PLUGIN_RECEIVE MIDI .. #endif and similar constructs..

define midi input port:

Code: Select all

lv2:port [
   a ev:EventPort, lv2:InputPort;
   lv2:index         6 ;
   ev:supportsEvent   <http://lv2plug.in/ns/ext/midi#MidiEvent> ;
   lv2:symbol         "midi" ;
   lv2:name         "MIDI Input" ;
] .


instantiation:

Code: Select all

LV2_URI_Map_Feature* map_feature;
const LV2_Feature* const*  ft;
for (ft=features; *ft; ft++) {
   if (!strcmp((*ft)->URI,"http://lv2plug.in/ns/ext/uri-map")) { // LV2_URI_MAP_URI
      map_feature = (LV2_URI_Map_Feature*)(*ft)->data;
      MLV2EventType = map_feature->uri_to_id(
         map_feature->callback_data,
         "http://lv2plug.in/ns/ext/event",
         "http://lv2plug.in/ns/ext/midi#MidiEvent"
      );
   }
   else if (!strcmp((*ft)->URI, "http://lv2plug.in/ns/ext/event")) {
      MLV2EventFeature =(LV2_Event_Feature*)(*ft)->data;
   }
}


connect the port:

Code: Select all

MLV2EventBuffer = (LV2_Event_Buffer*)data_location;


and finally, at the start of the run() function:

Code: Select all

LV2_Event_Iterator event_iterator;
lv2_event_begin(&event_iterator,MLV2EventBuffer);
while (lv2_event_is_valid(&event_iterator)) {
   uint8_t* data;
   LV2_Event* event = lv2_event_get(&event_iterator,&data);
   if (event->type == 0) {
      MLV2EventFeature->lv2_event_unref(MLV2EventFeature->callback_data, event);
   }
   else if (event->type == MLV2EventType) {
      uint32_t offset = event->frames;
      const uint8_t* msg = (uint8_t*)data;
      on_instance_midiEvent(offset,msg[0],msg[1],msg[2]);
   }
   lv2_event_increment(&event_iterator);
}


does anybody see any obvious errors or missing things or other issues?

i also tried another way, using some AtomPort stuff (i think?), with the same results,
except that i felt it was more confusing - more terminology and stuff i don't fully grasp yet..
(but that also worked in qtractor and ardour, but not carla, so the problem might be somewhere else?)

User avatar
falkTX
Established Member
Posts: 6646
Joined: Sat Jan 09, 2010 3:04 pm

Re: lv2 midi input

Postby falkTX » Sat Jun 23, 2018 6:06 pm

do you have more than 1 midi input port?
try setting the lv2:designation lv2:control on the port.

you are using 2 deprecated things, which is not a good thing to start with.
atom can be confusing, but please use urid-map instead of uri-map.
the 2nd parameter on the uri-map function is confusing..

is the full code published somewhere?
also, is your carla self-compiled? I would say, make sure you are using latest git, I am about to make a new bugfix release.
lots of stuff fixed lately

User avatar
skei
Established Member
Posts: 103
Joined: Sun May 18, 2014 4:24 pm

Re: lv2 midi input

Postby skei » Sat Jun 23, 2018 6:42 pm

falkTX wrote:do you have more than 1 midi input port?


no, just one.. this is just a test plugin, and i have 2 audio inputs, 2 audio outputs, and 2 control inputs (parameters), plus this midi input

falkTX wrote:try setting the lv2:designation lv2:control on the port.


i will try that

falkTX wrote:you are using 2 deprecated things, which is not a good thing to start with.
atom can be confusing, but please use urid-map instead of uri-map.
the 2nd parameter on the uri-map function is confusing..


ok.. i have to read up a little about these atoms, and look at urid-map

falkTX wrote:is the full code published somewhere?


not yet.. i will publish the library/framework as soon as i can get the main plugin formats (ladspa, dssi, lv2, vst2, vst3, standalone) basically working (at least a minimal version, so i can build for example a simple gui-less synth in all formats)

..and decided on licensing and all that stuff :-/

falkTX wrote:also, is your carla self-compiled? I would say, make sure you are using latest git, I am about to make a new bugfix release.
lots of stuff fixed lately


i use the latest version from your kx studio repositories (help/about says "version 1.9.8 (2.0-beta6)"
(in linux mint/cinnamon, in case that matters)..

always looking forward to new versions of your stuff..
(mega-thanks for all your linux-audio efforts!)

User avatar
skei
Established Member
Posts: 103
Joined: Sun May 18, 2014 4:24 pm

Re: lv2 midi input

Postby skei » Sat Jun 23, 2018 7:33 pm

i looked at the example from here: http://lv2plug.in/book/#_midi_gate
and came up with something like the below.. i don't fully understand what everyting is doing yet, so i absolutely need to look at some docs :-)

but, same result.. works in qtractor, didn't test in ardour, doesn't work in carla..

the little led/light on the plugin in the carla rack view lights up when i press a midi key.. does that mean carla is sending the midi to the plugin?

kode_debug.ttl:

Code: Select all

@prefix doap:      <http://usefulinc.com/ns/doap#> .
@prefix lv2:      <http://lv2plug.in/ns/lv2core#> .
@prefix rdf:      <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:      <http://www.w3.org/2000/01/rdf-schema#> .
@prefix atom:      <http://lv2plug.in/ns/ext/atom#> .
@prefix midi:      <http://lv2plug.in/ns/ext/midi#> .
@prefix urid:      <http://lv2plug.in/ns/ext/urid#> .

<urn:skei.audio/kode_debug>
   a lv2:Plugin , lv2:InstrumentPlugin ;
   doap:name         "kode_debug" ;
   lv2:optionalFeature   lv2:hardRTCapable ;
   lv2:requiredFeature   urid:map ;
   lv2:port [
      ...
      ...
   ] , [
      a lv2:InputPort , atom:AtomPort ;
      atom:bufferType      atom:Sequence ;
      atom:supports      midi:MidiEvent ;
      lv2:designation      lv2:control ;
      lv2:index         6 ;
      lv2:symbol         "midi_in" ;
      lv2:name         "Midi in"
   ] .


Code: Select all

#define KODE_PLUGIN_LV2_MAX_URIS 16

plugin instance class:

   const LV2_Atom_Sequence*   MLV2AtomSequence   = KODE_NULL;
   LV2_URID_Map*            MLV2Map            = KODE_NULL;
   KODE_uint32               MMidiEventType      = 0;
   LV2_URID*                MLV2URIS         = KODE_NULL;
      
plugin class.

   // for some reason, i thought it could be smart to prepare for multiple uri's..
   LV2_URID   MLV2URIS[KODE_PLUGIN_LV2_MAX_URIS]   = {0};
      
instantiate()

   LV2_URID_Map* map = NULL;
   for (int i=0; features[i]; ++i) {
      if (!strcmp(features[i]->URI, LV2_URID__map)) {
         map = (LV2_URID_Map*)features[i]->data;
         break;
      }
   }
   if (!map) return KODE_NULL;
   MLV2URIS[0] = map->map(map->handle, LV2_MIDI__MidiEvent);
   ...
   instance->MLV2URIS = MLV2URIS;   

connect()

   MLV2AtomSequence = (const LV2_Atom_Sequence*)data_location;

run()

   uint32_t offset = 0;
   LV2_ATOM_SEQUENCE_FOREACH(MLV2AtomSequence, ev) {
      if (ev->body.type == MLV2URIS[0]) {
         const uint8_t* const msg = (const uint8_t*)(ev + 1);
         offset = (uint32_t)ev->time.frames;
         on_instance_midiEvent(offset,msg[0],msg[1],msg[2]);
      }
   }

User avatar
falkTX
Established Member
Posts: 6646
Joined: Sat Jan 09, 2010 3:04 pm

Re: lv2 midi input

Postby falkTX » Sat Jun 23, 2018 8:51 pm

are you trying to send MIDI CCs by any chance?
those are disabled by default.

btw, when plugins have midi input, you can use the built-in keyboard widget to send some notes to the plugin.
test that too, to see if something gets received or not.


Return to “Developer's Section”

Who is online

Users browsing this forum: No registered users and 2 guests