<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>drobilla.net - Ardour</title><link href="https://drobilla.net/" rel="alternate"/><link href="https://drobilla.net/category/ardour/feed/atom" rel="self"/><id>https://drobilla.net/</id><updated>2014-11-03T20:09:00-05:00</updated><entry><title>LV2 Plugin Control Units in Ardour</title><link href="https://drobilla.net/2014/11/03/lv2-plugin-control-units-in-ardour.html" rel="alternate"/><published>2014-11-03T20:09:00-05:00</published><updated>2014-11-03T20:09:00-05:00</updated><author><name>drobilla</name></author><id>tag:drobilla.net,2014-11-03:/2014/11/03/lv2-plugin-control-units-in-ardour.html</id><content type="html">&lt;p&gt;LV2 has had a “units” extension since the beginning, which allows
plugins to specify units like Hz or dB for their controls. To date this
information has not been used very widely by hosts, so I've done some
work in Ardour to use this information for better UI generation and
intelligent plugin control.&lt;/p&gt;
&lt;p&gt;Units can specify a format string which describes how to print a value
in that unit. This is now used to draw the text on control sliders:&lt;/p&gt;
&lt;p&gt;&lt;img alt="An Ardour control dialog for an LV2 plugin." src="/images/control_dialog-300x152.png"&gt;&lt;/p&gt;
&lt;p&gt;The same controls are used in automation lane headers. If the control is
a note number, then right-clicking will present a menu with an option to
pop up a note selector dialog where the value can be chosen on a piano
keyboard:&lt;/p&gt;
&lt;p&gt;&lt;img alt="The select note menu on a note number port." src="/images/select_note_menu-300x286.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="The Ardour note selector dialog." src="/images/note_choose_dialog-300x51.png"&gt;&lt;/p&gt;
&lt;p&gt;Similarly, numeric frequency controls have a context menu which can set
the value to a specific number of beats in the current tempo, if the
frequency range is low:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Setting a low frequency port in beats." src="/images/set_beats_menu-272x300.png"&gt;&lt;/p&gt;
&lt;p&gt;If the frequency range is high, then numeric frequency ports can be set
with the note selector dialog just like note numbers:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Setting an audible frequency port by note." src="/images/set_freq_menu-300x83.png"&gt;&lt;/p&gt;
&lt;p&gt;In the future, it would be nice to have this idea applied more
extensively so automation lanes can “pretend” a port is in the desired
unit, for example allowing the user to automate an LFO frequency in
beats, or a cutoff frequency in notes. Until then, being able to at
least easily set controls to musically sensible values makes many
production tasks easier, particularly in electronic music where it's
often desirable to set plugin controls based on key or tempo.&lt;/p&gt;
&lt;p&gt;Up next is setting time ports based on tempo, for cases like setting
delay lines to a certain number of beats, but many plugins are missing
the unit information required to make this possible. Hopefully better
and more widespread host support will provide some incentive for plugin
authors to specify the units of their ports. It is very simple to do so,
see the &lt;a href="http://lv2plug.in/ns/extensions/units"&gt;LV2 units&lt;/a&gt; documentation
for examples.&lt;/p&gt;</content><category term="misc"/><category term="Ardour"/><category term="Hacking"/><category term="LAD"/><category term="LV2"/></entry><entry><title>Labeled MIDI controller values in Ardour</title><link href="https://drobilla.net/2014/01/06/labeled-midi-controller-values-in-ardour.html" rel="alternate"/><published>2014-01-06T17:09:00-05:00</published><updated>2014-01-06T17:09:00-05:00</updated><author><name>drobilla</name></author><id>tag:drobilla.net,2014-01-06:/2014/01/06/labeled-midi-controller-values-in-ardour.html</id><content type="html">&lt;p&gt;A while ago, I implemented &lt;a href="/2013/01/20/ardour-midi-patch-controller-and-note-names.html"&gt;MIDI patch, controller, and note name
support for
Ardour&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There was one thing missing from that work: labelled controller values.
This is particularly useful for controllers that don't represent a
continuous numeric parameter, but instead have a set of specific values.
For example, the Moog Minitaur supports CC #86 to control the LFO sync
clock division, but it's not obvious how a 0-127 number maps to a clock
division. From the manual, we can learn that 61-67 is “1/4”, 68-73 is
“1/8 Dot”, and so on.&lt;/p&gt;
&lt;p&gt;Translate that information into standard MIDINameDocument format, and a
few hours of hacking later... voila, Ardour displays something sensible
when hovering over an automation point instead of a meaningless number.&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/ardour_midi_cc_cursor.png"&gt;&lt;img alt="Ardour displaying a labelled MIDI controller value when hovering over an automation point." src="/images/ardour_midi_cc_cursor-150x85.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want to add support for your MIDI device or program, my .midnam
documents for the Moog Minitaur, MF-104M, and MF-108M, included in the
Ardour distribution all contain examples of labelled values. It should
be relatively obvious how to copy and modify these for other devices.&lt;/p&gt;</content><category term="misc"/><category term="Ardour"/><category term="Hacking"/><category term="LAD"/></entry><entry><title>Ardour MIDI Patch, Controller, and Note Names</title><link href="https://drobilla.net/2013/01/20/ardour-midi-patch-controller-and-note-names.html" rel="alternate"/><published>2013-01-20T00:50:00-05:00</published><updated>2013-01-20T00:50:00-05:00</updated><author><name>drobilla</name></author><id>tag:drobilla.net,2013-01-20:/2013/01/20/ardour-midi-patch-controller-and-note-names.html</id><content type="html">&lt;p&gt;Ardour has supported displaying MIDI patch names loaded from a
&lt;a href="http://www.midi.org/dtds/midi_xml.php"&gt;MIDINameDocument&lt;/a&gt; (or “midnam”
file) for a while, though only patches, and even that was pretty flaky.
Since this has become an itch for me and it's time for Ardour MIDI to
reach release quality, I took some time to give it a serious overhaul.
In this case, a picture or two is indeed worth a thousand words:&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/ardour_midi_note_names.png"&gt;&lt;img alt="Human readable MIDI note names in Ardour 3" src="/images/ardour_midi_note_names-150x119.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/ardour_midi_control_names.png"&gt;&lt;img alt="Human readable MIDI controller menu in Ardour" src="/images/ardour_midi_control_names-150x104.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The note names are mainly useful for doing percussion. Several of the
bundled midnam files have note names defined, and I have added one for
General MIDI drums, which more or less corresponds to a lot of
instruments, including &lt;a href="http://www.hydrogen-music.org/"&gt;Hydrogen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Controller names, to my surprise, were not present in any of the
existing midnam files at all. I wanted to sequence a hardware synth (the
Moog Minitaur) without constantly referring to the manual and trying to
remember which CC is which, so I wrote a new midnam file for the device
and implemented support in Ardour. I am very disappointed to learn that
there is no ability to group controllers, which really is the best way
to do things, so I may embrace and extend (in a completely backwards
compatible way) the format in the future to provide a better interface.&lt;/p&gt;
&lt;p&gt;The quality of midnam files scattered around the 'net is atrocious. The
MMA actually hosts a DTD for it, but most files use the wrong DOCTYPE
(usually with a broken link), among other problems. I fixed and cleaned
up all the bundled ones in Ardour, validated them against the DTD, and
left a README in that directory about how to do so. Hopefully this,
along with incentive added by these features, encourages the community
to grow a nice set of quality midnam files.&lt;/p&gt;
&lt;p&gt;So, MIDI name support in Ardour is now in pretty good shape. Now we just
need to add the corresponding LV2 support...&lt;/p&gt;</content><category term="misc"/><category term="Ardour"/><category term="Hacking"/><category term="LAD"/><category term="MIDI"/></entry><entry><title>Ingen as Remote Server or LV2 Plugin</title><link href="https://drobilla.net/2012/12/22/ingen-as-remote-server-or-lv2-plugin.html" rel="alternate"/><published>2012-12-22T13:52:00-05:00</published><updated>2012-12-22T13:52:00-05:00</updated><author><name>drobilla</name></author><id>tag:drobilla.net,2012-12-22:/2012/12/22/ingen-as-remote-server-or-lv2-plugin.html</id><content type="html">&lt;p&gt;I have been working on the control protocol aspect of
&lt;a href="/software/ingen"&gt;Ingen&lt;/a&gt;, towards a few goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Working GUI communicating with the server via a socket&lt;/li&gt;
&lt;li&gt;Decent Python bindings for socket interface&lt;/li&gt;
&lt;li&gt;Ingen as an LV2 plugin&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Python bindings got fleshed out to support a script for loading
&lt;a href="http://alsamodular.sourceforge.net/"&gt;AMS&lt;/a&gt; patches into Ingen I have
been working on (very preliminary, but in the repository and installed
as ‘ingenams’). The socket interface is now sensibly synchronous, e.g.
you send a command, and recv on the socket to get the response, which
will include a status as well as whatever patch updates happened as a
result of the command. I am happy with this route to language bindings,
it's much more pleasant than a mess of direct bindings (e.g. via swig)
and being protocol controlled has many other advantages. The Python
interface is implemented purely in Python, it should be simple to do the
same in any language that can use sockets.&lt;/p&gt;
&lt;p&gt;The Ingen GUI can communicate with the engine via the same protocol, so
you can build patches over the network (e.g. if Ingen is running on a
headless machine as part of an audio rig). It can also run in the same
process and use direct function calls for maximum performance.&lt;/p&gt;
&lt;p&gt;The Ingen protocol uses the &lt;a href="http://lv2plug.in/ns/ext/patch/"&gt;LV2 Patch&lt;/a&gt;
vocabulary to describe changes. For the socket interface, this is
represented entirely in Turtle. When running as an LV2 plugin, Ingen
uses conceptually the same protocol, except in a binary format using LV2
&lt;a href="http://lv2plug.in/ns/ext/atom/"&gt;atoms&lt;/a&gt;. This is a nice example of the
benefits of having things defined in a good abstract model which can be
encoded in many ways. For example, it would be relatively simple to
implement control via JSON for a browser-based Ingen UI, which seems
like the best way to go for separate control panels, but that's a topic
for another day.&lt;/p&gt;
&lt;p&gt;Since Ingen control can be expressed as atoms, it can run as an LV2
plugin with a full patcher UI and communicate only via LV2 ports. The UI
is embeddable, and there is no memory sharing between engine and UI or
hidden communication, everything is host managed. Here is a screenshot
of Ingen running in &lt;a href="http://ardour.org/"&gt;Ardour&lt;/a&gt; 3. The MIDI in Ardour
is played through an Ingen synth plugin, and the output has been
recorded to the audio track. The patch can be manipulated live while
running in Ardour, except for top level ports.&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/ingen_in_ardour.png"&gt;&lt;img alt="Ingen running in Ardour as an LV2 plugin" src="/images/ingen_in_ardour-150x113.png"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="misc"/><category term="Ardour"/><category term="Hacking"/><category term="LAD"/><category term="LV2"/></entry><entry><title>LV2 Atom and State Serialisation</title><link href="https://drobilla.net/2012/02/23/lv2-atom-and-state-serialisation.html" rel="alternate"/><published>2012-02-23T01:42:00-05:00</published><updated>2012-02-23T01:42:00-05:00</updated><author><name>drobilla</name></author><id>tag:drobilla.net,2012-02-23:/2012/02/23/lv2-atom-and-state-serialisation.html</id><content type="html">&lt;p&gt;I have been working on full round-trip serialisation for everything in
the &lt;a href="http://lv2plug.in/ns/ext/atom"&gt;LV2 Atom&lt;/a&gt; extension (which also
applies for implementing state). I am doing this as a small library with
a simple API, with the goal that it be simple to include in any project.&lt;/p&gt;
&lt;p&gt;Currently this only writes (using
&lt;a href="/software/serd"&gt;Serd&lt;/a&gt;), I still need to move the
reading stuff into it (which will probably use a model and thus require
using &lt;a href="/software/sord"&gt;Sord&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The Atom extension defines a simple data model for use in LV2 plugins
and hosts (or elsewhere). The general Big Idea here is to have a
smallish set of primitive types, a few collections, and out of that one
can build arbitrarily complex structures. Everything (including
containers) is a simple and compact chunk of POD data, but serialises
to/from (a subset of) RDF, so it can nicely be described in a plugin's
Turtle file, among other advantages.&lt;/p&gt;
&lt;p&gt;An easy to adopt serialisation API is important to making these
advantages a reality for many implementations, so I have decided to
provide one before marking these extensions stable. It also serves as a
nice test case with complete coverage. Here is an example of an Atom
that contains every currently defined Atom type, as well as MIDI,
serialised to Turtle by sratom:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;rdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;xsd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;xsd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;three&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.0&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;xsd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;four&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4.0&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;xsd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;urid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;langlit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bonjour&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="n"&gt;fra&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;typelit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;eg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;atom&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nl"&gt;rdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;atom&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Vector&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nl"&gt;rdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;xsd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;xsd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;xsd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;xsd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;atom&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Sequence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nl"&gt;rdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nl"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;frameTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nl"&gt;rdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;901A01&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;midi&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;MidiEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nl"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;frameTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nl"&gt;rdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;902B02&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="n"&gt;midi&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;MidiEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I anticipate/intend for all plugin control to happen via such messages,
since this approach has a few important qualities:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Typically no need to define new binary formats for things (and be
    held back waiting for others to implement them).&lt;/li&gt;
&lt;li&gt;Everything has a portable serialization for free (meaning network
    transparency, saving/loading, and for developers or power users the
    ability to dump any message to see what is going on).&lt;/li&gt;
&lt;li&gt;The convention is to use “objects” (resources, i.e. things with
    properties) as messages, which are inherently extensible. No “oops I
    needed to add a parameter so now compatibility is broken”.&lt;/li&gt;
&lt;li&gt;Easy to bind to other languages or syntaxes, so e.g. Python or
    browser-based UI frameworks should be possible.&lt;/li&gt;
&lt;li&gt;Any RDF vocabulary can be used, meaning millions of well-defined and
    documented predicates (“keys”) are available right now (though it is
    perfectly okay to create one-off objects - compatibility with RDF is
    a benefit, not a burden).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The atom extension includes an API that makes it relatively simple to
build such objects in C, so plugins can write them directly to an output
port or a ring buffer. See the “forge” API in the Atom extension for
details. There are also iterators for all the collections and a “get”
function for objects to make reading data simple.&lt;/p&gt;
&lt;p&gt;Just in case it's not crystal clear, the above is only the &lt;em&gt;external
representation&lt;/em&gt; of the corresponding atom. At run-time, an atom (i.e.
what plugins work with) is just a blob of data with an integer type and
size header. 100% of the API provided for reading and writing atoms is
real-time safe and suitable for use in an audio processing thread.&lt;/p&gt;
&lt;p&gt;For an example, see the &lt;a href="https://gitlab.com/lv2/lv2/-/tree/main/plugins/eg-sampler.lv2"&gt;LV2 sampler
example&lt;/a&gt;, which
has a UI that loads samples via such messages. It currently works in
&lt;a href="/software/jalv"&gt;Jalv&lt;/a&gt;,
&lt;a href="http://ardour.org"&gt;Ardour&lt;/a&gt; support is coming soon. This is the way
forward for more powerful LV2 plugin control, and hopefully will end the
worrying practice of abusing direct instance access to provide such
functionality.&lt;/p&gt;
&lt;p&gt;This work isn't finished yet, but the important parts are done and not
likely to change significantly. I am interested in hearing any developer
feedback, feel free to comment on this post or at the &lt;a href="http://lists.lv2plug.in/listinfo.cgi/devel-lv2plug.in"&gt;LV2 mailing
list&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;[Edited on 2025-02-16 to update broken links]&lt;/p&gt;</content><category term="misc"/><category term="Ardour"/><category term="Hacking"/><category term="LAD"/><category term="LV2"/><category term="Semantic Web"/></entry><entry><title>Ardour: Back On Track. Maybe.</title><link href="https://drobilla.net/2007/06/24/ardour-back-on-track-maybe.html" rel="alternate"/><published>2007-06-24T12:00:00-04:00</published><updated>2007-06-24T12:00:00-04:00</updated><author><name>drobilla</name></author><id>tag:drobilla.net,2007-06-24:/2007/06/24/ardour-back-on-track-maybe.html</id><content type="html">&lt;p&gt;Well, I've been working on Ardour but not directly on my SoC project..
finally got around to fixing that whole mixer-strip-element thing that's
been on the table since last year. Things are more open to extensibility
now (and a unified bus implementation should appear soon, so we'll have
MIDI busses or even MIDI/audio (instrument) busses). Maybe we'll see
things like &lt;a href="http://ardour.org/node/1043"&gt;this&lt;/a&gt; actually happen some
time soonish...&lt;/p&gt;
&lt;p&gt;It would be nice to figure out a really good MIDI meter (something more
clever than just an audio peak meter abused), and a MIDI fader that can
work in various ways, or even instrument plugin support, but it's
probably time to get on the actual piano roll editing part of the
project and leave that stuff until afterwards.&lt;/p&gt;
&lt;p&gt;Kinda ruins my &lt;em&gt;flow&lt;/em&gt; though, you know?&lt;/p&gt;</content><category term="misc"/><category term="Ardour"/><category term="Hacking"/><category term="LAD"/></entry><entry><title>Back to the Hack</title><link href="https://drobilla.net/2007/05/29/back-to-the-hack.html" rel="alternate"/><published>2007-05-29T13:58:00-04:00</published><updated>2007-05-29T13:58:00-04:00</updated><author><name>drobilla</name></author><id>tag:drobilla.net,2007-05-29:/2007/05/29/back-to-the-hack.html</id><content type="html">&lt;p&gt;Well.. finally fully moved; I guess it's time to stop screwing around
and get back into hacking. Specifically Ardour, since I'm being payed to
do so and all.&lt;/p&gt;
&lt;p&gt;Looks like we don't have a fancy new cairo canvas to play with. Maybe it
will be worth my time to do that first, but I'm going to do some
fiddling with displaying MIDI data with gnomecanvas first to get a grasp
on things. Wouldn't hurt to have some visually obvious clue that I am,
in fact, actually doing something. This summer's project should be more
rewarding than last in that sense; most of what I need to do is visual
stuff which tends to be more fun since you have something nice and
tangible at the end of the day.&lt;/p&gt;
&lt;p&gt;Of course, displaying data is one thing. One relatively easy thing.
Actually editing it on the other hand.......... that's where the “fun”
(i.e. hard) part comes in.&lt;/p&gt;
&lt;p&gt;I think a top-down (GUI-&amp;gt;implementation) strategy is best here. The
Grand Battle Plan(TM) goes something like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get MIDI data displayed in regions, notes visible as one canvas item
   (rect) per note&lt;/li&gt;
&lt;li&gt;Attach event signals from note canvas items (move, click, etc) to a
   set of stub methods that encompass all the editing operations&lt;/li&gt;
&lt;li&gt;Now there's a nice centralized area where all the editing operations
   need to be implemented&lt;/li&gt;
&lt;li&gt;Figure out how the hell to implement them (ie ???????????)&lt;/li&gt;
&lt;li&gt;Implement them (ie Profit!)&lt;/li&gt;
&lt;/ul&gt;</content><category term="misc"/><category term="Ardour"/><category term="Hacking"/></entry></feed>