summaryrefslogtreecommitdiffstats
path: root/qt/QZBarThread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt/QZBarThread.cpp')
-rw-r--r--qt/QZBarThread.cpp358
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;
+}