1 /*------------------------------------------------------------------------
2  *  Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
3  *
4  *  This file is part of the ZBar Bar Code Reader.
5  *
6  *  The ZBar Bar Code Reader is free software; you can redistribute it
7  *  and/or modify it under the terms of the GNU Lesser Public License as
8  *  published by the Free Software Foundation; either version 2.1 of
9  *  the License, or (at your option) any later version.
10  *
11  *  The ZBar Bar Code Reader is distributed in the hope that it will be
12  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  *  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU Lesser Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser Public License
17  *  along with the ZBar Bar Code Reader; if not, write to the Free
18  *  Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  *  Boston, MA  02110-1301  USA
20  *
21  *  http://sourceforge.net/projects/zbar
22  *------------------------------------------------------------------------*/
23 
24 #include "processor.h"
25 #include "window.h"
26 #include "image.h"
27 #include "img_scanner.h"
28 
proc_enter(zbar_processor_t * proc)29 static inline int proc_enter (zbar_processor_t *proc)
30 {
31     _zbar_mutex_lock(&proc->mutex);
32     return(_zbar_processor_lock(proc));
33 }
34 
proc_leave(zbar_processor_t * proc)35 static inline int proc_leave (zbar_processor_t *proc)
36 {
37     int rc = _zbar_processor_unlock(proc, 0);
38     _zbar_mutex_unlock(&proc->mutex);
39     return(rc);
40 }
41 
proc_open(zbar_processor_t * proc)42 static inline int proc_open (zbar_processor_t *proc)
43 {
44     /* arbitrary default */
45     int width = 640, height = 480;
46     if(proc->video) {
47         width = zbar_video_get_width(proc->video);
48         height = zbar_video_get_height(proc->video);
49     }
50     return(_zbar_processor_open(proc, "zbar barcode reader", width, height));
51 }
52 
53 /* API lock is already held */
_zbar_process_image(zbar_processor_t * proc,zbar_image_t * img)54 int _zbar_process_image (zbar_processor_t *proc,
55                          zbar_image_t *img)
56 {
57     uint32_t force_fmt = proc->force_output;
58     if(img) {
59         if(proc->dumping) {
60             zbar_image_write(proc->window->image, "zbar");
61             proc->dumping = 0;
62         }
63 
64         uint32_t format = zbar_image_get_format(img);
65         zprintf(16, "processing: %.4s(%08" PRIx32 ") %dx%d @%p\n",
66                 (char*)&format, format,
67                 zbar_image_get_width(img), zbar_image_get_height(img),
68                 zbar_image_get_data(img));
69 
70         /* FIXME locking all other interfaces while processing is conservative
71          * but easier for now and we don't expect this to take long...
72          */
73         zbar_image_t *tmp = zbar_image_convert(img, fourcc('Y','8','0','0'));
74         if(!tmp)
75             goto error;
76 
77         if(proc->syms) {
78             zbar_symbol_set_ref(proc->syms, -1);
79             proc->syms = NULL;
80         }
81         zbar_image_scanner_recycle_image(proc->scanner, img);
82         int nsyms = zbar_scan_image(proc->scanner, tmp);
83         _zbar_image_swap_symbols(img, tmp);
84 
85         zbar_image_destroy(tmp);
86         tmp = NULL;
87         if(nsyms < 0)
88             goto error;
89 
90         proc->syms = zbar_image_scanner_get_results(proc->scanner);
91         if(proc->syms)
92             zbar_symbol_set_ref(proc->syms, 1);
93 
94         if(_zbar_verbosity >= 8) {
95             const zbar_symbol_t *sym = zbar_image_first_symbol(img);
96             while(sym) {
97                 zbar_symbol_type_t type = zbar_symbol_get_type(sym);
98                 int count = zbar_symbol_get_count(sym);
99                 zprintf(8, "%s: %s (%d pts) (dir=%d) (q=%d) (%s)\n",
100                         zbar_get_symbol_name(type),
101                         zbar_symbol_get_data(sym),
102                         zbar_symbol_get_loc_size(sym),
103                         zbar_symbol_get_orientation(sym),
104                         zbar_symbol_get_quality(sym),
105                         (count < 0) ? "uncertain" :
106                         (count > 0) ? "duplicate" : "new");
107                 sym = zbar_symbol_next(sym);
108             }
109         }
110 
111         if(nsyms) {
112             /* FIXME only call after filtering */
113             _zbar_mutex_lock(&proc->mutex);
114             _zbar_processor_notify(proc, EVENT_OUTPUT);
115             _zbar_mutex_unlock(&proc->mutex);
116             if(proc->handler)
117                 proc->handler(img, proc->userdata);
118         }
119 
120         if(force_fmt) {
121             zbar_symbol_set_t *syms = img->syms;
122             img = zbar_image_convert(img, force_fmt);
123             if(!img)
124                 goto error;
125             img->syms = syms;
126             zbar_symbol_set_ref(syms, 1);
127         }
128     }
129 
130     /* display to window if enabled */
131     int rc = 0;
132     if(proc->window) {
133         if((rc = zbar_window_draw(proc->window, img)))
134             err_copy(proc, proc->window);
135         _zbar_processor_invalidate(proc);
136     }
137 
138     if(force_fmt && img)
139         zbar_image_destroy(img);
140     return(rc);
141 
142 error:
143     return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED,
144                        __func__, "unknown image format"));
145 }
146 
_zbar_processor_handle_input(zbar_processor_t * proc,int input)147 int _zbar_processor_handle_input (zbar_processor_t *proc,
148                                   int input)
149 {
150     int event = EVENT_INPUT;
151     switch(input) {
152     case -1:
153         event |= EVENT_CANCELED;
154         _zbar_processor_set_visible(proc, 0);
155         err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__,
156                     "user closed display window");
157         break;
158 
159     case 'd':
160         proc->dumping = 1;
161         return(0);
162 
163     case '+':
164     case '=':
165         if(proc->window) {
166             int ovl = zbar_window_get_overlay(proc->window);
167             zbar_window_set_overlay(proc->window, ovl + 1);
168         }
169         break;
170 
171     case '-':
172         if(proc->window) {
173             int ovl = zbar_window_get_overlay(proc->window);
174             zbar_window_set_overlay(proc->window, ovl - 1);
175         }
176         break;
177     }
178 
179     _zbar_mutex_lock(&proc->mutex);
180     proc->input = input;
181     if(input == -1 && proc->visible && proc->streaming)
182         /* also cancel outstanding output waiters */
183         event |= EVENT_OUTPUT;
184     _zbar_processor_notify(proc, event);
185     _zbar_mutex_unlock(&proc->mutex);
186     return(input);
187 }
188 
189 #ifdef ZTHREAD
190 
proc_video_thread(void * arg)191 static ZTHREAD proc_video_thread (void *arg)
192 {
193     zbar_processor_t *proc = arg;
194     zbar_thread_t *thread = &proc->video_thread;
195 
196     _zbar_mutex_lock(&proc->mutex);
197     _zbar_thread_init(thread);
198     zprintf(4, "spawned video thread\n");
199 
200     while(thread->started) {
201         /* wait for video stream to be active */
202         while(thread->started && !proc->streaming)
203             _zbar_event_wait(&thread->notify, &proc->mutex, NULL);
204         if(!thread->started)
205             break;
206 
207         /* blocking capture image from video */
208         _zbar_mutex_unlock(&proc->mutex);
209         zbar_image_t *img = zbar_video_next_image(proc->video);
210         _zbar_mutex_lock(&proc->mutex);
211 
212         if(!img && !proc->streaming)
213             continue;
214         else if(!img)
215             /* FIXME could abort streaming and keep running? */
216             break;
217 
218         /* acquire API lock */
219         _zbar_processor_lock(proc);
220         _zbar_mutex_unlock(&proc->mutex);
221 
222         if(thread->started && proc->streaming)
223             _zbar_process_image(proc, img);
224 
225         zbar_image_destroy(img);
226 
227         _zbar_mutex_lock(&proc->mutex);
228         /* release API lock */
229         _zbar_processor_unlock(proc, 0);
230     }
231 
232     thread->running = 0;
233     _zbar_event_trigger(&thread->activity);
234     _zbar_mutex_unlock(&proc->mutex);
235     return(0);
236 }
237 
proc_input_thread(void * arg)238 static ZTHREAD proc_input_thread (void *arg)
239 {
240     zbar_processor_t *proc = arg;
241     zbar_thread_t *thread = &proc->input_thread;
242     if(proc->window && proc_open(proc))
243         goto done;
244 
245     _zbar_mutex_lock(&proc->mutex);
246     thread->running = 1;
247     _zbar_event_trigger(&thread->activity);
248     zprintf(4, "spawned input thread\n");
249 
250     int rc = 0;
251     while(thread->started && rc >= 0) {
252         _zbar_mutex_unlock(&proc->mutex);
253         rc = _zbar_processor_input_wait(proc, &thread->notify, -1);
254         _zbar_mutex_lock(&proc->mutex);
255     }
256 
257     _zbar_mutex_unlock(&proc->mutex);
258     _zbar_processor_close(proc);
259     _zbar_mutex_lock(&proc->mutex);
260 
261  done:
262     thread->running = 0;
263     _zbar_event_trigger(&thread->activity);
264     _zbar_mutex_unlock(&proc->mutex);
265     return(0);
266 }
267 
268 #endif
269 
zbar_processor_create(int threaded)270 zbar_processor_t *zbar_processor_create (int threaded)
271 {
272     zbar_processor_t *proc = calloc(1, sizeof(zbar_processor_t));
273     if(!proc)
274         return(NULL);
275     err_init(&proc->err, ZBAR_MOD_PROCESSOR);
276 
277     proc->scanner = zbar_image_scanner_create();
278     if(!proc->scanner) {
279         free(proc);
280         return(NULL);
281     }
282 
283     proc->threaded = !_zbar_mutex_init(&proc->mutex) && threaded;
284     _zbar_processor_init(proc);
285     return(proc);
286 }
287 
zbar_processor_destroy(zbar_processor_t * proc)288 void zbar_processor_destroy (zbar_processor_t *proc)
289 {
290     zbar_processor_init(proc, NULL, 0);
291 
292     if(proc->syms) {
293         zbar_symbol_set_ref(proc->syms, -1);
294         proc->syms = NULL;
295     }
296     if(proc->scanner) {
297         zbar_image_scanner_destroy(proc->scanner);
298         proc->scanner = NULL;
299     }
300 
301     _zbar_mutex_destroy(&proc->mutex);
302     _zbar_processor_cleanup(proc);
303 
304     assert(!proc->wait_head);
305     assert(!proc->wait_tail);
306     assert(!proc->wait_next);
307 
308     proc_waiter_t *w, *next;
309     for(w = proc->free_waiter; w; w = next) {
310         next = w->next;
311         _zbar_event_destroy(&w->notify);
312         free(w);
313     }
314 
315     err_cleanup(&proc->err);
316     free(proc);
317 }
318 
zbar_processor_init(zbar_processor_t * proc,const char * dev,int enable_display)319 int zbar_processor_init (zbar_processor_t *proc,
320                          const char *dev,
321                          int enable_display)
322 {
323     if(proc->video)
324         zbar_processor_set_active(proc, 0);
325 
326     if(proc->window && !proc->input_thread.started)
327         _zbar_processor_close(proc);
328 
329     _zbar_mutex_lock(&proc->mutex);
330     _zbar_thread_stop(&proc->input_thread, &proc->mutex);
331     _zbar_thread_stop(&proc->video_thread, &proc->mutex);
332 
333     _zbar_processor_lock(proc);
334     _zbar_mutex_unlock(&proc->mutex);
335 
336     if(proc->window) {
337         zbar_window_destroy(proc->window);
338         proc->window = NULL;
339     }
340 
341     int rc = 0;
342     if(proc->video) {
343         zbar_video_destroy(proc->video);
344         proc->video = NULL;
345     }
346 
347     if(!dev && !enable_display)
348         /* nothing to do */
349         goto done;
350 
351     if(enable_display) {
352         proc->window = zbar_window_create();
353         if(!proc->window) {
354             rc = err_capture(proc, SEV_FATAL, ZBAR_ERR_NOMEM,
355                              __func__, "allocating window resources");
356             goto done;
357         }
358     }
359 
360     if(dev) {
361         proc->video = zbar_video_create();
362         if(!proc->video) {
363             rc = err_capture(proc, SEV_FATAL, ZBAR_ERR_NOMEM,
364                              __func__, "allocating video resources");
365             goto done;
366         }
367         if(proc->req_width || proc->req_height)
368             zbar_video_request_size(proc->video,
369                                      proc->req_width, proc->req_height);
370         if(proc->req_intf)
371             zbar_video_request_interface(proc->video, proc->req_intf);
372         if((proc->req_iomode &&
373             zbar_video_request_iomode(proc->video, proc->req_iomode)) ||
374            zbar_video_open(proc->video, dev)) {
375             rc = err_copy(proc, proc->video);
376             goto done;
377         }
378     }
379 
380     /* spawn blocking video thread */
381     int video_threaded = (proc->threaded && proc->video &&
382                           zbar_video_get_fd(proc->video) < 0);
383     if(video_threaded &&
384        _zbar_thread_start(&proc->video_thread, proc_video_thread, proc,
385                           &proc->mutex)) {
386         rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
387                          "spawning video thread");
388         goto done;
389     }
390 
391     /* spawn input monitor thread */
392     int input_threaded = (proc->threaded &&
393                           (proc->window ||
394                            (proc->video && !video_threaded)));
395     if(input_threaded &&
396        _zbar_thread_start(&proc->input_thread, proc_input_thread, proc,
397                           &proc->mutex)) {
398         rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
399                          "spawning input thread");
400         goto done;
401     }
402 
403     if(proc->window && !input_threaded &&
404        (rc = proc_open(proc)))
405         goto done;
406 
407     if(proc->video && proc->force_input) {
408         if(zbar_video_init(proc->video, proc->force_input))
409             rc = err_copy(proc, proc->video);
410     }
411     else if(proc->video) {
412         int retry = -1;
413         if(proc->window) {
414             retry = zbar_negotiate_format(proc->video, proc->window);
415             if(retry)
416                 fprintf(stderr,
417                         "WARNING: no compatible input to output format\n"
418                         "...trying again with output disabled\n");
419         }
420         if(retry)
421             retry = zbar_negotiate_format(proc->video, NULL);
422 
423         if(retry) {
424             zprintf(1, "ERROR: no compatible %s format\n",
425                     (proc->video) ? "video input" : "window output");
426             rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED,
427                              __func__, "no compatible image format");
428         }
429     }
430 
431  done:
432     _zbar_mutex_lock(&proc->mutex);
433     proc_leave(proc);
434     return(rc);
435 }
436 
437 zbar_image_data_handler_t*
zbar_processor_set_data_handler(zbar_processor_t * proc,zbar_image_data_handler_t * handler,const void * userdata)438 zbar_processor_set_data_handler (zbar_processor_t *proc,
439                                  zbar_image_data_handler_t *handler,
440                                  const void *userdata)
441 {
442     zbar_image_data_handler_t *result = NULL;
443     proc_enter(proc);
444 
445     result = proc->handler;
446     proc->handler = handler;
447     proc->userdata = userdata;
448 
449     proc_leave(proc);
450     return(result);
451 }
452 
zbar_processor_set_userdata(zbar_processor_t * proc,void * userdata)453 void zbar_processor_set_userdata (zbar_processor_t *proc,
454                                   void *userdata)
455 {
456     _zbar_mutex_lock(&proc->mutex);
457     proc->userdata = userdata;
458     _zbar_mutex_unlock(&proc->mutex);
459 }
460 
zbar_processor_get_userdata(const zbar_processor_t * proc)461 void *zbar_processor_get_userdata (const zbar_processor_t *proc)
462 {
463     zbar_processor_t *ncproc = (zbar_processor_t*)proc;
464     _zbar_mutex_lock(&ncproc->mutex);
465     void *userdata = (void*)ncproc->userdata;
466     _zbar_mutex_unlock(&ncproc->mutex);
467     return(userdata);
468 }
469 
zbar_processor_set_config(zbar_processor_t * proc,zbar_symbol_type_t sym,zbar_config_t cfg,int val)470 int zbar_processor_set_config (zbar_processor_t *proc,
471                                zbar_symbol_type_t sym,
472                                zbar_config_t cfg,
473                                int val)
474 {
475     proc_enter(proc);
476     int rc = zbar_image_scanner_set_config(proc->scanner, sym, cfg, val);
477     proc_leave(proc);
478     return(rc);
479 }
480 
zbar_processor_set_control(zbar_processor_t * proc,const char * control_name,int value)481 int zbar_processor_set_control (zbar_processor_t *proc,
482                                 const char *control_name,
483                                 int value)
484 {
485     proc_enter(proc);
486     int value_before, value_after;
487     if(_zbar_verbosity >= 4)
488         if(zbar_video_get_control(proc->video, control_name, &value_before)==0)
489             zprintf(0, "value of %s before a set: %d\n", control_name, value_before);
490     int rc = zbar_video_set_control(proc->video, control_name, value);
491     if(_zbar_verbosity >= 4)
492         if(zbar_video_get_control(proc->video, control_name, &value_after)==0)
493             zprintf(0, "value of %s after a set: %d\n", control_name, value_after);
494     proc_leave(proc);
495     return(rc);
496 }
497 
zbar_processor_get_control(zbar_processor_t * proc,const char * control_name,int * value)498 int zbar_processor_get_control (zbar_processor_t *proc,
499                                 const char *control_name,
500                                 int *value)
501 {
502     proc_enter(proc);
503     int rc = zbar_video_get_control(proc->video, control_name, value);
504     proc_leave(proc);
505     return(rc);
506 }
507 
zbar_processor_request_size(zbar_processor_t * proc,unsigned width,unsigned height)508 int zbar_processor_request_size (zbar_processor_t *proc,
509                                  unsigned width,
510                                  unsigned height)
511 {
512     proc_enter(proc);
513     proc->req_width = width;
514     proc->req_height = height;
515     proc_leave(proc);
516     return(0);
517 }
518 
zbar_processor_request_interface(zbar_processor_t * proc,int ver)519 int zbar_processor_request_interface (zbar_processor_t *proc,
520                                       int ver)
521 {
522     proc_enter(proc);
523     proc->req_intf = ver;
524     proc_leave(proc);
525     return(0);
526 }
527 
zbar_processor_request_iomode(zbar_processor_t * proc,int iomode)528 int zbar_processor_request_iomode (zbar_processor_t *proc,
529                                    int iomode)
530 {
531     proc_enter(proc);
532     proc->req_iomode = iomode;
533     proc_leave(proc);
534     return(0);
535 }
536 
zbar_processor_force_format(zbar_processor_t * proc,unsigned long input,unsigned long output)537 int zbar_processor_force_format (zbar_processor_t *proc,
538                                  unsigned long input,
539                                  unsigned long output)
540 {
541     proc_enter(proc);
542     proc->force_input = input;
543     proc->force_output = output;
544     proc_leave(proc);
545     return(0);
546 }
547 
zbar_processor_is_visible(zbar_processor_t * proc)548 int zbar_processor_is_visible (zbar_processor_t *proc)
549 {
550     proc_enter(proc);
551     int visible = proc->window && proc->visible;
552     proc_leave(proc);
553     return(visible);
554 }
555 
zbar_processor_set_visible(zbar_processor_t * proc,int visible)556 int zbar_processor_set_visible (zbar_processor_t *proc,
557                                 int visible)
558 {
559     proc_enter(proc);
560     _zbar_mutex_unlock(&proc->mutex);
561 
562     int rc = 0;
563     if(proc->window) {
564         if(proc->video)
565             rc = _zbar_processor_set_size(proc,
566                                           zbar_video_get_width(proc->video),
567                                           zbar_video_get_height(proc->video));
568         if(!rc)
569             rc = _zbar_processor_set_visible(proc, visible);
570 
571         if(!rc)
572             proc->visible = (visible != 0);
573     }
574     else if(visible)
575         rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
576                          "processor display window not initialized");
577 
578     _zbar_mutex_lock(&proc->mutex);
579     proc_leave(proc);
580     return(rc);
581 }
582 
583 const zbar_symbol_set_t*
zbar_processor_get_results(const zbar_processor_t * proc)584 zbar_processor_get_results (const zbar_processor_t *proc)
585 {
586     zbar_processor_t *ncproc = (zbar_processor_t*)proc;
587     proc_enter(ncproc);
588     const zbar_symbol_set_t *syms = proc->syms;
589     if(syms)
590         zbar_symbol_set_ref(syms, 1);
591     proc_leave(ncproc);
592     return(syms);
593 }
594 
zbar_processor_user_wait(zbar_processor_t * proc,int timeout)595 int zbar_processor_user_wait (zbar_processor_t *proc,
596                               int timeout)
597 {
598     proc_enter(proc);
599     _zbar_mutex_unlock(&proc->mutex);
600 
601     int rc = -1;
602     if(proc->visible || proc->streaming || timeout >= 0) {
603         zbar_timer_t timer;
604         rc = _zbar_processor_wait(proc, EVENT_INPUT,
605                                   _zbar_timer_init(&timer, timeout));
606     }
607 
608     if(!proc->visible)
609         rc = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__,
610                          "display window not available for input");
611 
612     if(rc > 0)
613         rc = proc->input;
614 
615     _zbar_mutex_lock(&proc->mutex);
616     proc_leave(proc);
617     return(rc);
618 }
619 
zbar_processor_set_active(zbar_processor_t * proc,int active)620 int zbar_processor_set_active (zbar_processor_t *proc,
621                                int active)
622 {
623     proc_enter(proc);
624 
625     int rc;
626     if(!proc->video) {
627         rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
628                          "video input not initialized");
629         goto done;
630     }
631     _zbar_mutex_unlock(&proc->mutex);
632 
633     zbar_image_scanner_enable_cache(proc->scanner, active);
634 
635     rc = zbar_video_enable(proc->video, active);
636     if(!rc) {
637         _zbar_mutex_lock(&proc->mutex);
638         proc->streaming = active;
639         _zbar_mutex_unlock(&proc->mutex);
640         rc = _zbar_processor_enable(proc);
641     }
642     else
643         err_copy(proc, proc->video);
644 
645     if(!proc->streaming && proc->window) {
646         if(zbar_window_draw(proc->window, NULL) && !rc)
647             rc = err_copy(proc, proc->window);
648         _zbar_processor_invalidate(proc);
649     }
650 
651     _zbar_mutex_lock(&proc->mutex);
652     if(proc->video_thread.started)
653         _zbar_event_trigger(&proc->video_thread.notify);
654 
655  done:
656     proc_leave(proc);
657     return(rc);
658 }
659 
zbar_process_one(zbar_processor_t * proc,int timeout)660 int zbar_process_one (zbar_processor_t *proc,
661                       int timeout)
662 {
663     proc_enter(proc);
664     int streaming = proc->streaming;
665     _zbar_mutex_unlock(&proc->mutex);
666 
667     int rc = 0;
668     if(!proc->video) {
669         rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
670                          "video input not initialized");
671         goto done;
672     }
673 
674     if(!streaming) {
675         rc = zbar_processor_set_active(proc, 1);
676         if(rc)
677             goto done;
678     }
679 
680     zbar_timer_t timer;
681     rc = _zbar_processor_wait(proc, EVENT_OUTPUT,
682                               _zbar_timer_init(&timer, timeout));
683 
684     if(!streaming && zbar_processor_set_active(proc, 0))
685         rc = -1;
686 
687  done:
688     _zbar_mutex_lock(&proc->mutex);
689     proc_leave(proc);
690     return(rc);
691 }
692 
zbar_process_image(zbar_processor_t * proc,zbar_image_t * img)693 int zbar_process_image (zbar_processor_t *proc,
694                         zbar_image_t *img)
695 {
696     proc_enter(proc);
697     _zbar_mutex_unlock(&proc->mutex);
698 
699     int rc = 0;
700     if(img && proc->window)
701         rc = _zbar_processor_set_size(proc,
702                                       zbar_image_get_width(img),
703                                       zbar_image_get_height(img));
704     if(!rc) {
705         zbar_image_scanner_enable_cache(proc->scanner, 0);
706         zbar_image_scanner_request_dbus(proc->scanner, proc->is_dbus_enabled);
707         rc = _zbar_process_image(proc, img);
708         if(proc->streaming)
709             zbar_image_scanner_enable_cache(proc->scanner, 1);
710     }
711 
712     _zbar_mutex_lock(&proc->mutex);
713     proc_leave(proc);
714     return(rc);
715 }
716 
zbar_processor_request_dbus(zbar_processor_t * proc,int req_dbus_enabled)717 int zbar_processor_request_dbus (zbar_processor_t *proc,
718                                  int req_dbus_enabled)
719 {
720 #ifdef HAVE_DBUS
721     proc_enter(proc);
722     proc->is_dbus_enabled = req_dbus_enabled;
723     proc_leave(proc);
724     return(0);
725 #else
726     return(1);
727 #endif
728 }
729