diff --git a/generate-lv2-html-docs.sh b/generate-lv2-html-docs.sh
index 57c5365..8a01a89 100755
--- a/generate-lv2-html-docs.sh
+++ b/generate-lv2-html-docs.sh
@@ -21,5 +21,9 @@ if [ ! -f documentation/style.css ]; then
fi
cp kx-external-ui.lv2/* documentation/extui/
+cp kx-programs.lv2/* documentation/progs/
+cp kx-rtmempool.lv2/* documentation/rtmpl/
lv2specgen.py $(pwd)/kx-external-ui.lv2/manifest.ttl /usr/share/lv2specgen/ ../style.css $(pwd)/documentation/extui/index.html $(pwd)/documentation/extui "" -i -p extui
+lv2specgen.py $(pwd)/kx-programs.lv2/manifest.ttl /usr/share/lv2specgen/ ../style.css $(pwd)/documentation/progs/index.html $(pwd)/documentation/progs "" -i -p progs
+lv2specgen.py $(pwd)/kx-rtmempool.lv2/manifest.ttl /usr/share/lv2specgen/ ../style.css $(pwd)/documentation/rtmpl/index.html $(pwd)/documentation/rtmpl "" -i -p rtmpl
diff --git a/kx-external-ui.lv2/external-ui.ttl b/kx-external-ui.lv2/external-ui.ttl
index ecaf93f..0658435 100644
--- a/kx-external-ui.lv2/external-ui.ttl
+++ b/kx-external-ui.lv2/external-ui.ttl
@@ -38,7 +38,7 @@
- List of hosts that use this extension:
+ List of hosts that support this extension:
- Ardour
diff --git a/kx-programs.lv2/manifest.ttl b/kx-programs.lv2/manifest.ttl
new file mode 100644
index 0000000..b9ff520
--- /dev/null
+++ b/kx-programs.lv2/manifest.ttl
@@ -0,0 +1,8 @@
+@prefix lv2: .
+@prefix rdfs: .
+
+
+ a lv2:Specification ;
+ lv2:minorVersion 1 ;
+ lv2:microVersion 0 ;
+ rdfs:seeAlso .
diff --git a/kx-programs.lv2/programs.doap.ttl b/kx-programs.lv2/programs.doap.ttl
new file mode 100644
index 0000000..b4b72b3
--- /dev/null
+++ b/kx-programs.lv2/programs.doap.ttl
@@ -0,0 +1,25 @@
+@prefix dcs: .
+@prefix doap: .
+@prefix foaf: .
+@prefix rdfs: .
+
+
+ a doap:Project ;
+ rdfs:seeAlso <../kx-meta/meta.ttl> ;
+ doap:license ;
+ doap:name "Programs" ;
+ doap:homepage ;
+ doap:created "2015-07-03" ;
+ doap:shortdesc "LV2 extension for implementing plugin-side programs." ;
+ doap:developer ;
+ doap:maintainer ;
+ doap:release [
+ doap:revision "1.0" ;
+ doap:created "2015-07-03" ;
+ doap:file-release ;
+ dcs:changeset [
+ dcs:item [
+ rdfs:label "First stable release."
+ ]
+ ]
+ ] .
diff --git a/kx-programs.lv2/programs.h b/kx-programs.lv2/programs.h
new file mode 100644
index 0000000..0e2997d
--- /dev/null
+++ b/kx-programs.lv2/programs.h
@@ -0,0 +1,174 @@
+/*
+ LV2 Programs Extension
+ Copyright 2012 Filipe Coelho
+
+ 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.
+*/
+
+/**
+ @file lv2_programs.h
+ C header for the LV2 programs extension .
+*/
+
+#ifndef LV2_PROGRAMS_H
+#define LV2_PROGRAMS_H
+
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
+
+#define LV2_PROGRAMS_URI "http://kxstudio.sf.net/ns/lv2ext/programs"
+#define LV2_PROGRAMS_PREFIX LV2_PROGRAMS_URI "#"
+
+#define LV2_PROGRAMS__Host LV2_PROGRAMS_PREFIX "Host"
+#define LV2_PROGRAMS__Interface LV2_PROGRAMS_PREFIX "Interface"
+#define LV2_PROGRAMS__UIInterface LV2_PROGRAMS_PREFIX "UIInterface"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* LV2_Programs_Handle;
+
+typedef struct _LV2_Program_Descriptor {
+
+ /** Bank number for this program. Note that this extension does not
+ support MIDI-style separation of bank LSB and MSB values. There is
+ no restriction on the set of available banks: the numbers do not
+ need to be contiguous, there does not need to be a bank 0, etc. */
+ uint32_t bank;
+
+ /** Program number (unique within its bank) for this program. There is
+ no restriction on the set of available programs: the numbers do not
+ need to be contiguous, there does not need to be a program 0, etc. */
+ uint32_t program;
+
+ /** Name of the program. */
+ const char * name;
+
+} LV2_Program_Descriptor;
+
+/**
+ Programs extension, plugin data.
+
+ When the plugin's extension_data is called with argument LV2_PROGRAMS__Interface,
+ the plugin MUST return an LV2_Programs_Instance structure, which remains valid
+ for the lifetime of the plugin.
+*/
+typedef struct _LV2_Programs_Interface {
+ /**
+ * get_program()
+ *
+ * This member is a function pointer that provides a description
+ * of a program (named preset sound) available on this plugin.
+ *
+ * The index argument is an index into the plugin's list of
+ * programs, not a program number as represented by the Program
+ * field of the LV2_Program_Descriptor. (This distinction is
+ * needed to support plugins that use non-contiguous program or
+ * bank numbers.)
+ *
+ * This function returns a LV2_Program_Descriptor pointer that is
+ * guaranteed to be valid only until the next call to get_program
+ * or deactivate, on the same plugin instance. This function must
+ * return NULL if passed an index argument out of range, so that
+ * the host can use it to query the number of programs as well as
+ * their properties.
+ */
+ const LV2_Program_Descriptor *(*get_program)(LV2_Handle handle,
+ uint32_t index);
+
+ /**
+ * select_program()
+ *
+ * This member is a function pointer that selects a new program
+ * for this plugin. The program change should take effect
+ * immediately at the start of the next run() call. (This
+ * means that a host providing the capability of changing programs
+ * between any two notes on a track must vary the block size so as
+ * to place the program change at the right place. A host that
+ * wanted to avoid this would probably just instantiate a plugin
+ * for each program.)
+ *
+ * Plugins should ignore a select_program() call with an invalid
+ * bank or program.
+ *
+ * A plugin is not required to select any particular default
+ * program on activate(): it's the host's duty to set a program
+ * explicitly.
+ *
+ * A plugin is permitted to re-write the values of its input
+ * control ports when select_program is called. The host should
+ * re-read the input control port values and update its own
+ * records appropriately. (This is the only circumstance in which
+ * a LV2 plugin is allowed to modify its own control-input ports.)
+ */
+ void (*select_program)(LV2_Handle handle,
+ uint32_t bank,
+ uint32_t program);
+
+} LV2_Programs_Interface;
+
+/**
+ Programs extension, UI data.
+
+ When the UI's extension_data is called with argument LV2_PROGRAMS__UIInterface,
+ the UI MUST return an LV2_Programs_UI_Interface structure, which remains valid
+ for the lifetime of the UI.
+*/
+typedef struct _LV2_Programs_UI_Interface {
+ /**
+ * select_program()
+ *
+ * This is exactly the same as select_program in LV2_Programs_Instance,
+ * but this struct relates to the UI instead of the plugin.
+ *
+ * When called, UIs should update their state to match the selected program.
+ */
+ void (*select_program)(LV2UI_Handle handle,
+ uint32_t bank,
+ uint32_t program);
+
+} LV2_Programs_UI_Interface;
+
+/**
+ Feature data for LV2_PROGRAMS__Host.
+*/
+typedef struct _LV2_Programs_Host {
+ /**
+ * Opaque host data.
+ */
+ LV2_Programs_Handle handle;
+
+ /**
+ * program_changed()
+ *
+ * Tell the host to reload a plugin's program.
+ * Parameter handle MUST be the 'handle' member of this struct.
+ * Parameter index is program index to change.
+ * When index is -1, host should reload all the programs.
+ *
+ * The plugin MUST NEVER call this function on a RT context or during run().
+ *
+ * NOTE: This call is to inform the host about a program's bank, program or name change.
+ * It DOES NOT change the current selected program.
+ */
+ void (*program_changed)(LV2_Programs_Handle handle,
+ int32_t index);
+
+} LV2_Programs_Host;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LV2_PROGRAMS_H */
diff --git a/kx-programs.lv2/programs.ttl b/kx-programs.lv2/programs.ttl
new file mode 100644
index 0000000..75f094a
--- /dev/null
+++ b/kx-programs.lv2/programs.ttl
@@ -0,0 +1,62 @@
+@prefix lv2: .
+@prefix owl: .
+@prefix progs: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix ui: .
+@prefix xsd: .
+
+
+ a owl:Ontology ;
+ rdfs:seeAlso ,
+ ,
+ <../kx-meta/meta.ttl> ;
+ lv2:documentation """
+
+ LV2 Programs is an LV2 Extension that allows a host to access plugin-side midi-mapped programs.
+ It is not the same as LV2 Presets,
+ which defines host-side presets where the plugin has no control or role whatsoever.
+
+
+
+ List of plugins that use this extension:
+
+
+
+
+ List of hosts that support this extension:
+
+
+""" .
+
+progs:Host
+ a lv2:Feature ;
+ lv2:documentation """
+
+TODO
+
+""" .
+
+progs:Interface
+ a lv2:ExtensionData ;
+ rdfs:label "Programs Plugin Interface" ;
+ lv2:documentation """
+
+TODO
+
+""" .
+
+progs:UIInterface
+ a lv2:ExtensionData ;
+ rdfs:label "Programs UI Interface" ;
+ lv2:documentation """
+
+TODO
+
+""" .
diff --git a/kx-rtmempool.lv2/manifest.ttl b/kx-rtmempool.lv2/manifest.ttl
new file mode 100644
index 0000000..c9d5cf0
--- /dev/null
+++ b/kx-rtmempool.lv2/manifest.ttl
@@ -0,0 +1,8 @@
+@prefix lv2: .
+@prefix rdfs: .
+
+
+ a lv2:Specification ;
+ lv2:minorVersion 1 ;
+ lv2:microVersion 0 ;
+ rdfs:seeAlso .
diff --git a/kx-rtmempool.lv2/rtmempool.doap.ttl b/kx-rtmempool.lv2/rtmempool.doap.ttl
new file mode 100644
index 0000000..bc8ea42
--- /dev/null
+++ b/kx-rtmempool.lv2/rtmempool.doap.ttl
@@ -0,0 +1,25 @@
+@prefix dcs: .
+@prefix doap: .
+@prefix foaf: .
+@prefix rdfs: .
+
+
+ a doap:Project ;
+ rdfs:seeAlso <../kx-meta/meta.ttl> ;
+ doap:license ;
+ doap:name "External UI" ;
+ doap:homepage ;
+ doap:created "2015-07-03" ;
+ doap:shortdesc "LV2 extension that provides a realtime safe memory pool for plugins." ;
+ doap:developer ;
+ doap:maintainer ;
+ doap:release [
+ doap:revision "1.0" ;
+ doap:created "2015-07-03" ;
+ doap:file-release ;
+ dcs:changeset [
+ dcs:item [
+ rdfs:label "First stable release."
+ ]
+ ]
+ ] .
diff --git a/kx-rtmempool.lv2/rtmempool.h b/kx-rtmempool.lv2/rtmempool.h
new file mode 100644
index 0000000..5a06644
--- /dev/null
+++ b/kx-rtmempool.lv2/rtmempool.h
@@ -0,0 +1,105 @@
+/*
+ LV2 realtime safe memory pool extension definition
+ This work is in public domain.
+
+ This file 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.
+
+ If you have questions, contact Filipe Coelho (aka falkTX)
+ or ask in #lad channel, FreeNode IRC network.
+*/
+
+/**
+ * @file lv2_rtmempool.h
+ * C header for the LV2 rtmempool extension .
+ *
+ */
+
+#ifndef LV2_RTMEMPOOL_H
+#define LV2_RTMEMPOOL_H
+
+#define LV2_RTSAFE_MEMORY_POOL_URI "http://kxstudio.sf.net/ns/lv2ext/rtmempool"
+#define LV2_RTSAFE_MEMORY_POOL_PREFIX LV2_RTSAFE_MEMORY_POOL_URI "#"
+
+#define LV2_RTSAFE_MEMORY_POOL__Pool LV2_RTSAFE_MEMORY_POOL_URI "Pool"
+
+/** max size of memory pool name, in chars, including terminating zero char */
+#define LV2_RTSAFE_MEMORY_POOL_NAME_MAX 128
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#include
+#endif
+
+/**
+ * Opaque data to host data for LV2_RtMemPool_Pool.
+ */
+typedef void* LV2_RtMemPool_Handle;
+
+/**
+ * On instantiation, host must supply LV2_RTSAFE_MEMORY_POOL__Pool feature.
+ * LV2_Feature::data must be pointer to LV2_RtMemPool_Pool.
+ */
+typedef struct _LV2_RtMemPool_Pool {
+ /**
+ * This function is called when plugin wants to create memory pool
+ *
+ * may/will sleep
+ *
+ * @param pool_name pool name, for debug purposes, max RTSAFE_MEMORY_POOL_NAME_MAX chars, including terminating zero char. May be NULL.
+ * @param data_size memory chunk size
+ * @param min_preallocated min chunks preallocated
+ * @param max_preallocated max chunks preallocated
+ *
+ * @return Success status, true if successful
+ */
+ bool (*create)(LV2_RtMemPool_Handle * handle_ptr,
+ const char * pool_name,
+ size_t data_size,
+ size_t min_preallocated,
+ size_t max_preallocated);
+
+ /**
+ * This function is called when plugin wants to destroy previously created memory pool
+ *
+ * may/will sleep
+ */
+ void (*destroy)(LV2_RtMemPool_Handle handle);
+
+ /**
+ * This function is called when plugin wants to allocate memory in context where sleeping is not allowed
+ *
+ * will not sleep
+ *
+ * @return Pointer to allocated memory or NULL if memory no memory is available
+ */
+ void * (*allocate_atomic)(LV2_RtMemPool_Handle handle);
+
+ /**
+ * This function is called when plugin wants to allocate memory in context where sleeping is allowed
+ *
+ * may/will sleep
+ *
+ * @return Pointer to allocated memory or NULL if memory no memory is available (should not happen under normal conditions)
+ */
+ void * (*allocate_sleepy)(LV2_RtMemPool_Handle handle);
+
+ /**
+ * This function is called when plugin wants to deallocate previously allocated memory
+ *
+ * will not sleep
+ *
+ * @param memory_ptr pointer to previously allocated memory chunk
+ */
+ void (*deallocate)(LV2_RtMemPool_Handle handle,
+ void * memory_ptr);
+
+} LV2_RtMemPool_Pool;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LV2_RTMEMPOOL_H */
diff --git a/kx-rtmempool.lv2/rtmempool.ttl b/kx-rtmempool.lv2/rtmempool.ttl
new file mode 100644
index 0000000..ccc1ed1
--- /dev/null
+++ b/kx-rtmempool.lv2/rtmempool.ttl
@@ -0,0 +1,33 @@
+@prefix lv2: .
+@prefix owl: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix rtmpl: .
+@prefix ui: .
+@prefix xsd: .
+
+
+ a owl:Ontology ;
+ rdfs:seeAlso ,
+ ,
+ <../kx-meta/meta.ttl> ;
+ lv2:documentation """
+
+ LV2 realtime safe memory pool extension definition.
+
+
+
+ List of hosts that support this extension:
+
+
+""" .
+
+rtmpl:Pool
+ a lv2:Feature ;
+ lv2:documentation """
+
+TODO
+
+""" .