lipisharedrecognizer.cpp 13.50 KiB
/****************************************************************************
**
** 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 "lipisharedrecognizer.h"
#include "virtualkeyboarddebug.h"
#include "lipiworker.h"
#include "LTKMacros.h"
#include "LTKInc.h"
#include "LTKTypes.h"
#include "LTKOSUtil.h"
#include "LTKOSUtilFactory.h"
#include "LTKErrorsList.h"
#include "LTKErrors.h"
#include "LTKLogger.h"
#include "LTKConfigFileReader.h"
#include "LTKException.h"
#include "LTKLipiEngineInterface.h"
#include <QDir>
#include <QtCore/QLibraryInfo>
namespace QtVirtualKeyboard {
int LipiSharedRecognizer::s_lipiEngineRefCount = 0;
QString LipiSharedRecognizer::s_lipiRoot;
void *LipiSharedRecognizer::s_lipiEngineHandle = 0;
LipiSharedRecognizer::FN_PTR_CREATELTKLIPIENGINE LipiSharedRecognizer::s_createLTKLipiEngine = 0;
LipiSharedRecognizer::FN_PTR_DELETELTKLIPIENGINE LipiSharedRecognizer::s_deleteLTKLipiEngine = 0;
LTKLipiEngineInterface *LipiSharedRecognizer::s_lipiEngine = 0;
LTKShapeRecognizer *LipiSharedRecognizer::s_shapeRecognizer = 0;
LipiWorker *LipiSharedRecognizer::s_lipiWorker = 0;
QMap<int, QChar> LipiSharedRecognizer::s_unicodeMap;
QString LipiSharedRecognizer::s_activeModel;
stringStringMap LipiSharedRecognizer::s_lipiEngineConfigEntries;
int LipiSharedRecognizer::s_recognitionCount = 0;
/*!
    \class QtVirtualKeyboard::LipiSharedRecognizer
    \internal
LipiSharedRecognizer::LipiSharedRecognizer()
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
loadLipiInterface(); } LipiSharedRecognizer::~LipiSharedRecognizer() { unloadLipiInterface(); } QString LipiSharedRecognizer::model() const { return s_activeModel; } bool LipiSharedRecognizer::setModel(const QString &modelName) { VIRTUALKEYBOARD_DEBUG() << "LipiSharedRecognizer::setModel():" << modelName; if (!s_lipiEngine) { qWarning() << "Engine not initialized"; return false; } if (modelName.isEmpty()) return false; if (modelName == s_activeModel) return true; unloadModelData(); return loadModelData(modelName) == SUCCESS; } void LipiSharedRecognizer::subsetOfClasses(const QString &charset, vector<int> &outSubsetOfClasses) const { outSubsetOfClasses.clear(); outSubsetOfClasses.reserve(charset.length()); #ifdef QT_VIRTUALKEYBOARD_DEBUG QString notFound; #endif for (int i = 0; i < charset.length(); i++) { int classId = s_unicodeMap.key(charset.at(i), -1); if (classId != -1) outSubsetOfClasses.push_back(classId); #ifdef QT_VIRTUALKEYBOARD_DEBUG else notFound.append(charset.at(i)); #endif } #ifdef QT_VIRTUALKEYBOARD_DEBUG if (!notFound.isEmpty()) VIRTUALKEYBOARD_DEBUG() << "LipiSharedRecognizer::subsetOfClasses(): unrecognized characters" << notFound; #endif } QSharedPointer<LipiRecognitionTask> LipiSharedRecognizer::newRecognition(const LTKCaptureDevice& deviceInfo, const LTKScreenContext& screenContext, const vector<int>& inSubsetOfClasses, float confThreshold, int numChoices) { if (!s_lipiEngine || !s_shapeRecognizer || !s_lipiWorker) return QSharedPointer<LipiRecognitionTask>(); QSharedPointer<LipiRecognitionTask> task(new LipiRecognitionTask(deviceInfo, screenContext, inSubsetOfClasses, confThreshold, numChoices, s_recognitionCount));
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
++s_recognitionCount; return task; } QSharedPointer<LipiRecognitionResultsTask> LipiSharedRecognizer::startRecognition(QSharedPointer<LipiRecognitionTask> &recognitionTask) { if (!s_lipiEngine || !s_shapeRecognizer || !s_lipiWorker) return QSharedPointer<LipiRecognitionResultsTask>(); QSharedPointer<LipiRecognitionResultsTask> resultsTask(new LipiRecognitionResultsTask(recognitionTask->resultVector, s_unicodeMap, recognitionTask->resultId())); s_lipiWorker->addTask(recognitionTask); s_lipiWorker->addTask(resultsTask); return resultsTask; } bool LipiSharedRecognizer::cancelRecognition() { if (!s_lipiEngine || !s_shapeRecognizer || !s_lipiWorker) return false; return s_lipiWorker->removeAllTasks() > 0; } bool LipiSharedRecognizer::cancelRecognitionTask(QSharedPointer<LipiRecognitionTask> &recognitionTask) { if (!s_lipiEngine || !s_shapeRecognizer || !s_lipiWorker || !recognitionTask) return false; return recognitionTask->cancelRecognition() || s_lipiWorker->removeTask(recognitionTask) > 0; } int LipiSharedRecognizer::loadLipiInterface() { VIRTUALKEYBOARD_DEBUG() << "LipiSharedRecognizer::loadLipiInterface():" << s_lipiEngineRefCount; if (++s_lipiEngineRefCount == 1) { if (s_lipiRoot.isEmpty()) { if (qEnvironmentVariableIsEmpty("LIPI_ROOT")) { s_lipiRoot = QDir(QLibraryInfo::location(QLibraryInfo::DataPath) + "/qtvirtualkeyboard/lipi_toolkit").absolutePath(); qputenv("LIPI_ROOT", s_lipiRoot.toLatin1()); } else { s_lipiRoot = qgetenv("LIPI_ROOT"); } } QScopedPointer<LTKOSUtil> osUtil(LTKOSUtilFactory::getInstance()); const string lipiRootPath(QDir::toNativeSeparators(s_lipiRoot).toStdString()); int result = osUtil->loadSharedLib(lipiRootPath, LIPIENGINE_MODULE_STR, &s_lipiEngineHandle); if (result != SUCCESS) { qWarning() << QString("Error %1: Could not open shared library for module '%2'").arg(result).arg(LIPIENGINE_MODULE_STR); return result; } result = loadLipiEngineConfig(); if (result != SUCCESS) return result; result = osUtil->getFunctionAddress(s_lipiEngineHandle, "createLTKLipiEngine", (void **)&s_createLTKLipiEngine); if (result != SUCCESS) { qWarning() << QString("Error %1: %2").arg(result).arg(getErrorMessage(result).c_str()); return result; }
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
result = osUtil->getFunctionAddress(s_lipiEngineHandle, "deleteLTKLipiEngine", (void **)&s_deleteLTKLipiEngine); if (result != SUCCESS) { qWarning() << QString("Error %1: %2").arg(result).arg(getErrorMessage(result).c_str()); return result; } s_lipiEngine = s_createLTKLipiEngine(); s_lipiEngine->setLipiRootPath(lipiRootPath); #if 0 s_lipiEngine->setLipiLogFileName(QDir::toNativeSeparators(QString("%1/lipi.log").arg(s_lipiRoot)).toStdString()); s_lipiEngine->setLipiLogLevel("DEBUG"); #endif result = s_lipiEngine->initializeLipiEngine(); if (result != SUCCESS) { qWarning() << QString("Error %1: %2").arg(result).arg(getErrorMessage(result).c_str()); return result; } } return SUCCESS; } void LipiSharedRecognizer::unloadLipiInterface() { VIRTUALKEYBOARD_DEBUG() << "LipiSharedRecognizer::unloadLipiInterface():" << s_lipiEngineRefCount; Q_ASSERT(s_lipiEngineRefCount > 0); if (--s_lipiEngineRefCount == 0) { unloadModelData(); if (s_lipiEngine) { s_deleteLTKLipiEngine(); s_lipiEngine = 0; } s_createLTKLipiEngine = 0; s_deleteLTKLipiEngine = 0; QScopedPointer<LTKOSUtil> osUtil(LTKOSUtilFactory::getInstance()); osUtil->unloadSharedLib(s_lipiEngineHandle); s_lipiEngineHandle = 0; } } int LipiSharedRecognizer::loadLipiEngineConfig() { s_lipiEngineConfigEntries.clear(); const QString &lipiEngineConfigFile(QDir::toNativeSeparators(QString("%1/projects/lipiengine.cfg").arg(s_lipiRoot))); if (!QFileInfo::exists(lipiEngineConfigFile)) { qWarning() << "File not found" << lipiEngineConfigFile; return FAILURE; } try { LTKConfigFileReader configReader(lipiEngineConfigFile.toStdString()); s_lipiEngineConfigEntries = configReader.getCfgFileMap(); } catch (LTKException e) { return e.getErrorCode(); } return SUCCESS; } int LipiSharedRecognizer::resolveLogicalNameToProjectProfile(const QString &logicalName, QString &outProjectName, QString &outProfileName) { outProjectName.clear(); outProfileName.clear(); stringStringMap::const_iterator configEntry = s_lipiEngineConfigEntries.find(logicalName.toStdString()); if (configEntry == s_lipiEngineConfigEntries.end()) return FAILURE;
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
QStringList parts = QString(configEntry->second.c_str()).split('(', QString::SkipEmptyParts); if (parts.length() != 2) return FAILURE; parts[1].replace(')', ""); outProjectName = parts[0].trimmed(); outProfileName = parts[1].trimmed(); return SUCCESS; } int LipiSharedRecognizer::loadModelData(const QString &logicalName) { VIRTUALKEYBOARD_DEBUG() << "LipiSharedRecognizer::loadModelData():" << logicalName; Q_ASSERT(s_shapeRecognizer == 0); Q_ASSERT(s_lipiWorker == 0); #ifdef QT_VIRTUALKEYBOARD_DEBUG QTime perf; perf.start(); #endif s_activeModel = logicalName; QString project; QString profile; int result = resolveLogicalNameToProjectProfile(logicalName, project, profile); if (result == SUCCESS) { string strProject = project.toStdString(); string strProfile = profile.toStdString(); int result = s_lipiEngine->createShapeRecognizer(strProject, strProfile, &s_shapeRecognizer); if (result == SUCCESS) { result = loadMapping(QDir::toNativeSeparators(QString("%1/projects/%2/config/unicodeMapfile_%2.ini").arg(s_lipiRoot).arg(project))); if (result == SUCCESS) { s_lipiWorker = new LipiWorker(s_shapeRecognizer); QSharedPointer<LipiLoadModelDataTask> loadModelDataTask(new LipiLoadModelDataTask()); s_lipiWorker->addTask(loadModelDataTask); s_lipiWorker->start(); } } } #ifdef QT_VIRTUALKEYBOARD_DEBUG if (result == SUCCESS) VIRTUALKEYBOARD_DEBUG() << "LipiSharedRecognizer::loadModelData(): time:" << perf.elapsed() << "ms"; #endif if (result != SUCCESS) { qWarning() << QString("Error %1: %2").arg(result).arg(getErrorMessage(result).c_str()); unloadModelData(); } return result; } void LipiSharedRecognizer::unloadModelData() { if (!s_shapeRecognizer) return; VIRTUALKEYBOARD_DEBUG() << "LipiSharedRecognizer::unloadModelData():" << s_activeModel; #ifdef QT_VIRTUALKEYBOARD_DEBUG QTime perf; perf.start(); #endif
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
if (s_lipiWorker) { delete s_lipiWorker; s_lipiWorker = 0; } s_lipiEngine->deleteShapeRecognizer(s_shapeRecognizer); s_shapeRecognizer = 0; s_unicodeMap.clear(); s_activeModel.clear(); #ifdef QT_VIRTUALKEYBOARD_DEBUG VIRTUALKEYBOARD_DEBUG() << "LipiSharedRecognizer::unloadModelData(): time:" << perf.elapsed() << "ms"; #endif } int LipiSharedRecognizer::loadMapping(const QString &mapFile) { if (!QFileInfo(mapFile).exists()) { qWarning() << "File not found" << mapFile; return FAILURE; } try { LTKConfigFileReader configfilereader(mapFile.toStdString()); const stringStringMap &cfgFileMap = configfilereader.getCfgFileMap(); for (stringStringMap::const_iterator i = cfgFileMap.begin(); i != cfgFileMap.end(); i++) { if (i->first.empty()) continue; if (!QChar(i->first.at(0)).isDigit()) continue; bool ok; int id = QString(i->first.c_str()).toInt(&ok, 10); if (!ok) continue; QChar ch = QChar(QString(i->second.c_str()).toInt(&ok, 16)); if (!ok) continue; s_unicodeMap[id] = ch; } } catch (LTKException) { return FAILURE; } VIRTUALKEYBOARD_DEBUG() << s_unicodeMap; return SUCCESS; } } // namespace QtVirtualKeyboard