Subversion Repositories filter_foundry

Rev

Rev 393 | Rev 424 | 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;
78
                // char* debug = 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);
210 daniel-mar 81
 
217 daniel-mar 82
                // Use random AETE keys, because AppleScript has a global namespace
83
                // and therefore requires unique AETE keys
84
                data = (char*)malloc(0x300);
85
                if (!data) return 0;
86
                sprintf(data, "%s %s %c",
393 daniel-mar 87
                        parm->szCategory,
88
                        parm->szTitle,
217 daniel-mar 89
                        c);
90
                hash = printablehash(djb2(data));
91
                free(data);
92
                return hash;
93
        }
94
        else {
95
                // char* debug = malloc(2000);
96
                // sprintf(debug, "getAeteKey %c in MAIN PLUGIN", c);
97
                // simplealert(debug);
210 daniel-mar 98
 
217 daniel-mar 99
                // Attention: AETE keys (xpr#, cTl#) must be equal in scripting.r, scripting.rc and scripting.c(getAeteKey)!
100
                if (c == 'R') return 'xprR';
101
                if (c == 'G') return 'xprG';
102
                if (c == 'B') return 'xprB';
103
                if (c == 'A') return 'xprA';
104
                if ((c >= '0') && (c <= '9')) return 'cTl0' + (c - '0');
105
                return 0;
106
        }
210 daniel-mar 107
}
108
 
109
/* return true if dialog should be shown */
110
enum ScriptingShowDialog ReadScriptParamsOnRead(void)
111
{
217 daniel-mar 112
        PIReadDescriptor token;
113
        DescriptorKeyID key;
114
        DescriptorTypeID type;
115
        DescriptorKeyIDArray array = { NULLID };
116
        int32 flags;
117
        //OSErr stickyError;
118
        int32 v;
210 daniel-mar 119
 
217 daniel-mar 120
        if (DescriptorAvailable(NULL)) { /* playing back.  Do our thing. */
121
                token = OpenReader(array);
122
                if (token) {
123
                        while (PIGetKey(token, &key, &type, &flags)) {
124
                                if (key == getAeteKey('R', gdata->standalone ? &gdata->parm : NULL)) {
125
                                        expr[0] = get_cstring(token);
126
                                }
127
                                else if (key == getAeteKey('G', gdata->standalone ? &gdata->parm : NULL)) {
128
                                        expr[1] = get_cstring(token);
129
                                }
130
                                else if (key == getAeteKey('B', gdata->standalone ? &gdata->parm : NULL)) {
131
                                        expr[2] = get_cstring(token);
132
                                }
133
                                else if (key == getAeteKey('A', gdata->standalone ? &gdata->parm : NULL)) {
134
                                        expr[3] = get_cstring(token);
135
                                }
136
                                else {
137
                                        int i;
138
                                        for (i = 0; i <= 7; ++i) {
139
                                                if (key == getAeteKey('0' + i, gdata->standalone ? &gdata->parm : NULL)) {
140
                                                        PIGetInt(token, &v);
141
                                                        slider[i] = v;
142
                                                }
143
                                        }
144
                                }
145
                        }
210 daniel-mar 146
 
217 daniel-mar 147
                        /*stickyError =*/ CloseReader(&token); // closes & disposes.
210 daniel-mar 148
 
217 daniel-mar 149
                        // all Filter Foundry parameters are optional,
150
                        // so we needn't worry if any are missing
151
                }
210 daniel-mar 152
 
217 daniel-mar 153
                return gpb->descriptorParameters->playInfo == plugInDialogDisplay ? SCR_SHOW_DIALOG : SCR_HIDE_DIALOG;
154
        }
155
        else {
156
                return SCR_NO_SCRIPT;
157
        }
210 daniel-mar 158
}
159
 
