Extension API

Since version 1.1.3 (1.4.2 for macOS), Shadron's functionality may be expanded through extensions, which can be placed in the extensions directory, located

  • for Windows, either in %APPDATA%\Shadron or next to the Shadron executable;
  • for macOS, either in ~/.config/Shadron or in the app package's Resources folder.

The capabilities of extensions include providing input image and animation objects, providing new types of image/animation exports, receiving image data from Shadron through streams, and decoding image files and sound files which are not normally supported.

An extension is a dynamic library file (DLL or dylib) that implements the shadron-api.h. Each function must return a result code (one of SHADRON_RESULT_???). Unless specified otherwise or an error occurs, it should be SHADRON_RESULT_OK to indicate success.

Note: Extensions must not use the OpenGL API, except in a separate thread.

Identifiers are strings with ASCII encoding (irrespective of encoding set by extension!), beginning with a letter, and containing only basic alphanumeric characters and the underscore.

Extension registration

Each extension must be registered on program launch and unregistered before exit via the following functions.

int shadron_register_extension(int *magicNumber, int *flags, char *name, int *nameLength, int *version, void **context);

Registers the extension. If there is any discrepancy in the output values, the extension will not be registered and no further calls will be made.

  • magicNumber (out) – must be set to SHADRON_MAGICNO to verify compatibility with the current API
  • flags (out) – a bit field that must be filled with the extension's capabilities and string encoding. Specifying string encoding is mandatory
    • SHADRON_FLAG_IMAGE – support for image objects
    • SHADRON_FLAG_ANIMATION – support for animation objects
    • SHADRON_FLAG_EXPORT – support for exports
    • SHADRON_FLAG_STREAM – support for streams
    • SHADRON_FLAG_IMAGE_DECODER – image format decoding support
    • SHADRON_FLAG_SOUND_DECODER – sound format decoding support
    • SHADRON_FLAG_CHARSET_UTF8 – UTF-8 string encoding
    • SHADRON_FLAG_CHARSET_UTF16LE – UTF-16 little endian string encoding
  • name – the buffer where to copy the extension's name, by which the extension is referred in scripts. Is an identifier, must be at least 3 characters long
  • nameLength (in, out) – holds the capacity of the name buffer (256 characters), must be set to the name's length
  • version (in, out) – the version of Shadron is passed as a three-digit value (e.g. 141 for version 1.4.1), however the value is 0 before version 1.4.1. Should be set to the extension's version number (currently ignored)
  • context (out) – may be set to a pointer that holds the extension's data. This pointer will be then passed back to the extension in all subsequent function calls
int shadron_unregister_extension(void *context);

Unregisters the extension before exiting Shadron. This should release all resources and free allocated data. The context argument is the pointer outputted by shadron_register_extension. It is passed to all subsequent functions and therefore will be omitted from this point onward.

Object parsing

This set of functions must be always implemented, apart from format decoding-only extensions.

int shadron_register_initializer(void *context, int index, int *flags, char *name, int *nameLength);

Registers an initializer name for the object types specified by flags. Will be called repeatedly with increasing values of index until it returns SHADRON_RESULT_NO_MORE_ITEMS.

  • index – the ordinal number of the initializer, starting at 0
  • flags (out) – a bitfield of the type or types of objects it may initialize. See flags above, only image, animation, export, and stream are valid
  • name – the buffer where to copy the initializer's name, by which it is recognized in scripts. Is an identifier, must be at least 3 characters long
  • nameLength (in, out) – holds the capacity of the name buffer (256 characters), must be set to the name's length
int shadron_parse_initializer(void *context, int objectType, int index, const char *name, int nameLength, void **parseContext, int *firstArgumentTypes);

