§ 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

Valid HTML 4.01 Loose
 

This manual was generated with wtfm
wtfm uses aa_macro and SqLite
aa_macro uses python 2.7
Please consider supporting my dTank (β) development efforts via a small PayPal donation.