1 /**
2 * Copyright (c) 2001-2002 artofcode LLC.
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 ijs_client_open (ctx);
325 ijs_client_begin_job (ctx, 0);
326 break;
327 case 'p':
328 arg = get_arg (argc, argv, &i, arg + 2);
329 verify_context (ctx);
330 example_set_params (ctx, arg);
331 break;
332 case 'g':
333 arg = get_arg (argc, argv, &i, arg + 2);
334 verify_context (ctx);
335 example_get_param (ctx, arg);
336 break;
337 case 'e':
338 arg = get_arg (argc, argv, &i, arg + 2);
339 verify_context (ctx);
340 example_enum_param (ctx, arg);
341 break;
342 case 'l':
343 verify_context (ctx);
344 example_list_params (ctx);
345 break;
346 case 0:
347 verify_context (ctx);
348 send_pnm_file (ctx, stdin, xres, yres);
349 break;
350 }
351 }
352 else
353 {
354 FILE *f = fopen (arg, "rb");
355
356 if (f == NULL)
357 {
358 fprintf (stderr, "error opening %s\n", arg);
359 return 1;
360 }
361 verify_context (ctx);
362 send_pnm_file (ctx, f, xres, yres);
363 fclose (f);
364 }
365 }
366
367 verify_context (ctx);
368
369 ijs_client_end_job (ctx, 0);
370 ijs_client_close (ctx);
371
372 /* todo - suffield race, proceduralize */
373 ijs_client_begin_cmd (ctx, IJS_CMD_EXIT);
374 ijs_client_send_cmd_wait (ctx);
375
376 return 0;
377 }
378