/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 or (at your option) any later version ** approved by the KDE Free Qt Foundation. The licenses are as published by ** the Free Software Foundation and appearing in the file LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lipiworker_p.h" #include #include #include "LTKShapeRecognizer.h" #include "LTKErrors.h" QT_BEGIN_NAMESPACE namespace QtVirtualKeyboard { Q_DECLARE_LOGGING_CATEGORY(lcLipi) /*! \class QtVirtualKeyboard::LipiTask \internal */ /*! \class QtVirtualKeyboard::LipiLoadModelDataTask \internal */ void LipiLoadModelDataTask::run() { qCDebug(lcLipi) << "LipiLoadModelDataTask::run()"; QTime perf; perf.start(); int result = shapeRecognizer->loadModelData(); qCDebug(lcLipi) << "LipiLoadModelDataTask::run(): time:" << perf.elapsed() << "ms"; if (result != SUCCESS) qCWarning(lcLipi) << QStringLiteral("Error %1: %2").arg(result).arg(QLatin1String(getErrorMessage(result).c_str())); } /*! \class QtVirtualKeyboard::LipiRecognitionTask \internal */ LipiRecognitionTask::LipiRecognitionTask(const LTKCaptureDevice& deviceInfo, const LTKScreenContext& screenContext, const vector& inSubsetOfClasses, float confThreshold, int numChoices, int resultId) : LipiTask(), deviceInfo(deviceInfo), screenContext(screenContext), inSubsetOfClasses(inSubsetOfClasses), confThreshold(confThreshold), numChoices(numChoices), resultVector(new vector()), _resultId(resultId), stateRunning(false), stateCancelled(false) { } void LipiRecognitionTask::run() { qCDebug(lcLipi) << "LipiRecognitionTask::run()"; if (!shapeRecognizer || !resultVector) return; { QMutexLocker stateGuard(&stateLock); stateRunning = true; } resultVector->clear(); resultVector->reserve(numChoices); shapeRecognizer->setDeviceContext(deviceInfo); QTime perf; perf.start(); shapeRecognizer->recognize(traceGroup, screenContext, inSubsetOfClasses, confThreshold, numChoices, *resultVector); int perfElapsed = perf.elapsed(); { QMutexLocker stateGuard(&stateLock); stateRunning = false; if (stateCancelled) resultVector->clear(); qCDebug(lcLipi) << "LipiRecognitionTask::run(): time:" << perfElapsed << "ms" << (stateCancelled ? "(cancelled)" : ""); } } bool LipiRecognitionTask::cancelRecognition() { QMutexLocker stateGuard(&stateLock); stateCancelled = true; bool result = (stateRunning && shapeRecognizer); if (result) shapeRecognizer->requestCancelRecognition(); return result; } int LipiRecognitionTask::resultId() const { return _resultId; } /*! \class QtVirtualKeyboard::LipiRecognitionResultsTask \internal */ LipiRecognitionResultsTask::LipiRecognitionResultsTask(QSharedPointer > resultVector, const QMap &unicodeMap, int resultId) : LipiTask(), resultVector(resultVector), unicodeMap(unicodeMap), _resultId(resultId) { } void LipiRecognitionResultsTask::run() { if (!resultVector || unicodeMap.isEmpty()) return; QVariantList resultList; for (vector::const_iterator i = resultVector->begin(); i != resultVector->end(); i++) { QVariantMap result; int shapeId = i->getShapeId(); result[QLatin1String("resultId")] = _resultId; result[QLatin1String("shapeId")] = shapeId; result[QLatin1String("unicode")] = unicodeMap.value(shapeId); result[QLatin1String("confidence")] = i->getConfidence(); resultList.append(result); } if (resultList.isEmpty()) return; emit resultsAvailable(resultList); } /*! \class QtVirtualKeyboard::LipiWorker \internal */ LipiWorker::LipiWorker(LTKShapeRecognizer *shapeRecognizer, QObject *parent) : QThread(parent), taskSema(), taskLock(), shapeRecognizer(shapeRecognizer) { abort = false; } LipiWorker::~LipiWorker() { abort = true; taskSema.release(); wait(); if (shapeRecognizer) shapeRecognizer->unloadModelData(); } void LipiWorker::addTask(QSharedPointer task) { if (task) { QMutexLocker guard(&taskLock); taskList.append(task); taskSema.release(); } } int LipiWorker::removeTask(QSharedPointer task) { int count = 0; if (task) { QMutexLocker guard(&taskLock); count = taskList.removeAll(task); taskSema.acquire(qMin(count, taskSema.available())); } return count; } int LipiWorker::removeAllTasks() { QMutexLocker guard(&taskLock); int count = taskList.count(); taskList.clear(); if (taskSema.available()) taskSema.acquire(taskSema.available()); return count; } void LipiWorker::run() { while (!abort) { taskSema.acquire(); if (abort) break; QSharedPointer currentTask; { QMutexLocker guard(&taskLock); if (!taskList.isEmpty()) { currentTask = taskList.front(); taskList.pop_front(); } } if (currentTask) { currentTask->shapeRecognizer = shapeRecognizer; currentTask->run(); } } } } // namespace QtVirtualKeyboard QT_END_NAMESPACE