§ 13.8 - developer.h
// developer.h
// -----------
// NOTE: Set your tabstops to every 4 columns for proper display
// Developer Interface
// ===================
#define PLUG_VERSION 1 // so far, the only version out there
// DTank is able to handle plugins as if they were native effects when
// saving, loading and processing files because each effect, plugin or
// internal, has its own unique codes that distinguish its settings and
// processes from those of any other plugin.
//
// We enforce these distinct conditions by requiring each developer to
// obtain from us unique codes that identify the specific plugins. We don't
// charge for providing the codes, or concern ourselves overly with exactly
// what it is your plugin does (even if it duplicates functionality already
// in DTank); the primary issue we're concerned with is ensuring that each
// plugin is able to distinctly and definitively identify itself.
//
// You can develop and test a plugin anonymously; plugins developed without
// the required codes will run for seven days after they were most recently
// compiled. Should that time expire, just recompile the plugin. This
// ensures that you can engage in a long development process without
// worrying about getting the codes or contacting us at all.
//
// But when the time comes to distribute that plugin, you will have to
// contact us for the codes you need. Please use the form letter below,
// adjusting it as is appropriate for your needs:
// ---------------------------------------------------------------------------
// to email: fyngyrz@gmail.com
//
// subject: Request unique developer ID, roles and keycodes.
// body:
// ---------------------------------------------------------------------------
// I/we are developing for your software. Please supply a unique developer
// ID in the name of [name] along with [a/X] unique layer role(s) and
// keycode(s) for our (X) planned plugin(s), which will add [explain] features.
// ---------------------------------------------------------------------------
//
// Developing more plugins, later? Use this:
//
// ---------------------------------------------------------------------------
// to email: fyngyrz@gmail.com
//
// subject: Request additional roles and keycodes.
// body:
// ---------------------------------------------------------------------------
// I/we (developer ID #X, already registered as "Your Name Here") are
// developing (an) additional plugin(s) for your software. Please supply
// [a/X] additional unique layer role(s) and keycode(s) for our (X) planned
// plugin(s), which will add [explain] features.
// ---------------------------------------------------------------------------
struct name
{
char n[20]; // name up to 19 char plus terminating zero. Do NOT exceed this size.
};
// struct plugin
// ================
// This structure is what you fill in to define how your plugin will appear
// to the end user, what controls you need, and how to handle issues like
// threading and processing phases when we execute your plugin.
//
// When we call your plugin for you to fill in this strcture, we'll pass a
// pointer to your plugin struct, in which we have set most values to 0,
// the floats to ranges of 0.0f...100.0f with defaults of 50.0f, and the
// developer information to the anonymous defaults.
//
// You, in turn, then need only set those values that define what your
// plugin needs; most values can be left unchanged by most plugins.
//
struct plugin
{ // This is basic plugin ID stuff that only has to be set when you're
// ready to distribute. See the comments just below for details on
// how exactly to set them.
// ----------------------------------------------------------------
long developer; // assigned developer ID
char key[40]; // plugin key
char name[80]; // developer name the above ID was issued to
long layer_role; // assigned layer role
// You MUST add these four lines, using your own information, when you are ready to
// distribute your plugin. Without these four lines, the above variables default to
// settings that expire the plugin 7 days after the date specified in the plugin struct.
// -------------------------------------------------------------------------------------
// strcpy(p->name,"Developer Name"); // name dev ID was issued to (MaTcH cAsE!)
// p->developer = 0; // your dev ID number (not 0!)
// strcpy(p->key,"1234-5678-9012-3456"); // your dev key (not this number!)
// p->layer_role = 0; // your layer role (not 0!)
long plugversion; // version of plugin structure (we supply this)
// This date setting is IMPORTANT. The plugin will not work until this date
// arrives. Also, if you have not set developer, name and key, the plugin
// will STOP working seven days after this date. This prevents unregistered
// plugins from working in the wild and colliding with each other's settings
//
// The build SH script we supply sets these fields for you AUTOMATICALLY in
// the example plugin, which we hope you'll use as a model for your own
// scripts, makefiles and so on. Finally, make sure you use a unique filename
// for the final .so plugin file so it doesn't over-write someone else's.
// -------------------------------------------------------------------------
long year; // year plugin was last compiled [2011...]
long month; // month plugin was last compiled [1-12]
long day; // day plugin was last compiled [1-31]
// layer_pri determines where in the image processing order your plugin
// executes. What priority to use depends on what type of plugin you have.
//
// Higher priorities execute first.
//
// One consideration is for overlays you don't expect (or want) the
// user to process. For instance, an image matte. This should be placed
// above the histogram (which is at 5000) so that the histo won't count colors
// from it, and also so that all effects are applied to the layers below, and
// not the matte itself. Our Matte plugin is set to 5500, while the badge
// function runs at 5000. This ensures that the mattes render first, then the
// badges overlay the mattes, and that neither one is affected by the underlying
// image processing which has already rendered against the underlying content.
//
// --------------------------------------------------------------------------
long layer_pri; // position in layer stack
struct name panel; // name of this panel (you supply this, 19 ch max)
// Threading and Phase Management
// ==============================
//
// Preprocessing engine:
// ---------------------
// Your preprocessing engine will be called in from one to 32 phases,
// numbered zero to 31. The default is one phase. You need to specify how
// each phase is to be run, unless you just want one phase that isn't
// threaded.
//
// If you want your the preprocessor of your plugin to be multithreaded,
// then set pthread[phase]=1. In that case, we'll call your pengine()
// multiple times with subranges in different threads. If your pengine() is
// an empty procedure, do NOT set pthread[phase]=1; it'll get out of the
// way faster just being called one time.
//
// If you'd like us to call it in phases, for instance because you need to
// process the layers more than once, then set pphase to 2 or more. 1 is
// the same as zero; you'll only be called once.
//
// Regardless of if you're threaded or not, you need to tell the system if
// you want to be phased, and what kind of range you'll be preprocessing.
// There are three available choices for ranges.
//
// Leaving prange_method[phase]=0 will call pengine(start,finish) with
// values that represent the image as a single dimension of pixels; for
// instance, if the image is 100x100, start,finish will be 0,10000 or
// subranges thereof if threading. This makes for very easy processing if
// the XY position of the pixels are irrelevant to your effect.
//
// Setting prange_methods[phase]=1 will call pengine(start,finish) with
// values that represent y scan lines. In the case of the 100x100 image,
// start,finish will be 0,100 or subranges thereof if threading. This
// allows you to build geometrically-aware processing loops; the call gives
// you the Y range, and you process across the x dimension using the x
// value in the plug structure to control an x processing subloop.
//
// Setting prange_method[phase]=2 will call pengine(start,finish) with the
// custom range (or subranges thereof if threading) you set with
// pstart[phase] and pfinish[phase]. You would only process start to
// finish-1.
//
// Observe the phase variable in the plug struct
// to determine what the current phase is when called if pphase > 1.
// ---------------------------------------------------------------------
long pphase; // how many total phases for pengine()
long pthread[32]; // 1 if you'd like pengine() threaded
long prange_methods[32]; // 0 is image size, no dims; 1 is by Y scans...
long pstart[32]; // ...2 uses vars, a custom range passed to
long pfinish[32]; // ...pengine() as start[phase], finish[phase]
// Display engine:
// ---------------
// Your display engine will be called in from one to 32 phases, numbered
// zero to 31. The default is one phase. You need to specify how each phase
// is to be run if you wish to be called more than once or you would like
// to have the calls threaded.
//
// If you want a particular phase phase of the rendering engine of your
// plugin to be multithreaded, then set dthread[ThatPhase]=1. In that case,
// we'll call your dengine() with subranges in different threads during
// that phase.
//
// If you'd like us to call your dengine() procedure in phases, for
// instance because you need to process the layers more than once, then set
// dphase to 2 or more. 1 is the same as zero; you'll only be called once.
//
// Regardless of if you want threading or not, you need to tell the system
// if you want more than one execution phase, and if you don't want the
// dimsionless default range, what kind of range(s) you want to process.
// There are three choices.
//
// Leaving drange_methods[phase]=0 will call dengine(start,finish) with
// values that represent the image as a single dimension of pixels; for
// instance, if the image is 100x100, start,finish will be 0,10000 or
// subranges thereof if threading. This makes for very easy processing if
// XY position of the pixels are irrelevant to your effect.
//
// Setting drange_method[phase]=1 will call dengine(start,finish) with
// values that represent y scan lines. In the case of the 100x100 image,
// then start,finish will be 0,100 or subranges thereof if threading. This
// allows you to build geometrically-aware processing loops; the call gives
// you the Y range, and you process across the x dimension using the x
// value in the plug structure to control the x processing subloop.
//
// Setting drange_method[phase]=2 will call dengine(start,finish) with the
// custom range (or subranges thereof if threading) you set with
// pstart[phase] and pfinish[phase]. You would only process start to
// finish-1. This is not a commonly used mode for dengine(), since you
// always have to handle the whole image.
//
// Observe the phase variable in the plug struct to determine what the
// current phase is.
// ---------------------------------------------------------------------
long dphase; // how many phases for dengine()
long dthread[32]; // 1 if you'd like your dengine threaded
long drange_methods[32]; // 0 is image size, no dims; 1 is by Y scans
long dstart[32]; // Passed to your dengine() in the start...
long dfinish[32]; // ...and finish parms when drange_method[x]=2
// alpha management. if req_alpha=1, you always want an alpha channel.
// ---------------------------------------------------------------------
long req_alpha; // 1 if your plugin wants an image alpha channel
// The following two variables give you some flexibility with regard to how
// alpha channels are used and/or allocated. if you request an alpha
// channel and set allow_paint=1, then the user will be able to paint on
// the channel, even though you may have set up some alpha yourself. In
// this case, we will save the alpha channel with the image.
//
// If you request an alpha channel but set allow_paint=0, the alpha is
// essentially private to you (and it will never be saved.)
//
// If you don't request an alpha channel by setting req_alpha=0,
// allow_paint is ignored.
//
// But on the other hand, if you set req_alpha=0 and promotable=1, then the
// user can ADD an alpha channel, and paint on it, which in turn will
// moderate how your effect is applied to the image and we'll save that
// alpha channel for the user. This will allow the user to mix your effect
// in according to the painted detail in the alpha channel.
//
// We encourage this particular mechanism, though we understand that it is
// not always practical in cases where the alpha channel is part of the
// effect itself.
//
// Alpha channels are always the same size as the image being processed.
// For each 16-bit alpha value corresponding to an RGB pixel in the image,
// 0 is fully transparent, and 65535 is fully opaque. You can have an alpha
// channel w/o having any other layer channels.
// --------------------------------------------------------------------------------------------
long allow_paint; // 1 if you want users to be able to paint on your alpha channel
long promotable; // 1 means user can request paintable version, ADDING an alpha channel
// Layer management. Your effect may use no layers, or from 1 to 4 layers,
// NOT counting an alpha channel. These layers are used to hold
// pre-computed information that is generated in response to a user
// setting a slider, checkmark or button. You generate this information when we
// call your pengine() function. These layers are to be used to lighten the
// load on your dengine() function. There are many variations of how that
// may be accomplished. They are nominally 16bit channels, meaning that if
// the size you specify is 100, you get 200 bytes of memory in the channel.
//
// The way these variables work is; you have to request layers in the order
// lr, lg, lb. Despite the names, you don't have to use them for red, green
// and blue -- use is up to you. These are just names. So if you want one
// layer of size 100 bytes, you set req_lr = 50 (remember, 16-bit channels.)
// Because you didn't ask for lg, you *can't* ask for lb; the req_lb variable
// will be ignored. If you want two layers of 32768 16-bit values, set: req_lr=32768,
// and req_lg=32768. 0 (the default) and -1 are special values; 0 means, you don't
// get this layer or any more layers beyond it. -1 means, you get the layer
// and it will be the size of the image being processed. Whenever you say
// "I want this layer", either by specifying the size explicitly, or by
// putting a -1 in there, that's when the next layer becomes available to
// ask for. Remember these sizes are 16-bit, or two bytes per unit.
// --------------------------------------------------------------------------
long req_lr; // if 0, no chans. -1=image size, >0 = lr size (def: 0)
long req_lg; // if req_lr != 0, set 0 or -1 or >0 for lg size (def: 0)
long req_lb; // if req_lg != 0, set 0 or -1 or >0 for lb size (def: 0)
long req_lx; // if req_lb != 0, set 0 or -1 or >0 for lx size (def: 0)
// UI slider management. Your effect may utilize from zero to 8 sliders, with
// floating point ranges you specify. When you set a specific number, the
// variables in the arrays above the number are ignored. For instance, if you
// request two sliders, then only array entries 0 and 1 are used in each of
// the setup arrays here, and in each of the f[x] arrays in the plug struct
// sent to your plugin at execution time. Because of this, entries 2-7 don't
// need to be set here, and entries 2-7 in the plug structure are unused.
// --------------------------------------------------------------------------
long slider_req; // from 0-8 sliders you request (default: 0)
struct name sliders[8]; // the names of the sliders
float svalues[8]; // the initial values of the sliders (default: 50.0f)
float avalues[8]; // the low limits of the sliders (default: 0.0f)
float zvalues[8]; // the high limits of the sliders (default: 100.0f)
float ivalues[8]; // Option-click increment of slider (default 0.01f)
long fresolution[8]; // 0= xx.xx (2-decimal float); 1= XbyX (for square regions); 2= xx (integer)
long forder[8]; // unique ints that control positioning, see below
long ticks[8]; // 0 is no ticks. 3 is one at zero, one at 50%, and one 100%
long swidth[8]; // width of slider in pixels (we set to 200)
// UI checkmark management. Your effect may utilize from zero to 8 checkmarks.
// if you request 3, then only array entries 0-2 are valid both here and in
// the plug structure. Because of this, entries 3-7 don't need to be set, and
// entries 3-7 in the plug structure are unused.
// ---------------------------------------------------------------------------
long check_req; // from 0-8 checkmarks you request (default 0)
struct name checks[8]; // the names of the checkmarks
long cvalues[8]; // 1==checked, 0=not checked
long corder[8]; // unique ints that control positioning, see below
long cwidth[8]; // width of checkmark in pixels (we set to 18)
// UI button management. Your effect may utilize from zero to 8 buttons.
// if you request 4, then only array entries 0-3 are valid both here and in
// the plug structure. Because of this, entries 4-7 don't need to be set,
// and entries 4-7 in the plug structure are unused.
// --------------------------------------------------------------------
long button_req; // from 0-8 buttons you request (default: 0)
struct name buttons[8]; // the names on the buttons
long btypes[8]; // 0=momentary, 1 = bistable
long bvalues[8]; // 1==pressed, 0=not pressed
long border[8]; // unique ints that control positioning, see below
long bwidth[8]; // width of button in pixels
long well_req; // color wells struct name wells[8]; // names p->wells[x].n[0]=0; // means no label!
// strcpy(p->wells[x].n,"Label"); // sets label
long worder[8]; // unique ints that control positioning, see below
unsigned long red[8]; // color components
unsigned long green[8]; // ...
unsigned long blue[8]; // ...
// For the Future
// --------------
void *extension; // future enhancements will go here. NULL in plugversion 1
};
// Positioning Controls
// --------------------
// We're tried to make this easy, but as there are lots of ways positioning
// can be approached, most likely the explanation will be tougher than the
// actual work. Sorry about that!
//
// Basically, you can't fit very many controls across a panel, because the
// panels aren't very wide. How many you can fit essentially depends on how
// wide the controls are, and what controls they are. Buttons may be much
// smaller than sliders, for instance.
//
// We've given you a mechanism that will allow you to arrange the controls
// in any order you like, given that they will fit the way you specifiy
// them.
//
// Here's how it works. We're quite sure you can't fit ten controls in a
// single line of controls on one of our panels. With that in mind, we set
// it up so that the number 0-99 defines the left-to-right order of
// placement within a line; and the hundreds value (0, 100, 200, 300 and so on)
// controls which line the control is to be placed upon.
//
// Clear? No, probably not. So let's work through an example. Let's say
// that your plugin has two sets of checkmarks, buttons, and sliders. You
// want them to appear ordered like this on your plugin's panel:
//
// button ----slider---- [x]
// button ----slider---- [x]
//
// Ok, so the buttons are first. And there are two, so we need to set the
// first two values of border[] like this:
//
// border[0] = 0+0; // line 0, left to right position 0.
// border[1] = 100+0; // line 1, left to right position 0.
//
// Now we do the sliders:
//
// forder[0] = 0+26; // line 0, left to right postioned at 26%.
// forder[1] = 100+26; // line 1, left to right positioned at 26%.
//
// And finally the checkmarks:
//
// corder[0] = 0+80; // line 0, left to right position 80%
// corder[1] = 100+80; // line 1, left to right position 80%
//
// struct plug
// ==============
// This structure is handed to your pengine() and dengine() functions. It
// contains everything needed to precalculate your layer content with
// pengine(), if your plugin can use that, and to render the image with
// dengine().
//
struct plug
{
// These are the X and Y dimensions of the image
// ---------------------------------------------
long x; // width of 16-bit image buffers and alpha channel
long y; // height of 16-bit image buffers and alpha channel
// These tell you how to process your image; they are saved with the version
// They represent the settings of any user controls you requested in setup()
// -------------------------------------------------------------------------
float f[8]; // the slider values the user has set
long c[8]; // the checkmark values the user has set
long b[8]; // the buttons that are currently pressed
unsigned long red[8]; // red components of the eight colors...
unsigned long grn[8]; // ...green...
unsigned long blu[8]; // ...blue
// this tells you what phase you are in
// ------------------------------------
long phase; // which phase is this (if using phased code)
// These channels are always available to you.
// -------------------------------------------
unsigned short *mr; // RGB image incoming to you. You must not modify these
unsigned short *mg; // ...in pengine(), but you can in dengine(). All 3 are
unsigned short *mb; // ...always x wide and y high by 16 bits per channel
unsigned short *sr; // Effected image result you MUST produce in dengine(). In
unsigned short *sg; // ...pengine(), you can use these as scratch buffers.
unsigned short *sb; // ...always x wide and y high by 16 bits per channel
// ...note they will be destroyed before dengine() is called
// ...meaning they won't carry anything you did in pengine()
// ...forward to dengine(). Only the below layers can do that.
// These channels are available IF you asked for them in setup,
// and they are sized according to your request.
// ------------------------------------------------------------
unsigned short *lr; // layer(s) for your calculated data, if you asked for any.
unsigned short *lg; // ...these are for precalculating anything you can for your
unsigned short *lb; // ...layer engine and are NOT saved. We only save floats,
unsigned short *lx; // ...buttons, checks and paintable alpha.
// If not NULL, there is an image-sized alpha channel.
// ---------------------------------------------------
unsigned short *la; // alpha channel, if requested or promoted, otherwise NULL.
// Paintable alphas ARE saved.
// For the Future
// --------------
void *extension; // future enhancements will go here. NULL in plugversion 1
};
// Service Requests
// ----------------
// Services are delivered in a pkg structure when you request them using an req
// structure. You fill in the req code, call service() with a pointer to the
// req structure as the parameter, and you get a pkg structure pointer back.
// You check the return code for pkg->response == SVC_OK, and if true, then
// the service was performed, whatever it was. The demo plugin shows the
// sequence in both the init() and cleanup() phases.
// set req->p1 = pointer to char string for status line
// ----------------------------------------------------
#define REQ_STATUS 1
// Set p1 to point to a structure holding anything you want kept across
// your execution. This would typically be a structure that holds pointers
// to memory you allocated, variables, etc., that you want to exist across
// your entire execution. You can always get the correct pointer for the
// context you are running in by calling service() with REQ_THIRSTYNOW. In
// this way, your plugin can remain stateless internally, because we'll
// manage it for you. You cannot keep information inside the plugin across
// calls -- you MUST keep it in a structure we keep for you this way
// remember: We may be running multiple copies of multiple plugins all at
// one time, under multiple threads: so don't try to get around this. It
// only leads to Doom. DOOM, I tell you.
// -----------------------------------------------------------------------------------
#define REQ_HOLDMYBEER 2
// get your pointer back in p1 of pkg struct
// -----------------------------------------
#define REQ_THIRSTYNOW 3
// Get memory of size in v1 parameter
// If the response is SVC_FAIL, then
// we were unable to allocate the
// memory for you. Sorry.
// ----------------------------------
#define REQ_MEMORY 4
// Free memory pointed to by p1 parameter
// Note that if you don't free memory you
// allocate, we will do it for you when
// your plugin returns from cleanup(),
// as long as you use REQ_MEMORY to get
// the memory in the first place (which
// we HIGHLY recommend!)
// --------------------------------------
#define REQ_FREE 5
// provide the average of the RGB color
// last taken with the eyedropper. If
// the response is SVC_FAIL, then no
// eyedropper sample has been taken of
// this image yet.
// ------------------------------------
#define REQ_EYEDROP 6
// provide the position last clicked
// upon within the image boundaries. If
// the response is SVC_FAIL, then no
// click has been made within this image
// yet.
// ------------------------------------
#define REQ_EYEXY 7
// If your plugin isn't going to change the
// image much or process the entire thing,
// one quick trick is to swap the buffer
// pointer roles; this effectively instantly
// renders the entire image for you. Now,
// instead of writing to the sr,sg and sb
// channels, make your small changes to the
// mr,mg and mb channels and you're done.
// -----------------------------------------
#define REQ_SWAP 8
struct req
{
long svc; // put REQ_ codes here
void *p1; // parameters here as requred by request...
void *p2; // ...
long v1; // ...
long v2; // ...
long v3; // ...
};
// Service responses:
// ------------------
#define SVC_OK 0
#define SVC_UNKNOWN 1
#define SVC_FAIL 2
struct pkg
{
long response; // service will tell you what happened here
void *p1; // various things come back in these parameters...
void *p2; // ...
long v1; // ...
long v2; // ...
long v3; // ...
};
// These defines solve a problem with the date command outputting leading zeros on months
// --------------------------------------------------------------------------------------
#define X01 1
#define X02 2
#define X03 3
#define X04 4
#define X05 5
#define X06 6
#define X07 7
#define X08 8
#define X09 9
#define X10 10
#define X11 11
#define X12 12
Keyboard Navigation
, Previous Page
. Next Page
t TOC
i Index
o Operators
g Glossary
This manual was generated with wtfm
wtfm uses aa_macro and SqLite
aa_macro uses python 2.7