Indicates that a previously registered initializer has been encountered, and the parsing of its arguments may begin.

  • objectType – the type of the object, see flags (exactly one bit will be set)
  • index – the ordinal number of the initializer, matching the one in shadron_register_initializer
  • name – the name of the initializer. Is an identifier
  • nameLength – the length of name
  • parseContext (out) – may be set to a pointer to store data for the duration of the initializer's argument parsing
  • firstArgumentTypes (out) – a bitfield that must be set to the set of possible types to expect as the first argument. A mismatch will trigger a parse error
    • SHADRON_ARG_NONE – there may be no more arguments (end of initializer otherwise means a parse error)
    • SHADRON_ARG_KEYWORD – a keyword specific to the argument, a null-terminated string. Is an identifier
    • SHADRON_ARG_FILENAME – a filename (the resolved absolute path), a null-teminated string in the extension's encoding
    • SHADRON_ARG_STRING – a raw null-teminated string in the extension's encoding
    • SHADRON_ARG_INT – an integer (single int value)
    • SHADRON_ARG_FLOAT – an floating point number (single float value)
    • SHADRON_ARG_BOOL – a boolean (single int value, either 0 or 1)
    • SHADRON_ARG_DIMENSIONS – integer width and height (two int values)
    • SHADRON_ARG_EXPR_INT – an integer expression (int expression index)
    • SHADRON_ARG_EXPR_FLOAT – a floating point expression (int expression index)
    • SHADRON_ARG_EXPR_BOOL – a boolean expression (int expression index)
    • SHADRON_ARG_EXPR_DIMENSIONS – a dimensions expression (int expression index)
    • SHADRON_ARG_SOURCE_OBJ – a source image or animation object (int object index, followed by an int with its type – see flags)
int shadron_parse_initializer_argument(void *context, void *parseContext, int argNo, int argumentType, const void *argumentData, int *nextArgumentTypes);

This is called for each matching argument encountered during initializer parsing.

  • parseContext – the parsing context pointer outputted by shadron_parse_initializer
  • argNo – the ordinal number of the argument, starting at 0
  • argumentType – the type of the argument, see above (exactly one bit will be set)
  • argumentData – a pointer to the argument value. The data type depends on the argument type (see above)
  • nextArgumentTypes (out) – a bitfield that must be set to the set of possible types to expect as the following argument
int shadron_parse_initializer_finish(void *context, void *parseContext, int result, int objectType, const char *objectName, int nameLength, void **object);

Finishes the parsing of the initializer. This function will be called even if the parsing has failed, which is indicated by result. It must always destroy the parse context, and create the object on success.

Note: No object must be created unless result equals SHADRON_RESULT_OK.

Note: Since scripts are often reloaded, which would result in periodic reconstruction of objects, it is recommended to use objectName to match an existing object and return it instead (if it has not changed), and implement some form of reference counting to facilitate proper disposal. This is possible because when reloading, object deletion will only take place after the script has been fully parsed.

  • parseContext – the parsing context pointer. This is the last time this pointer will be passed, so all associated resources should be released
  • result – the result of parsing the initializer (a result code)
  • objectType – the type of the object, matching the value in shadron_parse_initializer
  • objectName – the name of the object (not the initializer). Will be empty string for export/stream. Always has UTF-8 encoding
  • nameLength – length of object name
  • object (out) – should be set to a pointer which represents the constructed object
int shadron_parse_error_length(void *context, void *parseContext, int *length, int encoding);

Called whenever a parse error is encountered, this gives the extension the opportunity to display a custom parse error message. This initial call only outputs the length of the message so that a buffer may be allocated. On success, a call to shadron_parse_error_string will follow. If the extension does not have an error message available, it should instead return SHADRON_RESULT_NO_DATA, and a generic message will be shown.

  • parseContext – the parsing context pointer
  • length (out) – must be set to (at least) the length of the error message in physical characters (bytes for UTF-8, byte pairs for UTF-16)
  • encoding – the extension's encoding, as set in shadron_register_extension
int shadron_parse_error_string(void *context, void *parseContext, void *buffer, int *length, int bufferEncoding);

Must fill the buffer with the parse error message. Return SHADRON_RESULT_NO_DATA if no message is available.

  • parseContext – the parsing context pointer
  • buffer – the buffer for the error message, which must be filled with characters with the extension's declared encoding
  • length (in, out) – the capacity of the buffer as outputted by shadron_parse_error_length. If the actual message is in fact shorter, this value must be updated
  • bufferEncoding – the extension's (and buffer's) encoding, as set in shadron_register_extension

Object interaction

This set of functions must be always implemented, apart from format decoding-only extensions. Their second argument is always the object pointer outputted by shadron_parse_initializer_finish and therefore will be omitted.

int shadron_object_prepare(void *context, void *object, int *flags, int *width, int *height, int *format);

Must prepare the object after the script has been successfully loaded, and before it is first presented to the user. Also informs about the object's properties (flags, dimensions, pixel format). Won't be called for export and stream objects.

