static inline int zbar_gtk_process_image (ZBarGtk *self, zbar_image_t *image) { ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); if(!image) return(-1); zbar_image_t *tmp = zbar_image_convert(image, fourcc('Y','8','0','0')); if(!tmp) return(-1); zbar_image_scanner_recycle_image(zbar->scanner, image); int rc = zbar_scan_image(zbar->scanner, tmp); zbar_image_set_symbols(image, zbar_image_get_symbols(tmp)); zbar_image_destroy(tmp); if(rc < 0) return(rc); gdk_threads_enter(); if(rc && zbar->thread) { /* update decode results */ const zbar_symbol_t *sym; for(sym = zbar_image_first_symbol(image); sym; sym = zbar_symbol_next(sym)) if(!zbar_symbol_get_count(sym)) { zbar_symbol_type_t type = zbar_symbol_get_type(sym); const char *data = zbar_symbol_get_data(sym); g_signal_emit(self, zbar_gtk_signals[DECODED], 0, type, data); /* FIXME skip this when unconnected? */ gchar *text = g_strconcat(zbar_get_symbol_name(type), zbar_get_addon_name(type), ":", data, NULL); g_signal_emit(self, zbar_gtk_signals[DECODED_TEXT], 0, text); g_free(text); } } if(zbar->window) { rc = zbar_window_draw(zbar->window, image); gtk_widget_queue_draw(GTK_WIDGET(self)); } else rc = -1; gdk_threads_leave(); return(rc); }
int zbar_processor_set_active (zbar_processor_t *proc, int active) { proc_enter(proc); int rc; if(!proc->video) { rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video input not initialized"); goto done; } _zbar_mutex_unlock(&proc->mutex); zbar_image_scanner_enable_cache(proc->scanner, active); rc = zbar_video_enable(proc->video, active); if(!rc) { _zbar_mutex_lock(&proc->mutex); proc->streaming = active; _zbar_mutex_unlock(&proc->mutex); rc = _zbar_processor_enable(proc); } else err_copy(proc, proc->video); if(!proc->streaming && proc->window) { if(zbar_window_draw(proc->window, NULL) && !rc) rc = err_copy(proc, proc->window); _zbar_processor_invalidate(proc); } _zbar_mutex_lock(&proc->mutex); if(proc->video_thread.started) _zbar_event_trigger(&proc->video_thread.notify); done: proc_leave(proc); return(rc); }
int zbar_window_attach (zbar_window_t *w, void *display, unsigned long drawable) { /* release image */ zbar_window_draw(w, NULL); if(w->cleanup) { w->cleanup(w); w->cleanup = NULL; w->draw_image = NULL; } if(w->formats) { free(w->formats); w->formats = NULL; } w->src_format = 0; w->src_width = w->src_height = 0; w->scaled_size.x = w->scaled_size.y = 0; w->dst_width = w->dst_height = 0; w->max_width = w->max_height = 1 << 15; w->scale_num = w->scale_den = 1; return(_zbar_window_attach(w, display, drawable)); }
/* API lock is already held */ int _zbar_process_image (zbar_processor_t *proc, zbar_image_t *img) { uint32_t force_fmt = proc->force_output; if(img) { if(proc->dumping) { zbar_image_write(proc->window->image, "zbar"); proc->dumping = 0; } uint32_t format = zbar_image_get_format(img); zprintf(16, "processing: %.4s(%08" PRIx32 ") %dx%d @%p\n", (char*)&format, format, zbar_image_get_width(img), zbar_image_get_height(img), zbar_image_get_data(img)); /* FIXME locking all other interfaces while processing is conservative * but easier for now and we don't expect this to take long... */ zbar_image_t *tmp = zbar_image_convert(img, fourcc('Y','8','0','0')); if(!tmp) goto error; if(proc->syms) { zbar_symbol_set_ref(proc->syms, -1); proc->syms = NULL; } zbar_image_scanner_recycle_image(proc->scanner, img); int nsyms = zbar_scan_image(proc->scanner, tmp); _zbar_image_swap_symbols(img, tmp); zbar_image_destroy(tmp); tmp = NULL; if(nsyms < 0) goto error; proc->syms = zbar_image_scanner_get_results(proc->scanner); if(proc->syms) zbar_symbol_set_ref(proc->syms, 1); if(_zbar_verbosity >= 8) { const zbar_symbol_t *sym = zbar_image_first_symbol(img); while(sym) { zbar_symbol_type_t type = zbar_symbol_get_type(sym); int count = zbar_symbol_get_count(sym); zprintf(8, "%s: %s (%d pts) (dir=%d) (q=%d) (%s)\n", zbar_get_symbol_name(type), zbar_symbol_get_data(sym), zbar_symbol_get_loc_size(sym), zbar_symbol_get_orientation(sym), zbar_symbol_get_quality(sym), (count < 0) ? "uncertain" : (count > 0) ? "duplicate" : "new"); sym = zbar_symbol_next(sym); } } if(nsyms) { /* FIXME only call after filtering */ _zbar_mutex_lock(&proc->mutex); _zbar_processor_notify(proc, EVENT_OUTPUT); _zbar_mutex_unlock(&proc->mutex); if(proc->handler) proc->handler(img, proc->userdata); } if(force_fmt) { zbar_symbol_set_t *syms = img->syms; img = zbar_image_convert(img, force_fmt); if(!img) goto error; img->syms = syms; zbar_symbol_set_ref(syms, 1); } } /* display to window if enabled */ int rc = 0; if(proc->window) { if((rc = zbar_window_draw(proc->window, img))) err_copy(proc, proc->window); _zbar_processor_invalidate(proc); } if(force_fmt && img) zbar_image_destroy(img); return(rc); error: return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "unknown image format")); }
static void *zbar_gtk_processing_thread (void *arg) { ZBarGtk *self = ZBAR_GTK(arg); if(!self->_private) return(NULL); ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); g_object_ref(zbar); g_assert(zbar->queue); g_async_queue_ref(zbar->queue); zbar->scanner = zbar_image_scanner_create(); g_assert(zbar->scanner); /* thread side enabled state */ gboolean video_enabled = FALSE; GValue *msg = NULL; while(TRUE) { if(!msg) msg = g_async_queue_pop(zbar->queue); g_assert(G_IS_VALUE(msg)); GType type = G_VALUE_TYPE(msg); if(type == G_TYPE_INT) { /* video state change */ int state = g_value_get_int(msg); if(state < 0) { /* terminate processing thread */ g_value_unset(msg); g_free(msg); msg = NULL; break; } g_assert(state >= 0 && state <= 1); video_enabled = (state != 0); } else if(type == G_TYPE_STRING) { /* open new video device */ const char *video_device = g_value_get_string(msg); video_enabled = zbar_gtk_video_open(self, video_device); } else if(type == GDK_TYPE_PIXBUF) { /* scan provided image and broadcast results */ zbar_image_t *image = zbar_image_create(); GdkPixbuf *pixbuf = GDK_PIXBUF(g_value_dup_object(msg)); if(zbar_gtk_image_from_pixbuf(image, pixbuf)) zbar_gtk_process_image(self, image); else g_object_unref(pixbuf); zbar_image_destroy(image); } else { gchar *dbg = g_strdup_value_contents(msg); g_warning("unknown message type (%x) passed to thread: %s\n", (unsigned)type, dbg); g_free(dbg); } g_value_unset(msg); g_free(msg); msg = NULL; if(video_enabled) { /* release reference to any previous pixbuf */ zbar_window_draw(zbar->window, NULL); if(zbar_video_enable(zbar->video, 1)) { zbar_video_error_spew(zbar->video, 0); video_enabled = FALSE; continue; } zbar_image_scanner_enable_cache(zbar->scanner, 1); while(video_enabled && !(msg = g_async_queue_try_pop(zbar->queue))) { zbar_image_t *image = zbar_video_next_image(zbar->video); if(zbar_gtk_process_image(self, image) < 0) video_enabled = FALSE; if(image) zbar_image_destroy(image); } zbar_image_scanner_enable_cache(zbar->scanner, 0); if(zbar_video_enable(zbar->video, 0)) { zbar_video_error_spew(zbar->video, 0); video_enabled = FALSE; } /* release video image and revert to logo */ if(zbar->window) { zbar_window_draw(zbar->window, NULL); gtk_widget_queue_draw(GTK_WIDGET(self)); } if(!video_enabled) /* must have been an error while streaming */ zbar_gtk_video_open(self, NULL); } } if(zbar->window) zbar_window_draw(zbar->window, NULL); g_object_unref(zbar); return(NULL); }
static inline gboolean zbar_gtk_video_open (ZBarGtk *self, const char *video_device) { ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); gboolean video_opened = FALSE; gdk_threads_enter(); zbar->req_width = DEFAULT_WIDTH; zbar->req_height = DEFAULT_HEIGHT; gtk_widget_queue_resize(GTK_WIDGET(self)); zbar->video_opened = FALSE; if(zbar->thread) g_object_notify(G_OBJECT(self), "video-opened"); if(zbar->window) { /* ensure old video doesn't have image ref * (FIXME handle video destroyed w/images outstanding) */ zbar_window_draw(zbar->window, NULL); gtk_widget_queue_draw(GTK_WIDGET(self)); } gdk_threads_leave(); if(zbar->video) { zbar_video_destroy(zbar->video); zbar->video = NULL; } if(video_device && video_device[0] && zbar->thread) { /* create video * FIXME video should support re-open */ zbar->video = zbar_video_create(); g_assert(zbar->video); if(zbar_video_open(zbar->video, video_device)) { zbar_video_error_spew(zbar->video, 0); zbar_video_destroy(zbar->video); zbar->video = NULL; /* FIXME error propagation */ return(FALSE); } /* negotiation accesses the window format list, * so we hold the lock for this part */ gdk_threads_enter(); video_opened = !zbar_negotiate_format(zbar->video, zbar->window); if(video_opened) { zbar->req_width = zbar_video_get_width(zbar->video); zbar->req_height = zbar_video_get_height(zbar->video); } gtk_widget_queue_resize(GTK_WIDGET(self)); zbar->video_opened = video_opened; if(zbar->thread) g_object_notify(G_OBJECT(self), "video-opened"); gdk_threads_leave(); } return(video_opened); }