Developer

The External Unit API allows anyone to design their own unit and use it within Alchemy.

Introduction

What makes these External Units "external", is that the internal logic is not performed within the main binary of Alchemy. Instead, Alchemy starts a separate executable for each unit. Alchemy will send this executable event data (eg. this button was pushed, that port received this data, etc) and it can send commands back to Alchemy (eg. activate this light, send this data through that port, etc)

The executable can be written in any language, all that matters is that it is capable of receiving data from STDIN, and sending data though STDOUT.

There are two main parts to an External Unit; the description file and the executable.

The Unit Description File

As the name suggests - this is used to describe the design of the unit. What components go where, how they look, etc. It also contains the name of the unit, its selection space and the path to the executable to use.

See here, for a in-depth description of the Unit Description File

The Executable

The executable is a user defined program which is used as the internal logic of the unit. All executables are run on their own threads, and thus operate asynchronously from the Alchemy. Alchemy communicates with these executables through the stdio, using a JSON format. The executable should be able to receive information as a series of events and can send at any time commands for Alchemy to execute. The executable is otherwise a regular program and can perform network actions, file actions or interface with another external system as usual.

Important Concepts

Import / Export (Exportable Data)

At some point during the program a user might decide to copy-and-paste your unit. We therefore want some way to clone a unit so that the pasted one is exactly the same as the copied one. A lot of this process is already handled by Alchemy, but the internal configuration is left up to the designer of the unit to handle. This is where the "Import/Export" interface comes in.

During the process of copying a unit, Alchemy will collect all relevant information (unit type, position, connections, etc.) and also collect the unit's "exportable" data. "exportable" data is data held in Alchemy on a per-unit basis, which can be updated using the "UpdateExportableData" command. Upon pasting, Alchemy creates the unit then runs the "import" method providing the same "exportable" data that was collected before.

Alchemy only stipulates that this data is a string, meaning that any format can be used so long as it is representable in string form. The collection and encoding of this data and the updating of the Alchemy held "exportable" data is the responsibility of the unit's designer, as is the correct decoding and distribution of this data.

The same "Import/Export" system is also used for saving/loading a project file.

Undo / Redo (Modifications)

One action a user might perform is an attempt to undo or redo an action. Similar to the Import / Export section above much of this process is handled by Alchemy, but aspects related to the configuration of a unit is left to the designer of that unit.

In order to not have to save the entire configuration for every single action, a "Modification" concept is used instead. The idea is that if a designer wishes that a certain action be "undoable", then the performance of that action should return a "modification" object, which contains information on what aspect of the configuration was changed, and what the before and after of that aspect was.

Similar to Export/Import, Alchemy only stipulates that the data stored in a Modification object is a string, meaning that any format can be used so long as it is representable in string form. The collection and encoding of this data is the responsibility of the unit's designer, as is the correct decoding and distribution of this data when an Undo or Redo event occurs.

This "modification" is stored and managed by Alchemy. When a user activates the "undo" function, Alchemy runs the "undo" method of the unit, providing the "modification" object. If the user activates the "redo" function, Alchemy runs the "redo" method of the unit and provides the "modification" object.

If a unit has not returned a modification for an action by the time a user attempts to "undo" or "redo" it; then the next modification in the undo/redo timeline is used instead, voiding the unit's opportunity to provide a modification for this action.