Subversion Repositories filter_foundry

Rev

Rev 503 | Rev 536 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
210 daniel-mar 1
/*
268 daniel-mar 2
    This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
312 daniel-mar 3
    Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
503 daniel-mar 4
    Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft
210 daniel-mar 5
 
312 daniel-mar 6
    This program is free software; you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation; either version 2 of the License, or
9
    (at your option) any later version.
210 daniel-mar 10
 
312 daniel-mar 11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
210 daniel-mar 15
 
312 daniel-mar 16
    You should have received a copy of the GNU General Public License
17
    along with this program; if not, write to the Free Software
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
210 daniel-mar 19
*/
20
 
334 daniel-mar 21
/* Portions Copyright 1996 - 1999 Adobe Systems Incorporated */
22
/* All Rights Reserved.                                      */
210 daniel-mar 23
 
24
//#include <stdio.h>
25
 
26
//#include "world.h" // must come before Photoshop includes
27
 
28
#include "ff.h"
29
 
30
#include "scripting.h"
31
//#include "ui.h"
32
#include "dbg.h"
33
 
34
//extern FilterRecordPtr gpb;
35
 
217 daniel-mar 36
OSErr put_cstring(PIWriteDescriptor token, DescriptorKeyID key, char* s) {
37
        OSErr e;
38
        size_t n = strlen(s);
39
        Ptr p;
40
        Handle h = PINEWHANDLE((int32)n);
41
        p = PILOCKHANDLE(h, false);
42
        memcpy(p, s, n);
43
        PIUNLOCKHANDLE(h);
44
        e = PIPutText(token, key, h);
45
        PIDISPOSEHANDLE(h); /* Not 100% sure if we are supposed to dispose of handle. It doesn't crash though */
46
        return e;
210 daniel-mar 47
}
48
 
217 daniel-mar 49
char* get_cstring(PIReadDescriptor token) {
505 daniel-mar 50
        size_t n;
217 daniel-mar 51
        Ptr p;
52
        char* str = NULL;
53
        Handle h;
54
        OSErr e = PIGetText(token, &h);
210 daniel-mar 55
 
482 daniel-mar 56
        if ((e == noErr) && h) {
217 daniel-mar 57
                n = PIGETHANDLESIZE(h);
58
                p = PILOCKHANDLE(h, false);
59
                if ((str = (char*)malloc(n + 1))) {
60
                        memcpy(str, p, n);
61
                        str[n] = 0;
62
                }
63
                PIUNLOCKHANDLE(h);
64
                PIDISPOSEHANDLE(h); /* Not 100% sure if we are supposed to dispose of handle. It doesn't crash though */
65
        }
66
        return str;
210 daniel-mar 67
}
68
 
69
// If parm is NULL, then it is standalone, otherwise it is the main plugin
70
OSType getAeteKey(char c, PARM_T* parm) {
217 daniel-mar 71
        // To make our plugin compatible with AppleScript, each key must
72
        // be unique, since the namespace is global!
73
        // Furthermore, the "uniqueID/scope" hstm-field in the PIPL must be empty.
210 daniel-mar 74
 
217 daniel-mar 75
        if (parm != NULL) {
76
                unsigned long hash;
77
                char* data;
444 daniel-mar 78
                // char* debug = (char*)malloc(2000);
393 daniel-mar 79
                // sprintf(debug, "getAeteKey %c with title %s/%s in STANDALONE PLUGIN", c, parm->szTitle, parm->szCategory);
217 daniel-mar 80
                // simplealert(debug);
424 daniel-mar 81
                // free(debug);
210 daniel-mar 82
 
217 daniel-mar 83
                // Use random AETE keys, because AppleScript has a global namespace
84
                // and therefore requires unique AETE keys
85
                data = (char*)malloc(0x300);
86
                if (!data) return 0;
87
                sprintf(data, "%s %s %c",
393 daniel-mar 88
                        parm->szCategory,
89
                        parm->szTitle,
217 daniel-mar 90
                        c);
91
                hash = printablehash(djb2(data));
92
                free(data);
93
                return hash;
94
        }
95
        else {
444 daniel-mar 96
                // char* debug = (char*)malloc(2000);
217 daniel-mar 97
                // sprintf(debug, "getAeteKey %c in MAIN PLUGIN", c);
98
                // simplealert(debug);
424 daniel-mar 99
                // free(debug);
210 daniel-mar 100
 
217 daniel-mar 101
                // Attention: AETE keys (xpr#, cTl#) must be equal in scripting.r, scripting.rc and scripting.c(getAeteKey)!
102
                if (c == 'R') return 'xprR';
103
                if (c == 'G') return 'xprG';
104
                if (c == 'B') return 'xprB';
105
                if (c == 'A') return 'xprA';
106
                if ((c >= '0') && (c <= '9')) return 'cTl0' + (c - '0');
107
                return 0;
108
        }
210 daniel-mar 109
}
110
 