160
OSErr WriteScriptParamsOnRead(void)
161
{
217 daniel-mar 162
        PIWriteDescriptor token;
163
        OSErr gotErr = noErr;
164
        extern int ctls[], maps[], nplanes;
165
        int i, allctls;
210 daniel-mar 166
 
217 daniel-mar 167
        if (DescriptorAvailable(NULL)) { /* recording.  Do our thing. */
168
                // 1. Call openWriteDescriptorProc which will return a PIWriteDescriptor token, such as writeToken.
169
                token = OpenWriter();
170
                if (token) {
171
                        // 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 172
 
217 daniel-mar 173
                        // write keys here
174
                        if (!gdata->standalone) {
175
                                if (nplanes > 0) put_cstring(token, getAeteKey('R', gdata->standalone ? &gdata->parm : NULL), expr[0]);
176
                                if (nplanes > 1) put_cstring(token, getAeteKey('G', gdata->standalone ? &gdata->parm : NULL), expr[1]);
177
                                if (nplanes > 2) put_cstring(token, getAeteKey('B', gdata->standalone ? &gdata->parm : NULL), expr[2]);
178
                                if (nplanes > 3) put_cstring(token, getAeteKey('A', gdata->standalone ? &gdata->parm : NULL), expr[3]);
179
                        }
210 daniel-mar 180
 
217 daniel-mar 181
                        /* only write values for the sliders that are actually used! */
182
                        allctls = checksliders(4, ctls, maps);
183
                        for (i = 0; i <= 7; ++i) {
184
                                if (allctls || ctls[i]) {
185
                                        PIPutInt(token, getAeteKey('0' + i, gdata->standalone ? &gdata->parm : NULL), slider[i]);
186
                                }
187
                        }
188
 
189
                        gotErr = CloseWriter(&token); /* closes and sets dialog optional */
190
                        /* done.  Now pass handle on to Photoshop */
191
                }
192
        }
193
        return gotErr;
210 daniel-mar 194
}
195
 
196
 
197
//-------------------------------------------------------------------------------
198
//
199
//      HostDescriptorAvailable
200
//
201
//      Determines whether the PIDescriptorParameters callback is available.
202
//
203
//      Check for valid suite version, routine suite version, and routine count.
204
//      Also check that the subset of routines we actually use is actually present.
205
//
206
//-------------------------------------------------------------------------------
207
 
403 daniel-mar 208
Boolean HostDescriptorAvailable(PIDescriptorParameters* procs, Boolean* outNewerVersion)
210 daniel-mar 209
{
403 daniel-mar 210
        if (procs == NULL) return FALSE; // Photoshop < 4.0 don't has scripting
211
 
217 daniel-mar 212
        if (outNewerVersion)
213
                *outNewerVersion = procs->descriptorParametersVersion > kCurrentDescriptorParametersVersion
214
                || procs->readDescriptorProcs->readDescriptorProcsVersion > kCurrentReadDescriptorProcsVersion
215
                || procs->writeDescriptorProcs->writeDescriptorProcsVersion > kCurrentWriteDescriptorProcsVersion;
210 daniel-mar 216
 
217 daniel-mar 217
        return procs != NULL
218
                && procs->descriptorParametersVersion == kCurrentDescriptorParametersVersion
210 daniel-mar 219
 
217 daniel-mar 220
                && procs->readDescriptorProcs != NULL
221
                && procs->readDescriptorProcs->readDescriptorProcsVersion == kCurrentReadDescriptorProcsVersion
222
                && (unsigned int)(procs->readDescriptorProcs->numReadDescriptorProcs) >= kCurrentReadDescriptorProcsCount
223
                && procs->readDescriptorProcs->openReadDescriptorProc != NULL
224
                && procs->readDescriptorProcs->closeReadDescriptorProc != NULL
225
                && procs->readDescriptorProcs->getKeyProc != NULL
226
                && procs->readDescriptorProcs->getTextProc != NULL
227
                && procs->readDescriptorProcs->getIntegerProc != NULL
210 daniel-mar 228
 
217 daniel-mar 229
                && procs->writeDescriptorProcs != NULL
230
                && procs->writeDescriptorProcs->writeDescriptorProcsVersion == kCurrentWriteDescriptorProcsVersion
231
                && (unsigned int)(procs->writeDescriptorProcs->numWriteDescriptorProcs) >= kCurrentWriteDescriptorProcsCount
232
                && procs->writeDescriptorProcs->openWriteDescriptorProc != NULL
233
                && procs->writeDescriptorProcs->closeWriteDescriptorProc != NULL
234
                && procs->writeDescriptorProcs->putTextProc != NULL
235
                && procs->writeDescriptorProcs->putIntegerProc != NULL;
210 daniel-mar 236
}
237
 
238
 
