DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

ui.h (20482B)


      1 /*
      2   LV2 UI Extension
      3   Copyright 2009-2016 David Robillard <d@drobilla.net>
      4   Copyright 2006-2011 Lars Luthman <lars.luthman@gmail.com>
      5 
      6   Permission to use, copy, modify, and/or distribute this software for any
      7   purpose with or without fee is hereby granted, provided that the above
      8   copyright notice and this permission notice appear in all copies.
      9 
     10   THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17 */
     18 
     19 /**
     20    @defgroup ui User Interfaces
     21 
     22    User interfaces of any type for plugins,
     23    <http://lv2plug.in/ns/extensions/ui> for details.
     24 
     25    @{
     26 */
     27 
     28 #ifndef LV2_UI_H
     29 #define LV2_UI_H
     30 
     31 #include <stdint.h>
     32 
     33 #include "lv2.h"
     34 #include "urid.h"
     35 
     36 #define LV2_UI_URI    "http://lv2plug.in/ns/extensions/ui"  ///< http://lv2plug.in/ns/extensions/ui
     37 #define LV2_UI_PREFIX LV2_UI_URI "#"                        ///< http://lv2plug.in/ns/extensions/ui#
     38 
     39 #define LV2_UI__CocoaUI          LV2_UI_PREFIX "CocoaUI"           ///< http://lv2plug.in/ns/extensions/ui#CocoaUI
     40 #define LV2_UI__Gtk3UI           LV2_UI_PREFIX "Gtk3UI"            ///< http://lv2plug.in/ns/extensions/ui#Gtk3UI
     41 #define LV2_UI__GtkUI            LV2_UI_PREFIX "GtkUI"             ///< http://lv2plug.in/ns/extensions/ui#GtkUI
     42 #define LV2_UI__PortNotification LV2_UI_PREFIX "PortNotification"  ///< http://lv2plug.in/ns/extensions/ui#PortNotification
     43 #define LV2_UI__PortProtocol     LV2_UI_PREFIX "PortProtocol"      ///< http://lv2plug.in/ns/extensions/ui#PortProtocol
     44 #define LV2_UI__Qt4UI            LV2_UI_PREFIX "Qt4UI"             ///< http://lv2plug.in/ns/extensions/ui#Qt4UI
     45 #define LV2_UI__Qt5UI            LV2_UI_PREFIX "Qt5UI"             ///< http://lv2plug.in/ns/extensions/ui#Qt5UI
     46 #define LV2_UI__UI               LV2_UI_PREFIX "UI"                ///< http://lv2plug.in/ns/extensions/ui#UI
     47 #define LV2_UI__WindowsUI        LV2_UI_PREFIX "WindowsUI"         ///< http://lv2plug.in/ns/extensions/ui#WindowsUI
     48 #define LV2_UI__X11UI            LV2_UI_PREFIX "X11UI"             ///< http://lv2plug.in/ns/extensions/ui#X11UI
     49 #define LV2_UI__backgroundColor  LV2_UI_PREFIX "backgroundColor"   ///< http://lv2plug.in/ns/extensions/ui#backgroundColor
     50 #define LV2_UI__binary           LV2_UI_PREFIX "binary"            ///< http://lv2plug.in/ns/extensions/ui#binary
     51 #define LV2_UI__fixedSize        LV2_UI_PREFIX "fixedSize"         ///< http://lv2plug.in/ns/extensions/ui#fixedSize
     52 #define LV2_UI__foregroundColor  LV2_UI_PREFIX "foregroundColor"   ///< http://lv2plug.in/ns/extensions/ui#foregroundColor
     53 #define LV2_UI__idleInterface    LV2_UI_PREFIX "idleInterface"     ///< http://lv2plug.in/ns/extensions/ui#idleInterface
     54 #define LV2_UI__noUserResize     LV2_UI_PREFIX "noUserResize"      ///< http://lv2plug.in/ns/extensions/ui#noUserResize
     55 #define LV2_UI__notifyType       LV2_UI_PREFIX "notifyType"        ///< http://lv2plug.in/ns/extensions/ui#notifyType
     56 #define LV2_UI__parent           LV2_UI_PREFIX "parent"            ///< http://lv2plug.in/ns/extensions/ui#parent
     57 #define LV2_UI__plugin           LV2_UI_PREFIX "plugin"            ///< http://lv2plug.in/ns/extensions/ui#plugin
     58 #define LV2_UI__portIndex        LV2_UI_PREFIX "portIndex"         ///< http://lv2plug.in/ns/extensions/ui#portIndex
     59 #define LV2_UI__portMap          LV2_UI_PREFIX "portMap"           ///< http://lv2plug.in/ns/extensions/ui#portMap
     60 #define LV2_UI__portNotification LV2_UI_PREFIX "portNotification"  ///< http://lv2plug.in/ns/extensions/ui#portNotification
     61 #define LV2_UI__portSubscribe    LV2_UI_PREFIX "portSubscribe"     ///< http://lv2plug.in/ns/extensions/ui#portSubscribe
     62 #define LV2_UI__protocol         LV2_UI_PREFIX "protocol"          ///< http://lv2plug.in/ns/extensions/ui#protocol
     63 #define LV2_UI__floatProtocol    LV2_UI_PREFIX "floatProtocol"     ///< http://lv2plug.in/ns/extensions/ui#floatProtocol
     64 #define LV2_UI__peakProtocol     LV2_UI_PREFIX "peakProtocol"      ///< http://lv2plug.in/ns/extensions/ui#peakProtocol
     65 #define LV2_UI__requestValue     LV2_UI_PREFIX "requestValue"      ///< http://lv2plug.in/ns/extensions/ui#requestValue
     66 #define LV2_UI__resize           LV2_UI_PREFIX "resize"            ///< http://lv2plug.in/ns/extensions/ui#resize
     67 #define LV2_UI__scaleFactor      LV2_UI_PREFIX "scaleFactor"       ///< http://lv2plug.in/ns/extensions/ui#scaleFactor
     68 #define LV2_UI__showInterface    LV2_UI_PREFIX "showInterface"     ///< http://lv2plug.in/ns/extensions/ui#showInterface
     69 #define LV2_UI__touch            LV2_UI_PREFIX "touch"             ///< http://lv2plug.in/ns/extensions/ui#touch
     70 #define LV2_UI__ui               LV2_UI_PREFIX "ui"                ///< http://lv2plug.in/ns/extensions/ui#ui
     71 #define LV2_UI__updateRate       LV2_UI_PREFIX "updateRate"        ///< http://lv2plug.in/ns/extensions/ui#updateRate
     72 #define LV2_UI__windowTitle      LV2_UI_PREFIX "windowTitle"       ///< http://lv2plug.in/ns/extensions/ui#windowTitle
     73 
     74 /**
     75    The index returned by LV2UI_Port_Map::port_index() for unknown ports.
     76 */
     77 #define LV2UI_INVALID_PORT_INDEX ((uint32_t)-1)
     78 
     79 #ifdef __cplusplus
     80 extern "C" {
     81 #else
     82 #    include <stdbool.h>
     83 #endif
     84 
     85 /**
     86    A pointer to some widget or other type of UI handle.
     87 
     88    The actual type is defined by the type of the UI.
     89 */
     90 typedef void* LV2UI_Widget;
     91 
     92 /**
     93    A pointer to UI instance internals.
     94 
     95    The host may compare this to NULL, but otherwise MUST NOT interpret it.
     96 */
     97 typedef void* LV2UI_Handle;
     98 
     99 /**
    100    A pointer to a controller provided by the host.
    101 
    102    The UI may compare this to NULL, but otherwise MUST NOT interpret it.
    103 */
    104 typedef void* LV2UI_Controller;
    105 
    106 /**
    107    A pointer to opaque data for a feature.
    108 */
    109 typedef void* LV2UI_Feature_Handle;
    110 
    111 /**
    112    A host-provided function that sends data to a plugin's input ports.
    113 
    114    @param controller The opaque controller pointer passed to
    115    LV2UI_Descriptor::instantiate().
    116 
    117    @param port_index Index of the port to update.
    118 
    119    @param buffer Buffer containing `buffer_size` bytes of data.
    120 
    121    @param buffer_size Size of `buffer` in bytes.
    122 
    123    @param port_protocol Either 0 or the URID for a ui:PortProtocol.  If 0, the
    124    protocol is implicitly ui:floatProtocol, the port MUST be an lv2:ControlPort
    125    input, `buffer` MUST point to a single float value, and `buffer_size` MUST
    126    be sizeof(float).  The UI SHOULD NOT use a protocol not supported by the
    127    host, but the host MUST gracefully ignore any protocol it does not
    128    understand.
    129 */
    130 typedef void (*LV2UI_Write_Function)(LV2UI_Controller controller,
    131                                      uint32_t         port_index,
    132                                      uint32_t         buffer_size,
    133                                      uint32_t         port_protocol,
    134                                      const void*      buffer);
    135 
    136 /**
    137    A plugin UI.
    138 
    139    A pointer to an object of this type is returned by the lv2ui_descriptor()
    140    function.
    141 */
    142 typedef struct _LV2UI_Descriptor {
    143 	/**
    144 	   The URI for this UI (not for the plugin it controls).
    145 	*/
    146 	const char* URI;
    147 
    148 	/**
    149 	   Create a new UI and return a handle to it.  This function works
    150 	   similarly to LV2_Descriptor::instantiate().
    151 
    152 	   @param descriptor The descriptor for the UI to instantiate.
    153 
    154 	   @param plugin_uri The URI of the plugin that this UI will control.
    155 
    156 	   @param bundle_path The path to the bundle containing this UI, including
    157 	   the trailing directory separator.
    158 
    159 	   @param write_function A function that the UI can use to send data to the
    160 	   plugin's input ports.
    161 
    162 	   @param controller A handle for the UI instance to be passed as the
    163 	   first parameter of UI methods.
    164 
    165 	   @param widget (output) widget pointer.  The UI points this at its main
    166 	   widget, which has the type defined by the UI type in the data file.
    167 
    168 	   @param features An array of LV2_Feature pointers.  The host must pass
    169 	   all feature URIs that it and the UI supports and any additional data, as
    170 	   in LV2_Descriptor::instantiate().  Note that UI features and plugin
    171 	   features are not necessarily the same.
    172 
    173 	*/
    174 	LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor,
    175 	                            const char*                     plugin_uri,
    176 	                            const char*                     bundle_path,
    177 	                            LV2UI_Write_Function            write_function,
    178 	                            LV2UI_Controller                controller,
    179 	                            LV2UI_Widget*                   widget,
    180 	                            const LV2_Feature* const*       features);
    181 
    182 
    183 	/**
    184 	   Destroy the UI.  The host must not try to access the widget after
    185 	   calling this function.
    186 	*/
    187 	void (*cleanup)(LV2UI_Handle ui);
    188 
    189 	/**
    190 	   Tell the UI that something interesting has happened at a plugin port.
    191 
    192 	   What is "interesting" and how it is written to `buffer` is defined by
    193 	   `format`, which has the same meaning as in LV2UI_Write_Function().
    194 	   Format 0 is a special case for lv2:ControlPort, where this function
    195 	   should be called when the port value changes (but not necessarily for
    196 	   every change), `buffer_size` must be sizeof(float), and `buffer`
    197 	   points to a single IEEE-754 float.
    198 
    199 	   By default, the host should only call this function for lv2:ControlPort
    200 	   inputs.  However, the UI can request updates for other ports statically
    201 	   with ui:portNotification or dynamicaly with ui:portSubscribe.
    202 
    203 	   The UI MUST NOT retain any reference to `buffer` after this function
    204 	   returns, it is only valid for the duration of the call.
    205 
    206 	   This member may be NULL if the UI is not interested in any port events.
    207 	*/
    208 	void (*port_event)(LV2UI_Handle ui,
    209 	                   uint32_t     port_index,
    210 	                   uint32_t     buffer_size,
    211 	                   uint32_t     format,
    212 	                   const void*  buffer);
    213 
    214 	/**
    215 	   Return a data structure associated with an extension URI, typically an
    216 	   interface struct with additional function pointers
    217 
    218 	   This member may be set to NULL if the UI is not interested in supporting
    219 	   any extensions. This is similar to LV2_Descriptor::extension_data().
    220 
    221 	*/
    222 	const void* (*extension_data)(const char* uri);
    223 } LV2UI_Descriptor;
    224 
    225 /**
    226    Feature/interface for resizable UIs (LV2_UI__resize).
    227 
    228    This structure is used in two ways: as a feature passed by the host via
    229    LV2UI_Descriptor::instantiate(), or as an interface provided by a UI via
    230    LV2UI_Descriptor::extension_data()).
    231 */
    232 typedef struct _LV2UI_Resize {
    233 	/**
    234 	   Pointer to opaque data which must be passed to ui_resize().
    235 	*/
    236 	LV2UI_Feature_Handle handle;
    237 
    238 	/**
    239 	   Request/advertise a size change.
    240 
    241 	   When provided by the host, the UI may call this function to inform the
    242 	   host about the size of the UI.
    243 
    244 	   When provided by the UI, the host may call this function to notify the
    245 	   UI that it should change its size accordingly.  In this case, the host
    246 	   must pass the LV2UI_Handle to provide access to the UI instance.
    247 
    248 	   @return 0 on success.
    249 	*/
    250 	int (*ui_resize)(LV2UI_Feature_Handle handle, int width, int height);
    251 } LV2UI_Resize;
    252 
    253 /**
    254    Feature to map port symbols to UIs.
    255 
    256    This can be used by the UI to get the index for a port with the given
    257    symbol.  This makes it possible to implement and distribute a UI separately
    258    from the plugin (since symbol, unlike index, is a stable port identifier).
    259 */
    260 typedef struct _LV2UI_Port_Map {
    261 	/**
    262 	   Pointer to opaque data which must be passed to port_index().
    263 	*/
    264 	LV2UI_Feature_Handle handle;
    265 
    266 	/**
    267 	   Get the index for the port with the given `symbol`.
    268 
    269 	   @return The index of the port, or LV2UI_INVALID_PORT_INDEX if no such
    270 	   port is found.
    271 	*/
    272 	uint32_t (*port_index)(LV2UI_Feature_Handle handle, const char* symbol);
    273 } LV2UI_Port_Map;
    274 
    275 /**
    276    Feature to subscribe to port updates (LV2_UI__portSubscribe).
    277 */
    278 typedef struct _LV2UI_Port_Subscribe {
    279 	/**
    280 	   Pointer to opaque data which must be passed to subscribe() and
    281 	   unsubscribe().
    282 	*/
    283 	LV2UI_Feature_Handle handle;
    284 
    285 	/**
    286 	   Subscribe to updates for a port.
    287 
    288 	   This means that the host will call the UI's port_event() function when
    289 	   the port value changes (as defined by protocol).
    290 
    291 	   Calling this function with the same `port_index` and `port_protocol`
    292 	   as an already active subscription has no effect.
    293 
    294 	   @param handle The handle field of this struct.
    295 	   @param port_index The index of the port.
    296 	   @param port_protocol The URID of the ui:PortProtocol.
    297 	   @param features Features for this subscription.
    298 	   @return 0 on success.
    299 	*/
    300 	uint32_t (*subscribe)(LV2UI_Feature_Handle      handle,
    301 	                      uint32_t                  port_index,
    302 	                      uint32_t                  port_protocol,
    303 	                      const LV2_Feature* const* features);
    304 
    305 	/**
    306 	   Unsubscribe from updates for a port.
    307 
    308 	   This means that the host will cease calling calling port_event() when
    309 	   the port value changes.
    310 
    311 	   Calling this function with a `port_index` and `port_protocol` that
    312 	   does not refer to an active port subscription has no effect.
    313 
    314 	   @param handle The handle field of this struct.
    315 	   @param port_index The index of the port.
    316 	   @param port_protocol The URID of the ui:PortProtocol.
    317 	   @param features Features for this subscription.
    318 	   @return 0 on success.
    319 	*/
    320 	uint32_t (*unsubscribe)(LV2UI_Feature_Handle      handle,
    321 	                        uint32_t                  port_index,
    322 	                        uint32_t                  port_protocol,
    323 	                        const LV2_Feature* const* features);
    324 } LV2UI_Port_Subscribe;
    325 
    326 /**
    327    A feature to notify the host that the user has grabbed a UI control.
    328 */
    329 typedef struct _LV2UI_Touch {
    330 	/**
    331 	   Pointer to opaque data which must be passed to ui_resize().
    332 	*/
    333 	LV2UI_Feature_Handle handle;
    334 
    335 	/**
    336 	   Notify the host that a control has been grabbed or released.
    337 
    338 	   The host should cease automating the port or otherwise manipulating the
    339 	   port value until the control has been ungrabbed.
    340 
    341 	   @param handle The handle field of this struct.
    342 	   @param port_index The index of the port associated with the control.
    343 	   @param grabbed If true, the control has been grabbed, otherwise the
    344 	   control has been released.
    345 	*/
    346 	void (*touch)(LV2UI_Feature_Handle handle,
    347 	              uint32_t             port_index,
    348 	              bool                 grabbed);
    349 } LV2UI_Touch;
    350 
    351 /**
    352    A status code for LV2UI_Request_Value::request.
    353 */
    354 typedef enum {
    355 	/**
    356 	   Completed successfully.
    357 
    358 	   The host will set the parameter later if the user choses a new value.
    359 	*/
    360 	LV2UI_REQUEST_VALUE_SUCCESS,
    361 
    362 	/**
    363 	   Parameter already being requested.
    364 
    365 	   The host is already requesting a parameter from the user (for example, a
    366 	   dialog is visible), or the UI is otherwise busy and can not make this
    367 	   request.
    368 	*/
    369 	LV2UI_REQUEST_VALUE_BUSY,
    370 
    371 	/**
    372 	   Unknown parameter.
    373 
    374 	   The host is not aware of this parameter, and is not able to set a new
    375 	   value for it.
    376 	*/
    377 	LV2UI_REQUEST_VALUE_ERR_UNKNOWN,
    378 
    379 	/**
    380 	   Unsupported parameter.
    381 
    382 	   The host knows about this parameter, but does not support requesting a
    383 	   new value for it from the user.  This is likely because the host does
    384 	   not have UI support for choosing a value with the appropriate type.
    385 	*/
    386 	LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED
    387 } LV2UI_Request_Value_Status;
    388 
    389 /**
    390    A feature to request a new parameter value from the host.
    391 */
    392 typedef struct {
    393 	/**
    394 	   Pointer to opaque data which must be passed to request().
    395 	*/
    396 	LV2UI_Feature_Handle handle;
    397 
    398 	/**
    399 	   Request a value for a parameter from the host.
    400 
    401 	   This is mainly used by UIs to request values for complex parameters that
    402 	   don't change often, such as file paths, but it may be used to request
    403 	   any parameter value.
    404 
    405 	   This function returns immediately, and the return value indicates
    406 	   whether the host can fulfill the request.  The host may notify the
    407 	   plugin about the new parameter value, for example when a file is
    408 	   selected by the user, via the usual mechanism.  Typically, the host will
    409 	   send a message to the plugin that sets the new parameter value, and the
    410 	   plugin will notify the UI via a message as usual for any other parameter
    411 	   change.
    412 
    413 	   To provide an appropriate UI, the host can determine details about the
    414 	   parameter from the plugin data as usual.  The additional parameters of
    415 	   this function provide support for more advanced use cases, but in the
    416 	   simple common case, the plugin will simply pass the key of the desired
    417 	   parameter and zero for everything else.
    418 
    419 	   @param handle The handle field of this struct.
    420 
    421 	   @param key The URID of the parameter.
    422 
    423 	   @param type The optional type of the value to request.  This can be used
    424 	   to request a specific value type for parameters that support several.
    425 	   If non-zero, it must be the URID of an instance of rdfs:Class or
    426 	   rdfs:Datatype.
    427 
    428 	   @param features Additional features for this request, or NULL.
    429 
    430 	   @return A status code which is 0 on success.
    431 	*/
    432 	LV2UI_Request_Value_Status (*request)(LV2UI_Feature_Handle      handle,
    433 	                                      LV2_URID                  key,
    434 	                                      LV2_URID                  type,
    435 	                                      const LV2_Feature* const* features);
    436 
    437 } LV2UI_Request_Value;
    438 
    439 /**
    440    UI Idle Interface (LV2_UI__idleInterface)
    441 
    442    UIs can provide this interface to have an idle() callback called by the host
    443    rapidly to update the UI.
    444 */
    445 typedef struct _LV2UI_Idle_Interface {
    446 	/**
    447 	   Run a single iteration of the UI's idle loop.
    448 
    449 	   This will be called rapidly in the UI thread at a rate appropriate
    450 	   for a toolkit main loop.  There are no precise timing guarantees, but
    451 	   the host should attempt to call idle() at a high enough rate for smooth
    452 	   animation, at least 30Hz.
    453 
    454 	   @return non-zero if the UI has been closed, in which case the host
    455 	   should stop calling idle(), and can either completely destroy the UI, or
    456 	   re-show it and resume calling idle().
    457 	*/
    458 	int (*idle)(LV2UI_Handle ui);
    459 } LV2UI_Idle_Interface;
    460 
    461 /**
    462    UI Show Interface (LV2_UI__showInterface)
    463 
    464    UIs can provide this interface to show and hide a window, which allows them
    465    to function in hosts unable to embed their widget.  This allows any UI to
    466    provide a fallback for embedding that works in any host.
    467 
    468    If used:
    469    - The host MUST use LV2UI_Idle_Interface to drive the UI.
    470    - The UI MUST return non-zero from LV2UI_Idle_Interface::idle() when it has been closed.
    471    - If idle() returns non-zero, the host MUST call hide() and stop calling
    472      idle().  It MAY later call show() then resume calling idle().
    473 */
    474 typedef struct _LV2UI_Show_Interface {
    475 	/**
    476 	   Show a window for this UI.
    477 
    478 	   The window title MAY have been passed by the host to
    479 	   LV2UI_Descriptor::instantiate() as an LV2_Options_Option with key
    480 	   LV2_UI__windowTitle.
    481 
    482 	   @return 0 on success, or anything else to stop being called.
    483 	*/
    484 	int (*show)(LV2UI_Handle ui);
    485 
    486 	/**
    487 	   Hide the window for this UI.
    488 
    489 	   @return 0 on success, or anything else to stop being called.
    490 	*/
    491 	int (*hide)(LV2UI_Handle ui);
    492 } LV2UI_Show_Interface;
    493 
    494 /**
    495    Peak data for a slice of time, the update format for ui:peakProtocol.
    496 */
    497 typedef struct _LV2UI_Peak_Data {
    498 	/**
    499 	   The start of the measurement period.  This is just a running counter
    500 	   that is only meaningful in comparison to previous values and must not be
    501 	   interpreted as an absolute time.
    502 	*/
    503 	uint32_t period_start;
    504 
    505 	/**
    506 	   The size of the measurement period, in the same units as period_start.
    507 	*/
    508 	uint32_t period_size;
    509 
    510 	/**
    511 	   The peak value for the measurement period. This should be the maximal
    512 	   value for abs(sample) over all the samples in the period.
    513 	*/
    514 	float peak;
    515 } LV2UI_Peak_Data;
    516 
    517 /**
    518    Prototype for UI accessor function.
    519 
    520    This is the entry point to a UI library, which works in the same way as
    521    lv2_descriptor() but for UIs rather than plugins.
    522 */
    523 LV2_SYMBOL_EXPORT
    524 const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index);
    525 
    526 /**
    527    The type of the lv2ui_descriptor() function.
    528 */
    529 typedef const LV2UI_Descriptor* (*LV2UI_DescriptorFunction)(uint32_t index);
    530 
    531 #ifdef __cplusplus
    532 }
    533 #endif
    534 
    535 #endif /* LV2_UI_H */
    536 
    537 /**
    538    @}
    539 */