1 /**
2 * Copyright (C) 2001-2002 Artifex Software, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 **/
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "ijs.h"
29 #include "ijs_client.h"
30
31 static int
example_list_params(IjsClientCtx * ctx)32 example_list_params (IjsClientCtx *ctx)
33 {
34 int status = 0;
35 char buf[4096];
36 char ebuf[4096];
37 char *p;
38 status = ijs_client_list_params (ctx, 0, buf, sizeof(buf) - 1);
39 if (status >= 0)
40 {
41 buf[status] = 0;
42 fprintf (stderr, "settable params: %s\n", buf);
43 p = strtok(buf, ",");
44 while (p)
45 {
46 status = ijs_client_enum_param (ctx, 0, p, ebuf, sizeof(ebuf) - 1);
47 if (status >= 0)
48 {
49 ebuf[status] = 0;
50 fprintf (stderr, " %s: %s\n", p, ebuf);
51 }
52 else
53 {
54 fprintf (stderr, "Error %d getting param %s\n", status, p);
55 }
56 p = strtok(NULL, ",");
57 }
58 }
59 else
60 {
61 fprintf (stderr, "Error %d listing params\n", status);
62 }
63 return status;
64 }
65
66 static int
send_pnm_file(IjsClientCtx * ctx,FILE * f,int xres,int yres)67 send_pnm_file (IjsClientCtx *ctx, FILE *f, int xres, int yres)
68 {
69 int width, height;
70 char *lp, type;
71 int total_bytes, bytes_left;
72 int n_chan, bps;
73 char buf[4096];
74 int status = 0;
75
76 lp = fgets (buf, sizeof(buf), f);
77 if (lp == NULL)
78 {
79 fprintf (stderr, "error reading file\n");
80 return 1;
81 }
82 if (lp[0] != 'P' || lp[1] < '4' || lp[1] > '6')
83 {
84 fprintf (stderr, "need pnmraw file\n");
85 return 1;
86 }
87 type = lp[1];
88 do
89 {
90 lp = fgets (buf, sizeof(buf), f);
91 }
92 while (lp != NULL && lp[0] == '#');
93 if (sscanf (lp, "%d %d", &width, &height) != 2)
94 {
95 fprintf (stderr, "format error\n");
96 return 1;
97 }
98 if (type >= '5')
99 {
100 /* skip depth */
101 do
102 {
103 lp = fgets (buf, sizeof(buf), f);
104 }
105 while (lp != NULL && lp[0] == '#');
106 }
107
108 n_chan = (type == '6') ? 3 : 1;
109 bps = (type == '4') ? 1 : 8;
110
111 /* Set required parameters. Note: we should be checking the return
112 values. */
113 sprintf (buf, "%d", n_chan);
114 ijs_client_set_param (ctx, 0, "NumChan", buf, strlen (buf));
115 sprintf (buf, "%d", bps);
116 ijs_client_set_param (ctx, 0, "BitsPerSample", buf, strlen (buf));
117 strcpy (buf, (n_chan == 3) ? "DeviceRGB" : "DeviceGray");
118 ijs_client_set_param (ctx, 0, "ColorSpace", buf, strlen (buf));
119 sprintf (buf, "%d", width);
120 ijs_client_set_param (ctx, 0, "Width", buf, strlen (buf));
121 sprintf (buf, "%d", height);
122 ijs_client_set_param (ctx, 0, "Height", buf, strlen (buf));
123 sprintf (buf, "%dx%d", xres, yres);
124 ijs_client_set_param (ctx, 0, "Dpi", buf, strlen (buf));
125
126 ijs_client_begin_page (ctx, 0);
127
128 total_bytes = ((n_chan * bps * width + 7) >> 3) * height;
129 bytes_left = total_bytes;
130 while (bytes_left)
131 {
132 int n_bytes = bytes_left;
133 if (n_bytes > sizeof(buf))
134 n_bytes = sizeof(buf);
135 fread (buf, 1, n_bytes, f); /* todo: check error */
136 if (type == '4')
137 {
138 /* invert pbm so black is 0, as per DeviceGray color space */
139 int i;
140 for (i = 0; i < n_bytes; i++)
141 buf[i] ^= 0xff;
142 }
143 status = ijs_client_send_data_wait (ctx, 0, buf, n_bytes);
144 if (status)
145 break;
146 bytes_left -= n_bytes;
147 }
148
149 ijs_client_end_page (ctx, 0);
150
151 return status;
152 }
153
154 static void
verify_context(IjsClientCtx * ctx)155 verify_context (IjsClientCtx *ctx)
156 {
157 if (ctx == NULL)
158 {
159 fprintf (stderr, "Must specify valid server with -s flag\n");
160 exit (1);
161 }
162 }
163
164
165 static void
param_usage(void)166 param_usage (void)
167 {
168 fprintf (stderr, "parameter list must be in key=value, key=value format\n");
169 }
170
171 static void
example_set_params(IjsClientCtx * ctx,const char * arg)172 example_set_params (IjsClientCtx *ctx, const char *arg)
173 {
174 int code;
175 int i, inext;
176 char key[256];
177 char buf[4096];
178 int buf_ix;
179
180 for (i = 0; arg[i] != 0; i = inext)
181 {
182 int ibeg, ieq, iend;
183 int key_size;
184
185 for (ibeg = i; arg[ibeg] == ' '; ibeg++);
186
187 for (ieq = ibeg; arg[ieq] != 0; ieq++)
188 {
189 if (arg[ieq] == '=')
190 break;
191 }
192 if (arg[ieq] == 0)
193 {
194 param_usage ();
195 return;
196 }
197 for (iend = ieq; iend >= ibeg; iend--)
198 if (arg[iend - 1] != ' ')
199 break;
200 if (iend == ibeg)
201 {
202 param_usage ();
203 return;
204 }
205 key_size = iend - ibeg;
206 if (key_size + 1 > sizeof(key))
207 {
208 fprintf (stderr, "Key exceeds %d bytes\n", sizeof(key));
209 return;
210 }
211 memcpy (key, arg + ibeg, key_size);
212 key[key_size] = 0;
213 buf_ix = 0;
214 for (i = ieq + 1; arg[i] == ' '; i++);
215 for (; arg[i] != 0; i++)
216 {
217 if (arg[i] == ',')
218 break;
219 if (buf_ix == sizeof(buf))
220 {
221 fprintf (stderr, "Value for %s exceeds %d bytes\n",
222 key, sizeof(buf));
223 return;
224 }
225 if (arg[i] == '\\' && arg[i + 1] != 0)
226 buf[buf_ix++] = arg[++i];
227 else
228 buf[buf_ix++] = arg[i];
229 }
230 if (arg[i] == ',')
231 inext = i + 1;
232 else
233 inext = i;
234 code = ijs_client_set_param (ctx, 0, key, buf, buf_ix);
235 if (code < 0)
236 fprintf (stderr, "Warning: error %d setting parameter %s\n",
237 code, key);
238 }
239 }
240
241 static void
example_get_param(IjsClientCtx * ctx,const char * arg)242 example_get_param (IjsClientCtx *ctx, const char *arg)
243 {
244 char buf[4096];
245 int status;
246
247 status = ijs_client_get_param (ctx, 0, arg, buf, sizeof(buf) - 1);
248 if (status >= 0)
249 {
250 buf[status] = 0;
251 fprintf (stderr, "value of param %s = %s\n", arg, buf);
252 }
253 else
254 {
255 fprintf (stderr, "Error %d getting param %s\n", status, arg);
256 }
257 }
258
259 static void
example_enum_param(IjsClientCtx * ctx,const char * arg)260 example_enum_param (IjsClientCtx *ctx, const char *arg)
261 {
262 char buf[4096];
263 int status;
264
265 status = ijs_client_enum_param (ctx, 0, arg, buf, sizeof(buf) - 1);
266 if (status >= 0)
267 {
268 buf[status] = 0;
269 fprintf (stderr, "enumeration of param %s: %s\n", arg, buf);
270 }
271 else
272 {
273 fprintf (stderr, "Error %d getting param %s\n", status, arg);
274 }
275 }
276
277 static const char *
get_arg(int argc,char ** argv,int * pi,const char * arg)278 get_arg (int argc, char **argv, int *pi, const char *arg)
279 {
280 if (arg[0] != 0)
281 return arg;
282 else
283 {
284 (*pi)++;
285 if (*pi == argc)
286 return NULL;
287 else
288 return argv[*pi];
289 }
290 }
291
292 int
main(int argc,char ** argv)293 main (int argc, char **argv)
294 {
295 IjsClientCtx *ctx;
296 int i;
297 int xres = 300, yres = 300;
298
299 ctx = NULL;
300
301 for (i = 1; i < argc; i++)
302 {
303 const char *arg = argv[i];
304
305 if (arg[0] == '-')
306 {
307 switch (arg[1])
308 {
309 case 'r':
310 {
311 char *tail;
312
313 arg = get_arg (argc, argv, &i, arg + 2);
314 xres = strtol (arg, &tail, 10);
315 if (tail[0] == 0)
316 yres = xres;
317 else if (tail[0] == 'x')
318 yres = strtol (tail + 1, &tail, 10);
319 }
320 break;
321 case 's':
322 arg = get_arg (argc, argv, &i, arg + 2);
323 ctx = ijs_invoke_server (arg);
324 if (!ctx) {
325 fprintf (stderr, "ijs_invoke_server %s failed\n", arg);
326 return 1;
327 }
328 ijs_client_open (ctx);
329 ijs_client_begin_job (ctx, 0);
330 break;
331 case 'p':
332 arg = get_arg (argc, argv, &i, arg + 2);
333 verify_context (ctx);
334 example_set_params (ctx, arg);
335 break;
336 case 'g':
337 arg = get_arg (argc, argv, &i, arg + 2);
338 verify_context (ctx);
339 example_get_param (ctx, arg);
340 break;
341 case 'e':
342 arg = get_arg (argc, argv, &i, arg + 2);
343 verify_context (ctx);
344 example_enum_param (ctx, arg);
345 break;
346 case 'l':
347 verify_context (ctx);
348 example_list_params (ctx);
349 break;
350 case 0:
351 verify_context (ctx);
352 send_pnm_file (ctx, stdin, xres, yres);
353 break;
354 }
355 }
356 else
357 {
358 FILE *f = fopen (arg, "rb");
359
360 if (f == NULL)
361 {
362 fprintf (stderr, "error opening %s\n", arg);
363 return 1;
364 }
365 verify_context (ctx);
366 send_pnm_file (ctx, f, xres, yres);
367 fclose (f);
368 }
369 }
370
371 verify_context (ctx);
372
373 ijs_client_end_job (ctx, 0);
374 ijs_client_close (ctx);
375
376 /* todo - suffield race, proceduralize */
377 ijs_client_begin_cmd (ctx, IJS_CMD_EXIT);
378 ijs_client_send_cmd_wait (ctx);
379
380 return 0;
381 }
382