239
//-------------------------------------------------------------------------------
240
//
241
//      HostCloseReader
242
//
243
//      Closes a read token, disposes its handle, sets the token to NULL, and
244
//      sets the parameter blocks' descriptor to NULL.
245
//
246
//      The Descriptor Parameters suite are callbacks designed for
247
//      scripting and automation.  See PIActions.h.
248
//
249
//      Inputs:
250
//              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
251
//
252
//              HandleProcs *hProcs                             Pointer to HandleProcs callback.
253
//
254
//              PIReadDescriptor *token                 Pointer to token to close.
255
//
256
//              procs->descriptor                               Pointer to original read handle.
257
//
258
//      Outputs:
259
//              PIReadDescriptor *token                 Set to NULL.
260
//
261
//              procs->descriptor                               Disposed then set to NULL.
262
//
263
//              returns OSErr                                   noErr or error if one occurred.
264
//
265
//-------------------------------------------------------------------------------
266
 
217 daniel-mar 267
OSErr HostCloseReader(PIDescriptorParameters* procs,
268
        HandleProcs* hProcs,
269
        PIReadDescriptor* token)
210 daniel-mar 270
{
217 daniel-mar 271
        // Close token:
272
        OSErr err = procs->readDescriptorProcs->closeReadDescriptorProc(*token);
210 daniel-mar 273
 
217 daniel-mar 274
        // Dispose the parameter block descriptor:
275
        hProcs->disposeProc(procs->descriptor);
210 daniel-mar 276
 
217 daniel-mar 277
        // Set the descriptor and the read token to NULL:
278
        procs->descriptor = NULL;
279
        *token = NULL;
210 daniel-mar 280
 
217 daniel-mar 281
        return err;
210 daniel-mar 282
 
283
} // end HostCloseReader
284
 
285
//-------------------------------------------------------------------------------
286
//
287
//      HostCloseWriter
288
//
289
//      Closes a write token, stores its handle in the global parameter block for
290
//      the host to use, sets the token to NULL, and sets the recordInfo to
291
//      plugInDialogOptional (the default).
292
//
293
//      The Descriptor Parameters suite are callbacks designed for
294
//      scripting and automation.  See PIActions.h.
295
//
296
//      Inputs:
297
//              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
298
//
299
//              HandleProcs *hProcs                             Pointer to HandleProcs callback.
300
//
301
//              PIWriteDescriptor *token                Pointer to token to close and pass on.
302
//
303
//              procs->descriptor                               Should be NULL.  If not, its contents
304
//                                                                              will be disposed and replaced.
305
//
306
//      Outputs:
307
//              PIWriteDescriptor *token                Set to NULL.
308
//
309
//              procs->descriptor                               Set to descriptor handle.
310
//
311
//              returns OSErr                                   noErr or error if one occurred.
312
//
313
//-------------------------------------------------------------------------------
314
 
217 daniel-mar 315
OSErr   HostCloseWriter(PIDescriptorParameters* procs,
316
        HandleProcs* hProcs,
317
        PIWriteDescriptor* token)
210 daniel-mar 318
{
217 daniel-mar 319
        OSErr err = noErr; // assume no error
320
        PIDescriptorHandle h = NULL;
210 daniel-mar 321
 
217 daniel-mar 322
        if (procs->descriptor != NULL) // don't need descriptor passed to us
323
                hProcs->disposeProc(procs->descriptor); // dispose.
210 daniel-mar 324
 
217 daniel-mar 325
        // 3. Call CloseWriteDescriptorProc with writeToken, which will create a PIDescriptorHandle.
326
        procs->writeDescriptorProcs->closeWriteDescriptorProc(*token, &h);
210 daniel-mar 327
 
217 daniel-mar 328
        // 4. Place the PIDescriptorHandle into the descriptor field. The host will dispose of it when finished.
329
        procs->descriptor = h;
210 daniel-mar 330
 
217 daniel-mar 331
        // 5. Set recordInfo.  Options are: plugInDialogOptional,
332
        // plugInDialogRequire, plugInDialogNone:
333
        procs->recordInfo = plugInDialogOptional;
210 daniel-mar 334
 
217 daniel-mar 335
        *token = NULL;
336
 
337
        return err;
338
 
210 daniel-mar 339
} // end HostCloseWriter