Subversion Repositories filter_foundry

Rev

Rev 424 | Rev 453 | 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
4
    Copyright (C) 2018-2021 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) {
50
        int n;
51
        Ptr p;
52
        char* str = NULL;
53
        Handle h;
54
        OSErr e = PIGetText(token, &h);
210 daniel-mar 55
 
217 daniel-mar 56
        if (!e && h) {
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) {
145
                                                if (key == getAeteKey('0' + i, gdata->standalone ? &gdata->parm : NULL)) {
146
                                                        PIGetInt(token, &v);
147
                                                        slider[i] = v;
148
                                                }
149
                                        }
150
                                }
151
                        }
210 daniel-mar 152
 
217 daniel-mar 153
                        /*stickyError =*/ CloseReader(&token); // closes & disposes.
210 daniel-mar 154
 
217 daniel-mar 155
                        // all Filter Foundry parameters are optional,
156
                        // so we needn't worry if any are missing
157
                }
210 daniel-mar 158
 
217 daniel-mar 159
                return gpb->descriptorParameters->playInfo == plugInDialogDisplay ? SCR_SHOW_DIALOG : SCR_HIDE_DIALOG;
160
        }
161
        else {
162
                return SCR_NO_SCRIPT;
163
        }
210 daniel-mar 164
}
165
 
166
OSErr WriteScriptParamsOnRead(void)
167
{
217 daniel-mar 168
        PIWriteDescriptor token;
169
        OSErr gotErr = noErr;
170
        extern int ctls[], maps[], nplanes;
171
        int i, allctls;
210 daniel-mar 172
 
217 daniel-mar 173
        if (DescriptorAvailable(NULL)) { /* recording.  Do our thing. */
174
                // 1. Call openWriteDescriptorProc which will return a PIWriteDescriptor token, such as writeToken.
175
                token = OpenWriter();
176
                if (token) {
177
                        // 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 178
 
217 daniel-mar 179
                        // write keys here
180
                        if (!gdata->standalone) {
181
                                if (nplanes > 0) put_cstring(token, getAeteKey('R', gdata->standalone ? &gdata->parm : NULL), expr[0]);
182
                                if (nplanes > 1) put_cstring(token, getAeteKey('G', gdata->standalone ? &gdata->parm : NULL), expr[1]);
183
                                if (nplanes > 2) put_cstring(token, getAeteKey('B', gdata->standalone ? &gdata->parm : NULL), expr[2]);
184
                                if (nplanes > 3) put_cstring(token, getAeteKey('A', gdata->standalone ? &gdata->parm : NULL), expr[3]);
185
                        }
210 daniel-mar 186
 
217 daniel-mar 187
                        /* only write values for the sliders that are actually used! */
188
                        allctls = checksliders(4, ctls, maps);
189
                        for (i = 0; i <= 7; ++i) {
190
                                if (allctls || ctls[i]) {
191
                                        PIPutInt(token, getAeteKey('0' + i, gdata->standalone ? &gdata->parm : NULL), slider[i]);
192
                                }
193
                        }
194
 
195
                        gotErr = CloseWriter(&token); /* closes and sets dialog optional */
196
                        /* done.  Now pass handle on to Photoshop */
197
                }
198
        }
199
        return gotErr;
210 daniel-mar 200
}
201
 
202
 
203
//-------------------------------------------------------------------------------
204
//
205
//      HostDescriptorAvailable
206
//
207
//      Determines whether the PIDescriptorParameters callback is available.
208
//
209
//      Check for valid suite version, routine suite version, and routine count.
210
//      Also check that the subset of routines we actually use is actually present.
211
//
212
//-------------------------------------------------------------------------------
213
 
403 daniel-mar 214
Boolean HostDescriptorAvailable(PIDescriptorParameters* procs, Boolean* outNewerVersion)
210 daniel-mar 215
{
403 daniel-mar 216
        if (procs == NULL) return FALSE; // Photoshop < 4.0 don't has scripting
217
 
217 daniel-mar 218
        if (outNewerVersion)
219
                *outNewerVersion = procs->descriptorParametersVersion > kCurrentDescriptorParametersVersion
220
                || procs->readDescriptorProcs->readDescriptorProcsVersion > kCurrentReadDescriptorProcsVersion
221
                || procs->writeDescriptorProcs->writeDescriptorProcsVersion > kCurrentWriteDescriptorProcsVersion;
210 daniel-mar 222
 
217 daniel-mar 223
        return procs != NULL
224
                && procs->descriptorParametersVersion == kCurrentDescriptorParametersVersion
210 daniel-mar 225
 
217 daniel-mar 226
                && procs->readDescriptorProcs != NULL
227
                && procs->readDescriptorProcs->readDescriptorProcsVersion == kCurrentReadDescriptorProcsVersion
228
                && (unsigned int)(procs->readDescriptorProcs->numReadDescriptorProcs) >= kCurrentReadDescriptorProcsCount
229
                && procs->readDescriptorProcs->openReadDescriptorProc != NULL
230
                && procs->readDescriptorProcs->closeReadDescriptorProc != NULL
231
                && procs->readDescriptorProcs->getKeyProc != NULL
232
                && procs->readDescriptorProcs->getTextProc != NULL
233
                && procs->readDescriptorProcs->getIntegerProc != NULL
210 daniel-mar 234
 
217 daniel-mar 235
                && procs->writeDescriptorProcs != NULL
236
                && procs->writeDescriptorProcs->writeDescriptorProcsVersion == kCurrentWriteDescriptorProcsVersion
237
                && (unsigned int)(procs->writeDescriptorProcs->numWriteDescriptorProcs) >= kCurrentWriteDescriptorProcsCount
238
                && procs->writeDescriptorProcs->openWriteDescriptorProc != NULL
239
                && procs->writeDescriptorProcs->closeWriteDescriptorProc != NULL
240
                && procs->writeDescriptorProcs->putTextProc != NULL
241
                && procs->writeDescriptorProcs->putIntegerProc != NULL;
210 daniel-mar 242
}
243
 