111
/* return true if dialog should be shown */
112
enum ScriptingShowDialog ReadScriptParamsOnRead(void)
113
{
217 daniel-mar 114
        PIReadDescriptor token;
115
        DescriptorKeyID key;
116
        DescriptorTypeID type;
117
        DescriptorKeyIDArray array = { NULLID };
118
        int32 flags;
119
        //OSErr stickyError;
120
        int32 v;
210 daniel-mar 121
 
217 daniel-mar 122
        if (DescriptorAvailable(NULL)) { /* playing back.  Do our thing. */
123
                token = OpenReader(array);
124
                if (token) {
125
                        while (PIGetKey(token, &key, &type, &flags)) {
126
                                if (key == getAeteKey('R', gdata->standalone ? &gdata->parm : NULL)) {
424 daniel-mar 127
                                        if (expr[0]) free(expr[0]);
217 daniel-mar 128
                                        expr[0] = get_cstring(token);
129
                                }
130
                                else if (key == getAeteKey('G', gdata->standalone ? &gdata->parm : NULL)) {
424 daniel-mar 131
                                        if (expr[1]) free(expr[1]);
217 daniel-mar 132
                                        expr[1] = get_cstring(token);
133
                                }
134
                                else if (key == getAeteKey('B', gdata->standalone ? &gdata->parm : NULL)) {
424 daniel-mar 135
                                        if (expr[2]) free(expr[2]);
217 daniel-mar 136
                                        expr[2] = get_cstring(token);
137
                                }
138
                                else if (key == getAeteKey('A', gdata->standalone ? &gdata->parm : NULL)) {
424 daniel-mar 139
                                        if (expr[3]) free(expr[3]);
217 daniel-mar 140
                                        expr[3] = get_cstring(token);
141
                                }
142
                                else {
143
                                        int i;
144
                                        for (i = 0; i <= 7; ++i) {
456 daniel-mar 145
                                                if (key == getAeteKey((char)('0'+i), gdata->standalone ? &gdata->parm : NULL)) {
217 daniel-mar 146
                                                        PIGetInt(token, &v);
453 daniel-mar 147
                                                        if (v < 0) v = 0;
456 daniel-mar 148
                                                        else if (v > 255) v = 255;
149
                                                        slider[i] = (uint8_t)v;
217 daniel-mar 150
                                                }
151
                                        }
152
                                }
153
                        }
210 daniel-mar 154
 
217 daniel-mar 155
                        /*stickyError =*/ CloseReader(&token); // closes & disposes.
210 daniel-mar 156
 
217 daniel-mar 157
                        // all Filter Foundry parameters are optional,
158
                        // so we needn't worry if any are missing
159
                }
210 daniel-mar 160
 
217 daniel-mar 161
                return gpb->descriptorParameters->playInfo == plugInDialogDisplay ? SCR_SHOW_DIALOG : SCR_HIDE_DIALOG;
162
        }
163
        else {
164
                return SCR_NO_SCRIPT;
165
        }
210 daniel-mar 166
}
167
 