Note: The object's width and height must be between 1 and MAX_WIDTH or MAX_HEIGHT.

  • flags (in, out) – a bit field which contains flags for the preparation process, and must be updated to hold the object's properties
    • SHADRON_FLAG_FULL_RANGE (in, out) – full range modifier value / object property
    • SHADRON_FLAG_REPEAT (in) – animation repeat modifier value
    • SHADRON_FLAG_FILE_INPUT (out) – indicates that the object accepts files to load
    • SHADRON_FLAG_HARD_RESET (in) – indicates that the object should be reset completely to its initial state
  • width (in, out) – initially set to -MAX_WIDTH, must be set to the object's width
  • height (in, out) – initially set to -MAX_HEIGHT, must be set to the object's height
  • format (out) – the object's pixel format. May be one of:
    • SHADRON_FORMAT_RGBA_BYTE – 4-byte per pixel RGBA values, each channel between 0x00 and 0xff
    • SHADRON_FORMAT_RGBA_FLOAT – 16-byte per pixel single-precision floating point RGBA values, each channel between 0.0f and 1.0f (full range mode)
int shadron_object_size(void *context, void *object, int *width, int *height, int *format);

Must output the object's new dimensions and pixel format. This will be only called following a resize request. The arguments are initially set to the current values.

Note: The new width and height must be between 1 and MAX_WIDTH or MAX_HEIGHT.

  • width (in, out) – the object's width
  • height (in, out) – the object's height
  • format (in, out) – the object's pixel format (see formats above)
int shadron_object_load_file(void *context, void *object, const void *path, int pathLength, int pathEncoding);

Will be called if the user attempts to load a file into an object with the SHADRON_FLAG_FILE_INPUT flag. May return SHADRON_RESULT_OK_RESIZE to request a change of dimensions, or a SHADRON_RESULT_FILE_???_ERROR to indicate an error. On success, a pixel fetch will follow.

  • path – the absolute file path in the extension's declared encoding
  • pathLength – the length of path, in physical characters
  • pathEncoding – the extension's (and path's) encoding, as set in shadron_register_extension
int shadron_object_unload_file(void *context, void *object);

Similar to shadron_object_load_file, but must unload the current file instead.

int shadron_object_set_expression_value(void *context, void *object, int exprIndex, int exprType, const void *value);

Informs the object of the current value of an expression that has been passed as an argument of its initializer. Its value may change throughout the object's lifetime. May return SHADRON_RESULT_OK_RESIZE to request a change of dimensions, or SHADRON_RESULT_IGNORE to signify that the change did not affect the object's contents. Otherwise a pixel fetch will follow.

  • exprIndex – the expression index, as passed to shadron_parse_initializer_argument
  • valueType – the type of the value data (one of SHADRON_ARG_??? – excluding EXPR, see above)
  • value – pointer to the data that represents the expression value. See the list of argument types for interpretation
int shadron_object_offer_source_pixels(void *context, void *object, int sourceIndex, int sourceType, int width, int height, int *format, void **pixelBuffer, void **pixelsContext);

Offers the contents of a source image/animation object that has been passed as an argument of its initializer. This will be called every time the source is updated. May return SHADRON_RESULT_OK_RESIZE to request a change of dimensions, or SHADRON_RESULT_IGNORE to reject the offer. Otherwise, a call to shadron_object_post_source_pixels will follow.

  • sourceIndex – the source index, as passed to shadron_parse_initializer_argument
  • sourceType – the type of the source object (SHADRON_FLAG_IMAGE or SHADRON_FLAG_ANIMATION)
  • width – the width of the bitmap
  • height – the height of the bitmap
  • format (in, out) – the native pixel format of the bitmap. May be changed to a different one, if it is for example unsupported by the extension
  • pixelBuffer (out) – may be set to a pointer to a buffer on the extension's side, which will be populated with the pixels. Otherwise, a read-only buffer on Shadron's side will be provided
  • pixelsContext (out) – may be set to a pointer holding data associated with the pixel buffer, which will be passed back for deallocation
int shadron_object_post_source_pixels(void *context, void *object, void *pixelsContext, int sourceIndex, int plane, int width, int height, int format, const void *pixels);

Posts the pixels of a source image/animation object after shadron_object_offer_source_pixels has been accepted.

  • pixelsContext – the pointer set in shadron_object_offer_source_pixels
  • sourceIndex – the source index, matching the previous call to shadron_object_offer_source_pixels
  • plane – currently unused (must be 0)
  • width – the width of the bitmap
  • height – the height of the bitmap
  • format – the pixel format of the bitmap
  • pixels – the sequence of pixels (consecutive rows in bottom to top order, no padding)
int shadron_object_user_command(void *context, void *object, int command);

Informs the object about a user command.

  • command – code of the user command. Currently may be only:
    • SHADRON_COMMAND_RESTART – animation restart (R key)
