- Fix crash in x11_in_gtk2 when event_filter fires before widget is realized
- Use libgtk-x11-2.0.so.0 (with .0 suffix) by default which is available on systems without the dev package
- Update to waf 1.7.8 and autowaf r90 (install docs to versioned directory)
Ingen as remote server or LV2 plugin
I have been working on the control protocol aspect of Ingen, towards a few goals:
- Working GUI communicating with the server via a socket
- Decent Python bindings for socket interface
- Ingen as an LV2 plugin
The Python bindings got fleshed out to support a script for loading AMS 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.
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.
The Ingen protocol uses the LV2 Patch 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 atoms. 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.
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 Ardour 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.
Writing an LV2 Book
It has been clear for a while that some kind of higher level documentation is needed for LV2. The reference documentation is much better than it used to be, but this isn't very good at giving an overview, and is very imposing to new developers since LV2 is a bit different than, say, a library API due to the code/data split.
Overview documentation can't really go in the extension documentation, since many tasks plugin developers want to achieve involve several extensions (or no extensions at all). I have been wondering for a while what form this documentation should take: FAQ? Wiki pages? Just examples that illustrate specific things? For whatever reason I had never thought of a book format, but now I think that is the best approach. Too many LV2 ideas live in my head alone, especially the umbrella ideas, which is not good. A book seems like the best way to convey an overall understanding of LV2. This is important - LV2 is what I call a "click" technology (like LISP or RDF), it seems insane until it "clicks" and you get it. You really need that little enlightenment experience to be able to work with it well (and especially to be able to work on it). I need to convey that to more people. Of course it would also serve as a simple "How To" manual for plugin developers, which is the primary goal.
By "book" I don't necessarily mean paper based. While that might be nice a web version definitely should exist. I mean a largish document with several chapters and sections, with a clear overall arc that starts with the most basic plugin possible, and each section is about a specific type of functionality, like "receiving MIDI events" or "transport synchronization". That way, when a developer has a broad question like "how do I implement state, and dynamically control it?" there is a nice book chapter on exactly that topic with explanatory text.
The other thing that is definitely good is examples. We still have only a few official examples in the LV2 tree, more would be nice. Making this book very example centric would be a good idea, solving several problems at once. Perhaps a Literate Programming like approach, where each chapter is really just the comments of a working plugin that demonstrates the relevant functionality. This way, even people who won't read the documentation (i.e. most) still have working examples to build from, and these examples would also serve as nice test cases for hosts.
The early sections could also serve as a more proper specification for things like discovery, module loading, and so on, which thus far we haven't documented so well, but honestly I don't see this as a very high priority. It's a nice idea to have an authoritative LV2 document, but in practice hosts should just use a library (like Lilv) for that stuff anyway, and most do.
In terms of publishing tech, I am not sure. I would like the examples to be actual C source code without duplicating everything, hence the Literate Programming idea. Literate Programming in philosophy only, not actually using a weird format like CWEB. I'd just parse out the comments and render those as text, and pretty-print the code in-between. This is simple, and with Pygments it can easily output both HTML and LaTeX for both an online and a typeset version. This way, for "just show me the code" types, the example source is just normal C code, but heavily documented with explanatory prose. As it happens I banged out a little Python script to do just that this evening. The tricky part is things like links, references, and so on, that require special syntax. I'd really rather not have to invent and implement a new comment syntax. However, perhaps something so directly tied to code can just avoid the need for any of that anyway, and the master document can just include all the generated bits. Might have to manually make a separate HTML and LaTeX master document but that's not too bad. This would all be trivial if I only use LaTeX, but since this is documentation, being able to link to a chapter online and such is important. Anyway, this is beside the point, the important thing is the general idea of writing an LV2 book.
I think this is a really good idea, and though I don't exactly have all the time in the world to start a book-level project, I might start building it in the LV2 repository so it is part of the official distribution. As the spec grows, the book can grow along with it. I envision future LV2 releases adding specific functionality (like transport sync, which will be the upcoming one), along with a new book chapter on the topic. On a personal note, this meshes well with desire to stick to non-realtime communication (e.g. email), since I can't have the constant distraction of IRC in my life any more. I've spewed enough text on to the Internet to fill volumes, might as well put that into something of lasting value.
To me it seems clear that this is the best way to better document LV2 and make it more accessible to newbies, but I'm notoriously bad at predicting what others want, so any feedback would be appreciated. If I wrote an LV2 book, would you read it, or at least use it as a reference?
Is it worth my time to do this, or should I just stick to hacking when I have time to do LAD stuff? If there's a good chance that this will increase the Bus Factor of LV2, I think it's probably worth it.
LV2 plugin transport synchronisation
I have been working on getting accurate transport information provided to LV2 plugins. Until now, there was the ability to specially designate e.g. BPM control ports, but this has limitations, the most obvious being that it is is limited to conveying simple numeric values at the start of a cycle.
In general, things are headed in an event-based direction, and this is no exception. The LV2 Time extension defines all the properties needed to describe a transport position/speed/tempo/meter and the LV2 Atom extension defines a dictionary type that can be used to send several properties at once in a single event. The host sends updates whenever the transport has changed in a way the plugin can not anticipate (anything but rolling along at the same speed/tempo/meter). Since events are time stamped, this makes it possible to give plugins a sample accurate tempo map, even when there are changes in the middle of a cycle.
There is a new example plugin in the LV2 repository, eg-metro, which is a simple metronome that follows this scheme. If the host implements the above, the metronome will click in sync with the host transport.
I have implemented this in Jalv (which uses Jack transport), Ardour 3, and Ingen (via a new internal "Time" block). Ardour will send an update at the start of the cycle if a relocate has happened, and one on the exact sample of any meter or tempo change within the cycle. Due to the limitations of Jack transport, Jalv and Ingen will only send updates at the start of a cycle. The metronome should tick correctly when loaded in Jalv or Ingen when there is a Jack transport master active (I have tested with Ardour), and when loaded directly in Ardour.
This functionality is pretty important for many musical plugins, so hopefully other host authors implement it as well. Depending on feedback (and available time) I may document the above rules as a feature and add it to the time extension, and release LV2 1.2.2. I think a well-defined way to achieve this is worthy of a point release, and it will get the news out there to implementers.
- Fix embedding Gtk in Qt as a child widget (support reparenting)
- Support for wrapping native Windows UIs in Gtk2
- Gracefully handle UIs with no port_event method
- Replace host provided features that match Suil implemented features, rather than passing UIs duplicate features
- Disable timestamps in HTML documentation for reproducible build
fomp 1.0.0 has been released. This is an LV2 port of the MCP, VCO, FIL, and WAH plugins by Fons Adriaensen.
jalv 1.2.0 has been released. Jalv is a simple but fully featured LV2 host for Jack which exposes plugin ports to Jack, essentially making any LV2 plugin function as a Jack application. For more information, see http://drobilla.net/software/jalv.
- Tune UI update rate and ring size based on JACK rate and MIDI buffer size to handle the handle the maximum message rate the plugin can send.
- Support lv2:sampleRate control ports.
- Tolerate loading presets with port values that aren't xsd:decimal
- Notify plugins of Jack transport changes by sending events (an atom:Blank with properties from the LV2 time extension)
- Refuse to instantiate plugins which require unsupported features
- Support LV2 buf-size extension (with all features)
- Add Gtk3 UI
- Port to MinGW
- Fix Jack Session support
- Implement better data type validation in sord_validate conformant with the XSD and OWL specifications
- Fix memory leaks in sord_validate
- Install sord_validate man page
- Disable timestamps in HTML documentation for reproducible build
How to define a datatype in RDF
I had to do some digging around to figure out how to define a new Datatype with restrictions in RDF, so I thought it might make a useful post to save someone else the trouble in the future.
RDF datatypes are based on XSD
datatypes, which are often used
directly. Unfortunately, most implementations simply have the XSD types
baked in and do not support or validate new datatype descriptions
(though at least
can). Regardless, it is sometimes necessary to define a datatype with a
specific restriction so it can be machine validated. It's a bit tricky
to figure out how to do this, since everything is buried in
specifications that aren't as triple oriented as they should be. So,
here is an example of defining a datatype restricted by regular
expression in Turtle, derived from the OWL documentation:
<http://example.org/CSymbol> a rdfs:Datatype ; rdfs:comment "A symbol in the C programming language" ; owl:onDatatype xsd:string ; owl:withRestrictions ( [ xsd:pattern "[_a-zA-Z][_a-zA-Z0-9]*" ] ) .
The XSD specification defines several “constraining facets” you can use in this way. See the XSD specification for details, but the most obvious and useful for RDF are: xsd:length, xsd:minLength, xsd:maxLength, xsd:pattern, xsd:maxInclusive, xsd:maxExclusive, xsd:minInclusive, xsd:minExclusive. For example, you can define a numeric type with restricted range like so:
<http://example.org/AnswerishInteger> a rdfs:Datatype ; rdfs:comment "An integer between 24 and 42 inclusive" ; owl:onDatatype xsd:integer ; owl:withRestrictions ( [ xsd:minInclusive 24 ] [ xsd:maxInclusive 42 ] ) .
Defining datatypes in this way and using them as the rdfs:range for properties is a good idea because it describes which values are valid in a machine readable way. This makes it possible for simple generic tools to validate data, ensuring that all literals are valid values for the property they describe.
- Deprecate old flawed Lilv::Instance constructors
- Fix documentation for ui_type parameter of lilv_ui_is_supported()
- Fix crash when lv2info is run with an invalid URI argument
- Gracefully handle failure to save plugin state and print error message
- Reduce memory usage (per node)
- Simpler node implementation always backed by a SordNode
- Make all 'zix' symbols private to avoid symbol clashes in static builds
- Add lv2bench utility
- Fix various hyper-strict warnings
- Do not require a C++ compiler to build
- Add option to build utilities as static binaries
- Upgrade to waf 1.7.2
- lilvmm.hpp: Make Lilv::Instance handle features and failed instantiations
- lilvmm.hpp: Add Lilv::Instance::get_handle()
- lilvmm.hpp: Add Lilv::Instance::get_extension_data()