168
OSErr WriteScriptParamsOnRead(void)
169
{
217 daniel-mar 170
        PIWriteDescriptor token;
171
        OSErr gotErr = noErr;
172
        extern int ctls[], maps[], nplanes;
173
        int i, allctls;
210 daniel-mar 174
 
217 daniel-mar 175
        if (DescriptorAvailable(NULL)) { /* recording.  Do our thing. */
176
                // 1. Call openWriteDescriptorProc which will return a PIWriteDescriptor token, such as writeToken.
177
                token = OpenWriter();
178
                if (token) {
179
                        // 2. Call various Put routines such as PutIntegerProc, PutFloatProc, etc., to add key/value pairs to writeToken. The keys and value types must correspond to those in your terminology resource.
210 daniel-mar 180
 
217 daniel-mar 181
                        // write keys here
182
                        if (!gdata->standalone) {
183
                                if (nplanes > 0) put_cstring(token, getAeteKey('R', gdata->standalone ? &gdata->parm : NULL), expr[0]);
184
                                if (nplanes > 1) put_cstring(token, getAeteKey('G', gdata->standalone ? &gdata->parm : NULL), expr[1]);
185
                                if (nplanes > 2) put_cstring(token, getAeteKey('B', gdata->standalone ? &gdata->parm : NULL), expr[2]);
186
                                if (nplanes > 3) put_cstring(token, getAeteKey('A', gdata->standalone ? &gdata->parm : NULL), expr[3]);
187
                        }
210 daniel-mar 188
 
217 daniel-mar 189
                        /* only write values for the sliders that are actually used! */
190
                        allctls = checksliders(4, ctls, maps);
191
                        for (i = 0; i <= 7; ++i) {
192
                                if (allctls || ctls[i]) {
456 daniel-mar 193
                                        PIPutInt(token, getAeteKey((char)('0'+i), gdata->standalone ? &gdata->parm : NULL), slider[i]);
217 daniel-mar 194
                                }
195
                        }
196
 
197
                        gotErr = CloseWriter(&token); /* closes and sets dialog optional */
198
                        /* done.  Now pass handle on to Photoshop */
199
                }
200
        }
201
        return gotErr;
210 daniel-mar 202
}
203
 
204
 
205
//-------------------------------------------------------------------------------
206
//
207
//      HostDescriptorAvailable
208
//
209
//      Determines whether the PIDescriptorParameters callback is available.
210
//
211
//      Check for valid suite version, routine suite version, and routine count.
212
//      Also check that the subset of routines we actually use is actually present.
213
//
214
//-------------------------------------------------------------------------------
215
 
403 daniel-mar 216
Boolean HostDescriptorAvailable(PIDescriptorParameters* procs, Boolean* outNewerVersion)
210 daniel-mar 217
{
403 daniel-mar 218
        if (procs == NULL) return FALSE; // Photoshop < 4.0 don't has scripting
219
 
217 daniel-mar 220
        if (outNewerVersion)
221
                *outNewerVersion = procs->descriptorParametersVersion > kCurrentDescriptorParametersVersion
222
                || procs->readDescriptorProcs->readDescriptorProcsVersion > kCurrentReadDescriptorProcsVersion
223
                || procs->writeDescriptorProcs->writeDescriptorProcsVersion > kCurrentWriteDescriptorProcsVersion;
210 daniel-mar 224
 
217 daniel-mar 225
        return procs != NULL
226
                && procs->descriptorParametersVersion == kCurrentDescriptorParametersVersion
210 daniel-mar 227
 
217 daniel-mar 228
                && procs->readDescriptorProcs != NULL
229
                && procs->readDescriptorProcs->readDescriptorProcsVersion == kCurrentReadDescriptorProcsVersion
230
                && (unsigned int)(procs->readDescriptorProcs->numReadDescriptorProcs) >= kCurrentReadDescriptorProcsCount
231
                && procs->readDescriptorProcs->openReadDescriptorProc != NULL
232
                && procs->readDescriptorProcs->closeReadDescriptorProc != NULL
233
                && procs->readDescriptorProcs->getKeyProc != NULL
234
                && procs->readDescriptorProcs->getTextProc != NULL
235
                && procs->readDescriptorProcs->getIntegerProc != NULL
210 daniel-mar 236
 
217 daniel-mar 237
                && procs->writeDescriptorProcs != NULL
238
                && procs->writeDescriptorProcs->writeDescriptorProcsVersion == kCurrentWriteDescriptorProcsVersion
239
                && (unsigned int)(procs->writeDescriptorProcs->numWriteDescriptorProcs) >= kCurrentWriteDescriptorProcsCount
240
                && procs->writeDescriptorProcs->openWriteDescriptorProc != NULL
241
                && procs->writeDescriptorProcs->closeWriteDescriptorProc != NULL
242
                && procs->writeDescriptorProcs->putTextProc != NULL
243
                && procs->writeDescriptorProcs->putIntegerProc != NULL;
210 daniel-mar 244
}
245
 
