diff options
author | David Robillard <d@drobilla.net> | 2007-09-22 16:54:26 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-09-22 16:54:26 +0000 |
commit | 106b0784b8c8347bbbebcedc421030effdc26fd0 (patch) | |
tree | 55dbdd438de387b630a78e837ed23db12e9920cb | |
parent | d8fb10e4246b6804e2283e4f83d2bfdccad8ad58 (diff) | |
download | lilv-106b0784b8c8347bbbebcedc421030effdc26fd0.tar.gz lilv-106b0784b8c8347bbbebcedc421030effdc26fd0.tar.bz2 lilv-106b0784b8c8347bbbebcedc421030effdc26fd0.zip |
Updates LV2 and LV2 UI specs.
git-svn-id: http://svn.drobilla.net/lad/slv2@762 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | slv2/Makefile.am | 2 | ||||
-rw-r--r-- | slv2/lv2-gtk2gui.h | 212 | ||||
-rw-r--r-- | slv2/lv2.h | 76 | ||||
-rw-r--r-- | slv2/lv2_gui.h | 346 | ||||
-rw-r--r-- | slv2/pluginguiinstance.h | 19 | ||||
-rw-r--r-- | src/pluginguiinstance.c | 26 | ||||
-rw-r--r-- | src/slv2_internal.h | 4 |
7 files changed, 413 insertions, 272 deletions
diff --git a/slv2/Makefile.am b/slv2/Makefile.am index f090e22..8deb4db 100644 --- a/slv2/Makefile.am +++ b/slv2/Makefile.am @@ -3,7 +3,7 @@ slv2includedir = $(includedir)/slv2 slv2include_HEADERS = \ gui.h \ lv2.h \ - lv2-gtk2gui.h \ + lv2_gui.h \ plugin.h \ pluginclass.h \ pluginclasses.h \ diff --git a/slv2/lv2-gtk2gui.h b/slv2/lv2-gtk2gui.h deleted file mode 100644 index ae05c16..0000000 --- a/slv2/lv2-gtk2gui.h +++ /dev/null @@ -1,212 +0,0 @@ -/************************************************************************ - * - * GTK2 in-process UI extension for LV2 - * - * Copyright (C) 2006 Lars Luthman <lars.luthman@gmail.com> - * - * Based on lv2.h, which is - * - * Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, Stefan - * Westerfeld - * Copyright (C) 2006 Steve Harris, Dave Robillard. - * - * This header is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This header 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 - * USA. - * - ***********************************************************************/ - -/** @file - This extension defines an interface that can be used in LV2 plugins and - hosts to create GTK2 GUIs for plugins. The GUIs will be plugins that - will reside in shared object files in a LV2 bundle and be referenced in - the RDF file using the triples -<pre> - <http://my.plugin> <http://ll-plugins.nongnu.org/lv2/ext/gtk2gui#gui> <http://my.plugingui> - <http://my.plugingui> <http://ll-plugins.nongnu.org/lv2/ext/gtk2gui#binary> <mygui.so> -</pre> - where <http://my.plugin> is the URI of the plugin, <http://my.plugingui> is - the URI of the plugin GUI and <mygui.so> is the relative URI to the shared - object file. While it is possible to have the plugin GUI and the plugin in - the same shared object file it is probably a good idea to keep them - separate so that hosts that don't want GUIs don't have to load the GUI code. - - It's entirely possible to have multiple GUIs for the same plugin, or to have - the GUI for a plugin in a different bundle from the actual plugin - this - way people other than the plugin author can write plugin GUIs independently - without editing the original plugin bundle. If a GUI is in a separate bundle - the first triple above should be in that bundle's manifest.ttl file so that - hosts can find the GUI when scanning the manifests. - - Note that the process that loads the shared object file containing the GUI - code and the process that loads the shared object file containing the - actual plugin implementation does not have to be the same. There are many - valid reasons for having the plugin and the GUI in different processes, or - even on different machines. This means that you can _not_ use singletons - and global variables and expect them to refer to the same objects in the - GUI and the actual plugin. The function callback interface defined in this - header is all you can expect to work. - - Since the LV2 specification itself allows for extensions that may add - new types of data and configuration parameters that plugin authors may - want to control with a GUI, this extension allows for meta-extensions that - can extend the interface between the GUI and the host. See the - instantiate() and extension_data() callback pointers for more details. - - Note that this extension is NOT a Host Feature. There is no way for a plugin - to know whether the host that loads it supports GUIs or not, and the plugin - must ALWAYS work without the GUI (although it may be rather useless unless - it has been configured using the GUI in a previous session). - - GUIs written to this specification do not need to be threadsafe - the - functions defined below may only be called in the same thread as the GTK - main loop is running in. -*/ - -#ifndef LV2_GTK2GUI_H -#define LV2_GTK2GUI_H - -#include "lv2.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -/* The original header includes <gtk/gtkwidget.h>, but we don't want - libslv2 to depend on GTK+ so we forward declare the _GtkWidget struct - instead. */ -struct _GtkWidget; - - - -/** This handle indicates a particular instance of a GUI. - It is valid to compare this to NULL (0 for C++) but otherwise the - host MUST not attempt to interpret it. The GUI plugin may use it to - reference internal instance data. */ -typedef void* LV2UI_Handle; - - -/** This handle indicates a particular plugin instance, provided by the host. - It is valid to compare this to NULL (0 for C++) but otherwise the - GUI plugin MUST not attempt to interpret it. The host may use it to - reference internal instance data. */ -typedef void* LV2UI_Controller; - - -/** This is the type of the host-provided function that changes the value - of a control rate float input port in a plugin instance. A function - pointer of this type will be provided to the GUI by the host in the - instantiate() function. */ -typedef void (*LV2UI_Set_Control_Function)(LV2UI_Controller controller, - uint32_t port, - float value); - - -typedef struct _LV2UI_Descriptor { - - /** The URI for this GUI (not for the plugin it controls). */ - const char* URI; - - /** Create a new GUI object and return a handle to it. This function works - similarly to the instantiate() member in LV2_Descriptor, with the - additions that the URI for the plugin that this GUI is for is passed - as a parameter, a function pointer and a controller handle are passed to - allow the plugin to change control port values in the plugin - (control_function and controller) and a pointer to a GtkWidget pointer - is passed, which the GUI plugin should set to point to a newly created - widget which will be the main GUI for the plugin. - - The features array works like the one in the instantiate() member - in LV2_Descriptor, except that the URIs should be denoted with the triples - <pre> - <http://my.plugingui> <http://ll-plugins.nongnu.org/lv2/dev/gtk2gui#optionalFeature> <http://my.guifeature> - </pre> - or - <pre> - <http://my.plugingui> <http://ll-plugins.nongnu.org/lv2/dev/gtk2gui#requiredFeature> <http://my.guifeature> - </pre> - in the RDF file, instead of the lv2:optionalFeature or lv2:requiredFeature - that is used by host features. These features are associated with the GUI, - not with the plugin - they are not actually LV2 Host Features, they just - use the same data structure. - - The same rules apply for these features as for normal host features - - if a feature is listed as required in the RDF file and the host does not - support it, it must not load the GUI. - */ - LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor, - const char* plugin_uri, - const char* bundle_path, - LV2UI_Set_Control_Function control_function, - LV2UI_Controller controller, - struct _GtkWidget** widget, - const LV2_Host_Feature** features); - - - /** Destroy the GUI object and the associated widget. - */ - void (*cleanup)(LV2UI_Handle gui); - - /** Tell the GUI that a control port value has changed. This member may be - set to NULL if the GUI is not interested in control port changes. - */ - void (*set_control)(LV2UI_Handle gui, - uint32_t port, - float value); - - /** Returns a data structure associated with an extension URI, for example - a struct containing additional function pointers. Avoid returning - function pointers directly since standard C++ has no valid way of - casting a void* to a function pointer. This member may be set to NULL - if the GUI is not interested in supporting any extensions. This is similar - to the extension_data() member in LV2_Descriptor. - */ - void* (*extension_data)(LV2UI_Handle gui, - const char* uri); - -} LV2UI_Descriptor; - - - -/** Accessing a plugin GUI. - - A plugin programmer must include a function called "lv2ui_descriptor" - with the following function prototype within the shared object - file. This function will have C-style linkage (if you are using - C++ this is taken care of by the 'extern "C"' clause at the top of - the file). This function will be accessed by the GUI host using the - @c dlsym() function and called to get a LV2UI_UIDescriptor for the - wanted plugin. - - Just like lv2_descriptor(), this function takes an index parameter. The - index should only be used for enumeration and not as any sort of ID number - - the host should just iterate from 0 and upwards until the function returns - NULL, or a descriptor with an URI matching the one the host is looking for - is returned. -*/ -const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index); - - -/** This is the type of the lv2ui_descriptor() function. */ -typedef const LV2UI_Descriptor* (*LV2UI_DescriptorFunction)(uint32_t index); - - - -#ifdef __cplusplus -} -#endif - - -#endif @@ -2,7 +2,7 @@ * *** PROVISIONAL *** * * Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, - * Stefan Westerfeld + * Stefan Westerfeld. * Copyright (C) 2006-2007 Steve Harris, Dave Robillard. * * This header is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ extern "C" { /** @file lv2.h * - * Revision: 1.0beta4 + * Revision: 1.0beta5 * * == Overview == * @@ -54,18 +54,19 @@ extern "C" { * possible - the data file is mandatory. * * Plugins are expected to distinguish between control rate and audio - * rate data. Plugins have 'ports' that are inputs or outputs for audio - * or control data and each plugin is 'run' for a 'block' corresponding - * to a short time interval measured in samples. Audio rate data is - * communicated using arrays with one element per sample processed, + * rate data (or other types of data defined by extensions). Plugins have + * 'ports' that are inputs or outputs and each plugin is 'run' for a 'block' + * corresponding to a short time interval measured in samples. Audio rate + * data is communicated using arrays with one element per sample processed, * allowing a block of audio to be processed by the plugin in a single * pass. Control rate data is communicated using single values. Control * rate data has a single value at the start of a call to the 'run()' * function, and may be considered to remain this value for its duration. - * Thus the 'control rate' is determined by the block size, controlled - * by the host. The plugin may assume that all its input and output - * ports have been connected to the relevant data location (see the - * 'connect_port()' function below) before it is asked to run. + * Thus the 'control rate' is determined by the block size, controlled by + * the host. The plugin may assume that all its input and output ports have + * been connected to the relevant data location (see the 'connect_port()' + * function below) before it is asked to run, unless the port has been set + * 'connection optional' in the plugin's data file. * * Plugins will reside in shared object files suitable for dynamic linking * by dlopen() and family. The file will provide a number of 'plugin @@ -84,14 +85,16 @@ extern "C" { * To facilitate this, the functions provided by a plugin are divided into * classes: * - * - Audio class: run(), connect_port() - * - Instantiation class: instantiate(), cleanup(), - * activate(), deactivate() + * - Discovery class: lv2_descriptor(), extension_data() + * - Instantiation class: instantiate(), cleanup(), activate(), deactivate() + * - Audio class: run(), connect_port() * * Extensions to this specification which add new functions MUST declare in * which of these classes the functions belong, or define new classes for them. * The rules that hosts must follow are these: * + * - When a function from the Discovery class is running, no other + * functions in the same shared object file may run. * - When a function from the Instantiation class is running for a plugin * instance, no other functions for that instance may run. * - When a function is running for a plugin instance, no other @@ -100,9 +103,6 @@ extern "C" { * Any simultaneous calls that are not explicitly forbidden by these rules * are allowed. For example, a host may call run() for two different plugin * instances simultaneously. - * - * The extension_data() function and the lv2_descriptor() function are never - * associated with any plugin instances and may be called at any time. */ @@ -127,14 +127,12 @@ typedef void * LV2_Handle; * feature the host has which the plugin may depend on. This is to allow * extensions to the LV2 specification without causing any breakage. The base * LV2 specification does not define any host features; hosts are not required - * to use this facility. - */ + * to use this facility. */ typedef struct _LV2_Host_Feature { /** A globally unique, case-sensitive identifier for this feature. * * This MUST be defined in the specification of any LV2 extension which - * defines a host feature. - */ + * defines a host feature. */ const char * URI; /** Pointer to arbitrary data. @@ -144,8 +142,7 @@ typedef struct _LV2_Host_Feature { * specification makes no restrictions on the contents of this data. * The data here MUST be cleary defined by the LV2 extension which defines * this feature. - * If no data is required, this may be set to NULL. - */ + * If no data is required, this may be set to NULL. */ void * data; } LV2_Host_Feature; @@ -195,10 +192,10 @@ typedef struct _LV2_Descriptor { * Note that instance initialisation should generally occur in * activate() rather than here. If a host calls instantiate, it MUST * call cleanup() at some point in the future. */ - LV2_Handle (*instantiate)(const struct _LV2_Descriptor * Descriptor, - double SampleRate, - const char * BundlePath, - const LV2_Host_Feature *const * HostFeatures); + LV2_Handle (*instantiate)(const struct _LV2_Descriptor * descriptor, + double sample_rate, + const char * bundle_path, + const LV2_Host_Feature *const * host_features); /** Function pointer that connects a port on a plugin instance to a memory * location where the block of data for the port will be read/written. @@ -231,9 +228,9 @@ typedef struct _LV2_Descriptor { * If the plugin has the property lv2:hardRTCapable then there are * various things that the plugin MUST NOT do within the connect_port() * function (see lv2.ttl). */ - void (*connect_port)(LV2_Handle Instance, - uint32_t Port, - void * DataLocation); + void (*connect_port)(LV2_Handle instance, + uint32_t port, + void * data_location); /** Function pointer that initialises a plugin instance and activates * it for use. @@ -257,7 +254,7 @@ typedef struct _LV2_Descriptor { * * Note that connect_port() may be called before or after a call to * activate(). */ - void (*activate)(LV2_Handle Instance); + void (*activate)(LV2_Handle instance); /** Function pointer that runs a plugin instance for a block. * @@ -273,8 +270,8 @@ typedef struct _LV2_Descriptor { * If the plugin has the property lv2:hardRTCapable then there are * various things that the plugin MUST NOT do within the run() * function (see lv2.ttl). */ - void (*run)(LV2_Handle Instance, - uint32_t SampleCount); + void (*run)(LV2_Handle instance, + uint32_t sampleCount); /** This is the counterpart to activate() (see above). If there is * nothing for deactivate() to do then the plugin writer may provide @@ -291,7 +288,7 @@ typedef struct _LV2_Descriptor { * instance will be reinitialised when activate() is called to reuse it. * Hosts MUST NOT call deactivate() unless activate() was previously * called. */ - void (*deactivate)(LV2_Handle Instance); + void (*deactivate)(LV2_Handle instance); /** This is the counterpart to instantiate() (see above). Once an instance * of a plugin has been finished with it can be deleted using this @@ -302,7 +299,7 @@ typedef struct _LV2_Descriptor { * call to deactivate() MUST be made before cleanup() is called. * Hosts MUST NOT call cleanup() unless instantiate() was previously * called. */ - void (*cleanup)(LV2_Handle Instance); + void (*cleanup)(LV2_Handle instance); /** Function pointer that can be used to return additional instance data for * a plugin defined by some extenion (e.g. a struct containing additional @@ -319,15 +316,16 @@ typedef struct _LV2_Descriptor { * NULL if it does not support the extension, but hosts SHOULD NOT use this * as a discovery method (e.g. hosts should only call this function for * extensions known to be supported by the plugin from the data file). + * + * The host is never responsible for freeing the returned value. * * NOTE: It is highly recommended that this function returns a struct, and * NOT a direct function pointer. Standard C++ (for real reasons) does not * allow type casts from void* to a function pointer type. To provide * additional functions a struct should be returned containing the extra * function pointers (which is valid standard C++, and a much better idea - * for extensibility anyway). - */ - void* (*extension_data)(const char * URI); + * for extensibility anyway). */ + void* (*extension_data)(const char * uri); } LV2_Descriptor; @@ -360,12 +358,12 @@ typedef struct _LV2_Descriptor { * index that results in NULL being returned. Index has no meaning, * hosts MUST NOT depend on it remaining constant (ie when serialising) * in any way. */ -const LV2_Descriptor * lv2_descriptor(uint32_t Index); +const LV2_Descriptor * lv2_descriptor(uint32_t index); /** Datatype corresponding to the lv2_descriptor() function. */ typedef const LV2_Descriptor * -(*LV2_Descriptor_Function)(uint32_t Index); +(*LV2_Descriptor_Function)(uint32_t index); /* ******************************************************************** */ diff --git a/slv2/lv2_gui.h b/slv2/lv2_gui.h new file mode 100644 index 0000000..696f20b --- /dev/null +++ b/slv2/lv2_gui.h @@ -0,0 +1,346 @@ +/************************************************************************ + * + * In-process UI extension for LV2 + * + * Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com> + * + * Based on lv2.h, which is: + * + * Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, + * Stefan Westerfeld + * Copyright (C) 2006 Steve Harris, Dave Robillard. + * + * This header is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, + * or (at your option) any later version. + * + * This header 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA. + * + ***********************************************************************/ + +/** @file + This extension defines an interface that can be used in LV2 plugins and + hosts to create GUIs for plugins. The GUIs are plugins that reside in + shared object files in an LV2 bundle and be referenced in the RDF file + using the triples (Turtle shown) +<pre> + @prefix guiext: <http://ll-plugins.nongnu.org/lv2/ext/ipgui/1#> . + <http://my.plugin> guiext:gui <http://my.plugingui> . + <http://my.plugingui> guiext:binary <mygui.so> . +</pre> + where <http://my.plugin> is the URI of the plugin, <http://my.plugingui> is + the URI of the plugin GUI and <mygui.so> is the relative URI to the shared + object file. While it is possible to have the plugin GUI and the plugin in + the same shared object file it is probably a good idea to keep them + separate so that hosts that don't want GUIs don't have to load the GUI code. + + (Note: the prefix above is used throughout this file for the same URI) + + It's entirely possible to have multiple GUIs for the same plugin, or to have + the GUI for a plugin in a different bundle from the actual plugin - this + way people other than the plugin author can write plugin GUIs independently + without editing the original plugin bundle. If a GUI is in a separate bundle + the first triple above should be in that bundle's manifest.ttl file so that + hosts can find the GUI when scanning the manifests. + + Note that the process that loads the shared object file containing the GUI + code and the process that loads the shared object file containing the + actual plugin implementation does not have to be the same. There are many + valid reasons for having the plugin and the GUI in different processes, or + even on different machines. This means that you can _not_ use singletons + and global variables and expect them to refer to the same objects in the + GUI and the actual plugin. The function callback interface defined in this + header is all you can expect to work. + + Since the LV2 specification itself allows for extensions that may add + new types of data and configuration parameters that plugin authors may + want to control with a GUI, this extension allows for meta-extensions that + can extend the interface between the GUI and the host. See the + instantiate() and extension_data() callback pointers for more details. + + Note that this extension is NOT a Host Feature. There is no way for a plugin + to know whether the host that loads it supports GUIs or not, and the plugin + must ALWAYS work without the GUI (although it may be rather useless unless + it has been configured using the GUI in a previous session). + + GUIs written to this specification do not need to be threadsafe - the + functions defined below may only be called in the same thread as the UI + main loop is running in. +*/ + +#ifndef LV2_GUI_H +#define LV2_GUI_H + +#include "lv2.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** A pointer to some widget. + * The actual type of the widget is defined by the type URI of the GUI. + * e.g. if "<http://example.org/somegui> a guiext:GtkGUI", this is a pointer + * to a GtkWidget. All the functionality provided by this extension is + * toolkit independent, the host only needs to pass the necessary callbacks + * and display the widget, if possible. Plugins may have several GUIs, + * in various toolkits. + */ +typedef void* LV2UI_Widget; + + +/** This handle indicates a particular instance of a GUI. + It is valid to compare this to NULL (0 for C++) but otherwise the + host MUST not attempt to interpret it. The GUI plugin may use it to + reference internal instance data. */ +typedef void* LV2UI_Handle; + + +/** This handle indicates a particular plugin instance, provided by the host. + It is valid to compare this to NULL (0 for C++) but otherwise the + GUI plugin MUST not attempt to interpret it. The host may use it to + reference internal instance data. */ +typedef void* LV2UI_Controller; + + +/** This is the type of the host-provided function that the GUI can use to + send data to a plugin's input ports. The @c buffer parameter must point + to a block of data, @c buffer_size bytes large. The contents of this buffer + will depend on the class of the port it's being sent to. For ports of the + class lv2:ControlPort, buffer_size should be sizeof(float) and the buffer + contents should be a float value. For ports of the class llext:MidiPort the + buffer should contain the data bytes of a single MIDI event, and buffer_size + should be the number of bytes in the event. No other port classes are + allowed, unless the format and the meaning of the buffer passed to this + function is defined in the extension that specifies that class or in a + separate GUI host feature extension that is required by this GUI. + + The GUI is responsible for allocating the buffer and deallocating it after + the call. There are no timing guarantees at all for this function, although + the faster the host can get the data to the plugin port the better. A + function pointer of this type will be provided to the GUI by the host in + the instantiate() function. */ +typedef void (*LV2UI_Write_Function)(LV2UI_Controller controller, + uint32_t port_index, + uint32_t buffer_size, + const void* buffer); + +/** This is the type of the host-provided function that the GUI can use to + send arbitrary commands to the plugin. The parameters after the first one + should be const char* variables, terminated by a NULL pointer, and will be + interpreted as a command with arguments. A function of this type will be + provided to the GUI by the host in the instantiate() function. */ +typedef void (*LV2UI_Command_Function)(LV2UI_Controller controller, + uint32_t argc, + const char* const* argv); + +/** This is the type of the host-provided function that the GUI can use to + request a program change in the host. A function of this type will be + provided to the GUI by the host in the instantiate() function. Calling + this function does not guarantee that the program will change, it is just + a request. If the program does change, the GUI's current_program_changed() + callback will be called, either before or after this function returns + depending on whether the GUI host <-> plugin instance communication is + synchronous or asynchronous. */ +typedef void (*LV2UI_Program_Change_Function)(LV2UI_Controller controller, + unsigned char program); + +/** This is the type of the host-provided function that the GUI can use to + request that the current state of the plugin is saved to a program. + A function of this type will be provided to the GUI by the host in the + instantiate function. Calling this function does not guarantee that the + state will be saved, it is just a request. If the state is saved, the + GUI's program_added() callback will be called, either before or after + this function returns depending on whether the GUI host <-> plugin + instance communication is synchronous or asynchronous. */ +typedef void (*LV2UI_Program_Save_Function)(LV2UI_Controller controller, + unsigned char program, + const char* name); + + +/** */ +typedef struct _LV2UI_Descriptor { + + /** The URI for this GUI (not for the plugin it controls). */ + const char* URI; + + /** Create a new GUI object and return a handle to it. This function works + similarly to the instantiate() member in LV2_Descriptor, with the + additions that the URI for the plugin that this GUI is for is passed + as a parameter, a function pointer and a controller handle are passed to + allow the plugin to write to input ports in the plugin (write_function + and controller) and a pointer to a LV2_Widget is passed, which the GUI + plugin should set to point to a newly created widget which will be the + GUI for the plugin. This widget may only be destroyed by cleanup(). + + The features array works like the one in the instantiate() member + in LV2_Descriptor, except that the URIs should be denoted with the triples + <pre> + <http://my.plugingui> guiext:optionalFeature <http://my.guifeature> + </pre> + or + <pre> + <http://my.plugingui> guiext:requiredFeature <http://my.guifeature> + </pre> + in the RDF file, instead of the lv2:optionalFeature or lv2:requiredFeature + that is used by host features. These features are associated with the GUI, + not with the plugin - they are not actually LV2 Host Features, they just + use the same data structure. + + The same rules apply for these features as for normal host features - + if a feature is listed as required in the RDF file and the host does not + support it, it must not load the GUI. + */ + LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor, + const char* plugin_uri, + const char* bundle_path, + LV2UI_Write_Function write_function, + LV2UI_Command_Function command_function, + LV2UI_Program_Change_Function program_function, + LV2UI_Program_Save_Function save_function, + LV2UI_Controller controller, + LV2UI_Widget* widget, + const LV2_Host_Feature* const* host_features); + + + /** Destroy the GUI object and the associated widget. + */ + void (*cleanup)(LV2UI_Handle gui); + + /** Tell the GUI that something interesting has happened at a plugin port. + For control ports this would be when the value in the buffer has changed, + for message-based port classes like MIDI or OSC it would be when a + message has arrived in the buffer. For other port classes it is not + defined when this function is called, unless it is specified in the + definition of that port class extension. For control ports the default + setting is to call this function whenever an input control port value + has changed but not when any output control port value has changed, for + all other port classes the default setting is to never call this function. + + However, the default setting can be modified by using the following + URIs: + <pre> + guiext:portNotification + guiext:noPortNotification + guiext:plugin + guiext:portIndex + </pre> + For example, if you want the GUI with uri + <code><http://my.plugingui></code> for the plugin with URI + <code><http://my.plugin></code> to get notified when the value of the + output control port with index 4 changes, you would use the following + in the RDF for your GUI: + <pre> + <http://my.plugingui> guiext:portNotification [ guiext:plugin <http://my.plugin> ; + guiext:portIndex 4 ] . + </pre> + and similarly with <code>guiext:noPortNotification</code> if you wanted to + prevent notifications for a port for which it would be on by default + otherwise. + + The @c buffer is only valid during the time of this function call, so if + the GUI wants to keep it for later use it has to copy the contents to an + internal buffer. + + The buffer is subject to the same rules as the ones for the + LV2_Write_Function type. This means that a plugin GUI may not request a + portNotification for a port that has a class other than lv2:ControlPort + or llext:MidiPort unless the buffer format and meaning is specified in + the extension that defines that port class, or in a separate GUI host + feature extension that is required by the GUI. Any GUI that does that + should be considered broken and the host should not use it. + + This member may be set to NULL if the GUI is not interested in any + port events. + */ + void (*port_event)(LV2UI_Handle gui, + uint32_t port, + uint32_t buffer_size, + const void* buffer); + + /** This function is called when the plugin instance wants to send feedback + to the GUI. It may be called in response to a command function call, + either before or after the command function has returned (depending on + whether the GUI host <-> plugin instance communication is synchronous or + asynchronous). */ + void (*feedback)(LV2UI_Handle gui, + uint32_t argc, + const char* const* argv); + + /** This function is called when the host adds a new program to its program + list, or changes the name of an old one. It may be set to NULL if the + GUI isn't interested in displaying program information. */ + void (*program_added)(LV2UI_Handle gui, + unsigned char number, + const char* name); + + /** This function is called when the host removes a program from its program + list. It may be set to NULL if the GUI isn't interested in displaying + program information. */ + void (*program_removed)(LV2UI_Handle gui, + unsigned char number); + + /** This function is called when the host clears its program list. It may be + set to NULL if the GUI isn't interested in displaying program + information. */ + void (*programs_cleared)(LV2UI_Handle gui); + + /** This function is called when the host changes the current program. It may + be set to NULL if the GUI isn't interested in displaying program + information. */ + void (*current_program_changed)(LV2UI_Handle gui, + unsigned char number); + + /** Returns a data structure associated with an extension URI, for example + a struct containing additional function pointers. Avoid returning + function pointers directly since standard C++ has no valid way of + casting a void* to a function pointer. This member may be set to NULL + if the GUI is not interested in supporting any extensions. This is similar + to the extension_data() member in LV2_Descriptor. + */ + void* (*extension_data)(LV2UI_Handle gui, + const char* uri); + +} LV2UI_Descriptor; + + + +/** A plugin programmer must include a function called "lv2ui_descriptor" + with the following function prototype within the shared object + file. This function will have C-style linkage (if you are using + C++ this is taken care of by the 'extern "C"' clause at the top of + the file). This function will be accessed by the GUI host using the + @c dlsym() function and called to get a LV2UI_UIDescriptor for the + wanted plugin. + + Just like lv2_descriptor(), this function takes an index parameter. The + index should only be used for enumeration and not as any sort of ID number - + the host should just iterate from 0 and upwards until the function returns + NULL, or a descriptor with an URI matching the one the host is looking for + is returned. +*/ +const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index); + + +/** This is the type of the lv2ui_descriptor() function. */ +typedef const LV2UI_Descriptor* (*LV2UI_DescriptorFunction)(uint32_t index); + + + +#ifdef __cplusplus +} +#endif + + +#endif /* LV2_GUI_H */ + diff --git a/slv2/pluginguiinstance.h b/slv2/pluginguiinstance.h index 7801256..2eb9c60 100644 --- a/slv2/pluginguiinstance.h +++ b/slv2/pluginguiinstance.h @@ -25,7 +25,7 @@ extern "C" { #endif #include <assert.h> -#include <slv2/lv2-gtk2gui.h> +#include <slv2/lv2_gui.h> #include <slv2/plugin.h> /** \defgroup lib Plugin GUI library access @@ -72,11 +72,14 @@ typedef struct _SLV2GUIInstance { * \return NULL if instantiation failed. */ SLV2GUIInstance -slv2_plugin_gtk2_gui_instantiate(SLV2Plugin plugin, - SLV2Value gui, - LV2UI_Set_Control_Function control_function, - LV2UI_Controller controller, - const LV2_Host_Feature** host_features); +slv2_plugin_gtk2_gui_instantiate(SLV2Plugin plugin, + SLV2Value gui, + LV2UI_Write_Function write_function, + LV2UI_Command_Function command_function, + LV2UI_Program_Change_Function program_function, + LV2UI_Program_Save_Function save_function, + LV2UI_Controller controller, + const LV2_Host_Feature* const* host_features); /** Free a plugin GUI instance. @@ -87,9 +90,9 @@ void slv2_gtk2_gui_instance_free(SLV2GUIInstance instance); -/** Get the GTK+ 2.0 widget for the GUI instance. +/** Get the widget for the GUI instance. */ -struct _GtkWidget* +LV2UI_Widget slv2_gtk2_gui_instance_get_widget(SLV2GUIInstance instance); diff --git a/src/pluginguiinstance.c b/src/pluginguiinstance.c index c115751..a29e64d 100644 --- a/src/pluginguiinstance.c +++ b/src/pluginguiinstance.c @@ -32,11 +32,14 @@ SLV2GUIInstance -slv2_plugin_gtk2_gui_instantiate(SLV2Plugin plugin, - SLV2Value gui, - LV2UI_Set_Control_Function control_function, - LV2UI_Controller controller, - const LV2_Host_Feature** host_features) +slv2_plugin_gtk2_gui_instantiate(SLV2Plugin plugin, + SLV2Value gui, + LV2UI_Write_Function write_function, + LV2UI_Command_Function command_function, + LV2UI_Program_Change_Function program_function, + LV2UI_Program_Save_Function save_function, + LV2UI_Controller controller, + const LV2_Host_Feature* const* host_features) { assert(gui->type == SLV2_VALUE_GUI); @@ -48,7 +51,7 @@ slv2_plugin_gtk2_gui_instantiate(SLV2Plugin plugin, bool local_host_features = (host_features == NULL); if (local_host_features) { host_features = malloc(sizeof(LV2_Host_Feature)); - host_features[0] = NULL; + ((LV2_Host_Feature**)host_features)[0] = NULL; } const char* const lib_uri = slv2_value_as_uri(slv2_plugin_get_gui_library_uri(plugin, gui)); @@ -101,9 +104,12 @@ slv2_plugin_gtk2_gui_instantiate(SLV2Plugin plugin, impl->lv2ui_handle = ld->instantiate(ld, slv2_plugin_get_uri(plugin), (char*)bundle_path, - control_function, + write_function, + command_function, + program_function, + save_function, controller, - (struct _GtkWidget**)&impl->widget, + &impl->widget, host_features); impl->lib_handle = lib; result->pimpl = impl; @@ -130,7 +136,7 @@ slv2_plugin_gtk2_gui_instantiate(SLV2Plugin plugin, } if (local_host_features) - free(host_features); + free((LV2_Host_Feature**)host_features); return result; } @@ -150,7 +156,7 @@ slv2_gtk2_gui_instance_free(SLV2GUIInstance instance) } -struct _GtkWidget* +LV2UI_Widget slv2_gtk2_gui_instance_get_widget(SLV2GUIInstance instance) { return instance->pimpl->widget; } diff --git a/src/slv2_internal.h b/src/slv2_internal.h index d2296cf..1dedc50 100644 --- a/src/slv2_internal.h +++ b/src/slv2_internal.h @@ -28,7 +28,7 @@ extern "C" { #include <inttypes.h> #include <librdf.h> #include <slv2/types.h> -#include <slv2/lv2-gtk2gui.h> +#include <slv2/lv2_gui.h> @@ -103,7 +103,7 @@ struct _SLV2GUIInstanceImpl { void* lib_handle; const LV2UI_Descriptor* lv2ui_descriptor; LV2UI_Handle lv2ui_handle; - void* widget; + LV2UI_Widget widget; }; |