int shadron_object_destroy(void *context, void *object);

Must destroy the object.

Object image retrieval

This set of functions must be impemented if the extension flags include SHADRON_FLAG_IMAGE or SHADRON_FLAG_ANIMATION.

int shadron_object_fetch_pixels(void *context, void *object, float time, float deltaTime, int realTime, int plane, int width, int height, int format, const void **pixels, void **pixelsContext);

Requests the object's pixels. On success, a pointer to a buffer containing the pixel data must be stored in the pixels argument. Another possible return code is SHADRON_RESULT_NO_DATA, indicating there is no image available at this moment, or SHADRON_RESULT_NO_CHANGE, indicating the image has not changed since the previous pixel fetch. If the result code is SHADRON_RESULT_OK, shadron_object_release_pixels will be called afterwards.

  • time – the current time (equal to shadron_Time)
  • deltaTime – the time difference from the previous frame (equal to shadron_DeltaTime)
  • realTime – indicates whether the animation is running in real time (0 or 1). If so, low response time is favored over precise timing
  • plane – currently unused (must be 0)
  • width – the width of the bitmap
  • height – the height of the bitmap
  • format – the format of the bitmap
  • pixels (out) – should be set to a pointer to the pixel buffer, which contains the sequence of width*height pixels of the requested format, bottom to top row, without padding
  • pixelsContext (out) – may be set to a pointer that holds data necessary to release any resources associated with the pixel buffer
int shadron_object_release_pixels(void *context, void *object, void *pixelsContext);

Called after shadron_object_fetch_pixels, once the outputted pixel data is no longer needed, this function may be used to free any memory / resources acquired in that call.

  • pixelsContext – the pixel buffer context outputted by shadron_object_fetch_pixels

Export control

This set of functions must be impemented if the extension flags include SHADRON_FLAG_EXPORT.

int shadron_object_start_export(void *context, void *object, int *stepCount, void **exportData);

Starts an export for the given export object and retrieves the number of steps. Only one export per each export object may run at any given time.

  • stepCount (out) – must be set to the number of steps of the export
  • exportData (out) – may be set to a pointer that holds data specific to this particular export. Will be passed back in subsequent calls
int shadron_export_prepare_step(void *context, void *object, void *exportData, int step, float *time, float *deltaTime, int *outputFilenameLength, int filenameEncoding);

Initializes each step of the export and retrieves the current time for this step. If a file is to be generated in the export step, its path must be retrieved by Shadron first, in order to ensure the existence of its directory, or ask the user's permission to overwrite. In such a case, the file name's length must be outputted first, and the name itself will be retrieved afterwards, with a call to shadron_export_output_filename.

  • exportData – the pointer to export data received from shadron_object_start_export
  • step – the ordinal number of the export step, starting at 0
  • time (out) – must be set to the time of the step, which will serve as shadron_Time for its duration
  • deltaTime (out) – must be set to the delta time of the step, which will serve as shadron_DeltaTime for its duration
  • outputFilenameLength (out) – if a file is to be generated, must be set to the length of its path in physical characters
  • filenameEncoding – reminds the extension of its declared string encoding used for the file path string
int shadron_export_output_filename(void *context, void *object, void *exportData, int step, void *buffer, int *length, int encoding);

Called after shadron_export_prepare_step if outputFilenameLength had been set to a positive value. Must fill the provided buffer with the absolute path to the output file, so that Shadron may establish the path or ask the user if it should be overwritten.

  • exportData – the pointer to export data received from shadron_object_start_export
  • step – the ordinal number of the export step, matching the value passed to shadron_export_prepare_step
  • buffer – the buffer where the file path's characters must be copied
  • length (in, out) – initially set to the buffer capacity (in physical characters), must be updated if the actual string ends up being shorter
  • encoding – the path's encoding as declared during extension registration
int shadron_export_step(void *context, void *object, void *exportData, int step, float time, float deltaTime);

Finishes the export step after it has been successfully prepared and all source objects' pixel data provided.

  • exportData – the pointer to export data received from shadron_object_start_export
  • step – the ordinal number of the export step, matching the value passed to shadron_export_prepare_step
  • time – the step time, as set by shadron_export_prepare_step
  • deltaTime – the step delta time, as set by shadron_export_prepare_step
int shadron_export_finish(void *context, void *object, void *exportData, int result);

Informs the export object that the export has finished, or has been interrupted. In either case, any memory or other resources held by exportData should be released.

  • exportData – the pointer to export data received from shadron_object_start_export
  • result – will be either SHADRON_RESULT_OK or SHADRON_RESULT_CANCELLED

