diff options
Diffstat (limited to 'qt/QZBarThread.cpp')
-rw-r--r-- | qt/QZBarThread.cpp | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/qt/QZBarThread.cpp b/qt/QZBarThread.cpp new file mode 100644 index 0000000..7675fa3 --- /dev/null +++ b/qt/QZBarThread.cpp @@ -0,0 +1,358 @@ +//------------------------------------------------------------------------ +// Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net> +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ + +#include "QZBarThread.h" +#include <iostream> + +using namespace zbar; + +static const QString textFormat("%1:%2"); + +QZBarThread::QZBarThread(int verbosity) + : _videoOpened(false), reqWidth(DEFAULT_WIDTH), reqHeight(DEFAULT_HEIGHT), + video(NULL), image(NULL), running(true), videoRunning(false), + videoEnabled(false) +{ + zbar_set_verbosity(verbosity); + scanner.set_handler(*this); +} + +void QZBarThread::image_callback(Image &image) +{ + for (Image::SymbolIterator sym = image.symbol_begin(); + sym != image.symbol_end(); ++sym) + if (!sym->get_count()) { + QString data = QString::fromStdString(sym->get_data()); + emit decoded(sym->get_type(), data); + + emit decodedText(textFormat.arg( + QString::fromStdString(sym->get_type_name()), data)); + } +} + +void QZBarThread::processImage(Image &image) +{ + { + scanner.recycle_image(image); + Image tmp = image.convert(*(long *)"Y800"); + scanner.scan(tmp); + image.set_symbols(tmp.get_symbols()); + } + window.draw(image); + if (this->image && this->image != &image) { + delete this->image; + this->image = NULL; + } + emit update(); +} + +void QZBarThread::enableVideo(bool enable) +{ + if (!video) { + videoRunning = videoEnabled = false; + return; + } + try { + scanner.enable_cache(enable); + video->enable(enable); + videoRunning = enable; + } catch (std::exception &e) { + std::cerr << "ERROR: " << e.what() << std::endl; + } + if (!enable) { + // release video image and revert to logo + clear(); + emit update(); + } +} + +void QZBarThread::openVideo(const QString &device) +{ + if (videoRunning) + enableVideo(false); + + { + QMutexLocker locker(&mutex); + videoEnabled = _videoOpened = false; + } + + // ensure old video doesn't have image ref + // (FIXME handle video destroyed w/images outstanding) + clear(); + emit update(); + + if (video) { + delete video; + video = NULL; + emit videoOpened(false); + } + + if (device.isEmpty()) + return; + + try { + std::string devstr = device.toStdString(); + video = new Video(devstr); + + if (reqWidth != DEFAULT_WIDTH || reqHeight != DEFAULT_HEIGHT) + video->request_size(reqWidth, reqHeight); + + negotiate_format(*video, window); + { + QMutexLocker locker(&mutex); + videoEnabled = _videoOpened = true; + reqWidth = video->get_width(); + reqHeight = video->get_height(); + } + currentDevice = device; + + emit videoOpened(true); + } catch (std::exception &e) { + std::cerr << "ERROR: " << e.what() << std::endl; + emit videoOpened(false); + } +} + +void QZBarThread::videoDeviceEvent(VideoDeviceEvent *e) +{ + openVideo(e->device); +} + +void QZBarThread::videoEnabledEvent(VideoEnabledEvent *e) +{ + if (videoRunning && !e->enabled) + enableVideo(false); + videoEnabled = e->enabled; +} + +void QZBarThread::scanImageEvent(ScanImageEvent *e) +{ + if (videoRunning) + enableVideo(false); + + try { + image = new QZBarImage(e->image); + processImage(*image); + } catch (std::exception &e) { + std::cerr << "ERROR: " << e.what() << std::endl; + clear(); + } +} + +bool QZBarThread::event(QEvent *e) +{ + switch ((EventType)e->type()) { + case VideoDevice: + videoDeviceEvent((VideoDeviceEvent *)e); + break; + case VideoEnabled: + videoEnabledEvent((VideoEnabledEvent *)e); + break; + case ScanImage: + scanImageEvent((ScanImageEvent *)e); + break; + case Exit: + if (videoRunning) + enableVideo(false); + running = false; + break; + case ReOpen: + openVideo(currentDevice); + break; + default: + return (false); + } + return (true); +} + +void QZBarThread::run() +{ + QEvent *e = NULL; + while (running) { + if (!videoEnabled) { + QMutexLocker locker(&mutex); + while (queue.isEmpty()) + newEvent.wait(&mutex); + e = queue.takeFirst(); + } else { + // release reference to any previous QImage + clear(); + enableVideo(true); + + while (videoRunning && !e) { + try { + Image image = video->next_image(); + processImage(image); + } catch (std::exception &e) { + std::cerr << "ERROR: " << e.what() << std::endl; + enableVideo(false); + openVideo(""); + } + QMutexLocker locker(&mutex); + if (!queue.isEmpty()) + e = queue.takeFirst(); + } + + if (videoRunning) + enableVideo(false); + } + if (e) { + event(e); + delete e; + e = NULL; + } + } + clear(); + openVideo(""); +} + +QVector<QPair<int, QString> > QZBarThread::get_menu(int index) +{ + QVector<QPair<int, QString> > vector; + struct video_controls_s *ctrl; + + if (!video) + return vector; + + ctrl = video->get_controls(index); + if (!ctrl) + return vector; + + for (unsigned int i = 0; i < ctrl->menu_size; i++) + vector.append(qMakePair((int)ctrl->menu[i].value, + QString::fromUtf8(ctrl->menu[i].name))); + + return vector; +} + +int QZBarThread::get_controls(int index, char **name, char **group, + enum QZBar::ControlType *type, int *min, int *max, + int *def, int *step) +{ + struct video_controls_s *ctrl; + + if (!video) + return 0; + + ctrl = video->get_controls(index); + if (!ctrl) + return 0; + + if (name) + *name = ctrl->name; + if (group) + *group = ctrl->group; + if (min) + *min = ctrl->min; + if (max) + *max = ctrl->max; + if (def) + *def = ctrl->def; + if (step) + *step = ctrl->step; + + if (type) { + switch (ctrl->type) { + case VIDEO_CNTL_INTEGER: + *type = QZBar::Integer; + break; + case VIDEO_CNTL_MENU: + *type = QZBar::Menu; + break; + case VIDEO_CNTL_BUTTON: + *type = QZBar::Button; + break; + case VIDEO_CNTL_INTEGER64: + *type = QZBar::Integer64; + break; + case VIDEO_CNTL_STRING: + *type = QZBar::String; + break; + case VIDEO_CNTL_BOOLEAN: + *type = QZBar::Boolean; + break; + default: + *type = QZBar::Unknown; + break; + } + } + + return 1; +} + +int QZBarThread::set_control(char *name, bool value) +{ + if (!video) + return 0; + + return video->set_control(name, value); +} + +int QZBarThread::set_control(char *name, int value) +{ + if (!video) + return 0; + + return video->set_control(name, value); +} + +int QZBarThread::get_control(char *name, bool *value) +{ + if (!video) + return 0; + + return video->get_control(name, value); +} + +int QZBarThread::get_control(char *name, int *value) +{ + if (!video) + return 0; + + return video->get_control(name, value); +} + +void QZBarThread::request_size(unsigned width, unsigned height) +{ + reqWidth = width; + reqHeight = height; +} + +int QZBarThread::get_resolution(int index, unsigned &width, unsigned &height, + float &max_fps) +{ + struct video_resolution_s *res; + + if (!video) + return 0; + + res = video->get_resolution(index); + if (!res) + return 0; + + width = res->width; + height = res->height; + max_fps = res->max_fps; + + return 1; +} |