244
 
245
//-------------------------------------------------------------------------------
246
//
247
//      HostCloseReader
248
//
249
//      Closes a read token, disposes its handle, sets the token to NULL, and
250
//      sets the parameter blocks' descriptor to NULL.
251
//
252
//      The Descriptor Parameters suite are callbacks designed for
253
//      scripting and automation.  See PIActions.h.
254
//
255
//      Inputs:
256
//              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
257
//
258
//              HandleProcs *hProcs                             Pointer to HandleProcs callback.
259
//
260
//              PIReadDescriptor *token                 Pointer to token to close.
261
//
262
//              procs->descriptor                               Pointer to original read handle.
263
//
264
//      Outputs:
265
//              PIReadDescriptor *token                 Set to NULL.
266
//
267
//              procs->descriptor                               Disposed then set to NULL.
268
//
269
//              returns OSErr                                   noErr or error if one occurred.
270
//
271
//-------------------------------------------------------------------------------
272
 
217 daniel-mar 273
OSErr HostCloseReader(PIDescriptorParameters* procs,
274
        HandleProcs* hProcs,
275
        PIReadDescriptor* token)
210 daniel-mar 276
{
217 daniel-mar 277
        // Close token:
278
        OSErr err = procs->readDescriptorProcs->closeReadDescriptorProc(*token);
210 daniel-mar 279
 
217 daniel-mar 280
        // Dispose the parameter block descriptor:
281
        hProcs->disposeProc(procs->descriptor);
210 daniel-mar 282
 
217 daniel-mar 283
        // Set the descriptor and the read token to NULL:
284
        procs->descriptor = NULL;
285
        *token = NULL;
210 daniel-mar 286
 
217 daniel-mar 287
        return err;
210 daniel-mar 288
 
289
} // end HostCloseReader
290
 
291
//-------------------------------------------------------------------------------
292
//
293
//      HostCloseWriter
294
//
295
//      Closes a write token, stores its handle in the global parameter block for
296
//      the host to use, sets the token to NULL, and sets the recordInfo to
297
//      plugInDialogOptional (the default).
298
//
299
//      The Descriptor Parameters suite are callbacks designed for
300
//      scripting and automation.  See PIActions.h.
301
//
302
//      Inputs:
303
//              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
304
//
305
//              HandleProcs *hProcs                             Pointer to HandleProcs callback.
306
//
307
//              PIWriteDescriptor *token                Pointer to token to close and pass on.
308
//
309
//              procs->descriptor                               Should be NULL.  If not, its contents
310
//                                                                              will be disposed and replaced.
311
//
312
//      Outputs:
313
//              PIWriteDescriptor *token                Set to NULL.
314
//
315
//              procs->descriptor                               Set to descriptor handle.
316
//
317
//              returns OSErr                                   noErr or error if one occurred.
318
//
319
//-------------------------------------------------------------------------------
320
 
217 daniel-mar 321
OSErr   HostCloseWriter(PIDescriptorParameters* procs,
322
        HandleProcs* hProcs,
323
        PIWriteDescriptor* token)
210 daniel-mar 324
{
217 daniel-mar 325
        OSErr err = noErr; // assume no error
326
        PIDescriptorHandle h = NULL;
210 daniel-mar 327
 
217 daniel-mar 328
        if (procs->descriptor != NULL) // don't need descriptor passed to us
329
                hProcs->disposeProc(procs->descriptor); // dispose.
210 daniel-mar 330
 
217 daniel-mar 331
        // 3. Call CloseWriteDescriptorProc with writeToken, which will create a PIDescriptorHandle.
332
        procs->writeDescriptorProcs->closeWriteDescriptorProc(*token, &h);
210 daniel-mar 333
 
217 daniel-mar 334
        // 4. Place the PIDescriptorHandle into the descriptor field. The host will dispose of it when finished.
335
        procs->descriptor = h;
210 daniel-mar 336
 
217 daniel-mar 337
        // 5. Set recordInfo.  Options are: plugInDialogOptional,
338
        // plugInDialogRequire, plugInDialogNone:
339
        procs->recordInfo = plugInDialogOptional;
210 daniel-mar 340
 
217 daniel-mar 341
        *token = NULL;
342
 
343
        return err;
344
 
210 daniel-mar 345
} // end HostCloseWriter