246
 
247
//-------------------------------------------------------------------------------
248
//
249
//      HostCloseReader
250
//
251
//      Closes a read token, disposes its handle, sets the token to NULL, and
252
//      sets the parameter blocks' descriptor to NULL.
253
//
254
//      The Descriptor Parameters suite are callbacks designed for
255
//      scripting and automation.  See PIActions.h.
256
//
257
//      Inputs:
258
//              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
259
//
260
//              HandleProcs *hProcs                             Pointer to HandleProcs callback.
261
//
262
//              PIReadDescriptor *token                 Pointer to token to close.
263
//
264
//              procs->descriptor                               Pointer to original read handle.
265
//
266
//      Outputs:
267
//              PIReadDescriptor *token                 Set to NULL.
268
//
269
//              procs->descriptor                               Disposed then set to NULL.
270
//
271
//              returns OSErr                                   noErr or error if one occurred.
272
//
273
//-------------------------------------------------------------------------------
274
 
217 daniel-mar 275
OSErr HostCloseReader(PIDescriptorParameters* procs,
276
        HandleProcs* hProcs,
277
        PIReadDescriptor* token)
210 daniel-mar 278
{
217 daniel-mar 279
        // Close token:
280
        OSErr err = procs->readDescriptorProcs->closeReadDescriptorProc(*token);
210 daniel-mar 281
 
217 daniel-mar 282
        // Dispose the parameter block descriptor:
283
        hProcs->disposeProc(procs->descriptor);
210 daniel-mar 284
 
217 daniel-mar 285
        // Set the descriptor and the read token to NULL:
286
        procs->descriptor = NULL;
287
        *token = NULL;
210 daniel-mar 288
 
217 daniel-mar 289
        return err;
210 daniel-mar 290
 
291
} // end HostCloseReader
292
 
293
//-------------------------------------------------------------------------------
294
//
295
//      HostCloseWriter
296
//
297
//      Closes a write token, stores its handle in the global parameter block for
298
//      the host to use, sets the token to NULL, and sets the recordInfo to
299
//      plugInDialogOptional (the default).
300
//
301
//      The Descriptor Parameters suite are callbacks designed for
302
//      scripting and automation.  See PIActions.h.
303
//
304
//      Inputs:
305
//              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
306
//
307
//              HandleProcs *hProcs                             Pointer to HandleProcs callback.
308
//
309
//              PIWriteDescriptor *token                Pointer to token to close and pass on.
310
//
311
//              procs->descriptor                               Should be NULL.  If not, its contents
312
//                                                                              will be disposed and replaced.
313
//
314
//      Outputs:
315
//              PIWriteDescriptor *token                Set to NULL.
316
//
317
//              procs->descriptor                               Set to descriptor handle.
318
//
319
//              returns OSErr                                   noErr or error if one occurred.
320
//
321
//-------------------------------------------------------------------------------
322
 
217 daniel-mar 323
OSErr   HostCloseWriter(PIDescriptorParameters* procs,
324
        HandleProcs* hProcs,
325
        PIWriteDescriptor* token)
210 daniel-mar 326
{
217 daniel-mar 327
        OSErr err = noErr; // assume no error
328
        PIDescriptorHandle h = NULL;
210 daniel-mar 329
 
217 daniel-mar 330
        if (procs->descriptor != NULL) // don't need descriptor passed to us
331
                hProcs->disposeProc(procs->descriptor); // dispose.
210 daniel-mar 332
 
217 daniel-mar 333
        // 3. Call CloseWriteDescriptorProc with writeToken, which will create a PIDescriptorHandle.
334
        procs->writeDescriptorProcs->closeWriteDescriptorProc(*token, &h);
210 daniel-mar 335
 
217 daniel-mar 336
        // 4. Place the PIDescriptorHandle into the descriptor field. The host will dispose of it when finished.
337
        procs->descriptor = h;
210 daniel-mar 338
 
217 daniel-mar 339
        // 5. Set recordInfo.  Options are: plugInDialogOptional,
340
        // plugInDialogRequire, plugInDialogNone:
341
        procs->recordInfo = plugInDialogOptional;
210 daniel-mar 342
 
217 daniel-mar 343
        *token = NULL;
344
 
345
        return err;
346
 
210 daniel-mar 347
} // end HostCloseWriter