Stream control

This set of functions must be impemented if the extension flags include SHADRON_FLAG_STREAM.

int shadron_object_start_stream(void *context, void *object, void **streamData);

Notifies the stream object that streaming has started. Only one stream per each stream object may run at any given time.

  • streamData (out) – may be set to a pointer that holds data specific to this particular stream. Will be passed back in subsequent calls
int shadron_stream_prepare_frame(void *context, void *object, void *streamData, int step, float time, float deltaTime);

Notifies the stream object that a new frame is being streamed and specifies its time.

  • streamData – the pointer to export data received from shadron_object_start_stream
  • step – the ordinal number of the stream step, starting at 0
  • time – the current shadron_Time
  • deltaTime – the current shadron_DeltaTime
int shadron_stream_stop(void *context, void *object, void *streamData);

Informs the stream object that streaming has stopped. Any memory or other resources held by streamData should be released.

  • streamData – the pointer to export data received from shadron_object_start_stream

Format decoding

This set of functions must be impemented if the extension flags include SHADRON_FLAG_IMAGE_DECODER or SHADRON_FLAG_SOUND_DECODER.

int shadron_decode_image(void *context, const void *rawData, int rawLength, int *width, int *height, int *format, void **decoderContext);

Requests the extension to attempt to decode an image stored as a sequence of bytes in memory. If the format is not recognized, unsupported, or contains errors, SHADRON_RESULT_FILE_FORMAT_ERROR should be returned swiftly. On success, the decoded pixels will be retrieved by shadron_decode_fetch_pixels afterwards.

  • rawData – the raw bytes of the image file
  • rawLength – number of bytes in rawData
  • width (out) – must be set to the image's width
  • height (out) – must be set to the image's height
  • format (out) – must be set to the output pixel format (see formats above)
  • decoderContext (out) – should be set to a pointer, through which the pixels will be retrieved
int shadron_decode_sound(void *context, const void *rawData, int rawLength, int *sampleRate, int *sampleCount, int *format, void **decoderContext);

Requests the extension to attempt to decode an audio stored as a sequence of bytes in memory. If the format is not recognized, unsupported, or contains errors, SHADRON_RESULT_FILE_FORMAT_ERROR should be returned swiftly. On success, the decoded audio samples will be retrieved by shadron_decode_fetch_samples afterwards.

  • rawData – the raw bytes of the sound file
  • rawLength – number of bytes in rawData
  • sampleRate (out) – must be set to the audio's sample rate (in whole Hertz)
  • sampleCount (out) – must be set to the number of the audio's samples
  • format (out) – must be set to SHADRON_FORMAT_STEREO_INT16LE
  • decoderContext (out) – should be set to a pointer, through which the audio samples will be retrieved
int shadron_decode_fetch_pixels(void *context, void *decoderContext, const void *rawData, int rawLength, void *pixelBuffer, int width, int height, int format);

Retrieves the pixels after a successful call to shadron_decode_image. Any allocated memory or resources associated with decoderContext should be released.

  • decoderContext – the decoder context pointer as set by shadron_decode_image
  • rawData – the raw bytes of the image file
  • rawLength – number of bytes in rawData
  • pixelBuffer – the buffer where the image's pixels should be copied, as consecutive rows in bottom to top order, with no padding
  • width – the bitmap width, as set by shadron_decode_image
  • height – the bitmap height, as set by shadron_decode_image
  • format – the bitmap format, as set by shadron_decode_image
int shadron_decode_fetch_samples(void *context, void *decoderContext, const void *rawData, int rawLength, void *sampleBuffer, int sampleCount, int format);

Retrieves the audio samples after a successful call to shadron_decode_sound. Any allocated memory or resources associated with decoderContext should be released.

  • decoderContext – the decoder context pointer as set by shadron_decode_sound
  • rawData – the raw bytes of the sound file
  • rawLength – number of bytes in rawData
  • sampleBuffer – the buffer where the audio should be copied, as a sequence of signed 16-bit interleaved stereo samples
  • sampleCount – the number of requested samples, as set by shadron_decode_sound
  • format – the audio format, as set by shadron_decode_sound
int shadron_decode_discard(void *context, void *decoderContext);

Called in case an unexpected problems occurs after a successful call to shadron_decode_image or shadron_decode_sound which prevents retrieval of decoded data. Any allocated memory or resources associated with decoderContext should be released.

  • decoderContext – the decoder context pointer received by shadron_decode_image or shadron_decode_sound