File indexing completed on 2024-10-27 07:30:04

0001 /*
0002  * SPDX-FileCopyrightText: 2009 Grzegorz Kurtyka <grzegorz dot kurtyka at gmail dot com>
0003  * SPDX-FileCopyrightText: 2010 Kare Sars <kare dot sars at iki dot fi>
0004  * SPDX-FileCopyrightText: 2014 Gregor Mitsch : port to KDE5 frameworks
0005  *
0006  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007  */
0008 
0009 #include "finddevicesthread.h"
0010 
0011 // Sane includes
0012 extern "C"
0013 {
0014 #include <sane/saneopts.h>
0015 #include <sane/sane.h>
0016 }
0017 
0018 #include <QMutex>
0019 #include <QMutexLocker>
0020 
0021 #include <ksanecore_debug.h>
0022 
0023 #include "deviceinformation_p.h"
0024 
0025 namespace KSaneCore
0026 {
0027 static FindSaneDevicesThread *s_instancesane = nullptr;
0028 Q_GLOBAL_STATIC(QMutex, s_mutexsane)
0029 
0030 class InternalDeviceInformation : public DeviceInformation
0031 {
0032 public:
0033     InternalDeviceInformation(const QString &name, const QString &vendor,
0034                               const QString &model, const QString &type)
0035     {
0036         d->name = name;
0037         d->model = model;
0038         d->vendor = vendor;
0039         d->type = type;
0040     }
0041 };
0042 
0043 FindSaneDevicesThread *FindSaneDevicesThread::getInstance()
0044 {
0045 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0046     QMutexLocker<QMutex> locker(s_mutexsane);
0047 #else
0048     QMutexLocker locker(s_mutexsane);
0049 #endif
0050 
0051     if (s_instancesane == nullptr) {
0052         s_instancesane = new FindSaneDevicesThread();
0053     }
0054 
0055     return s_instancesane;
0056 }
0057 
0058 FindSaneDevicesThread::FindSaneDevicesThread() : QThread(nullptr)
0059 {
0060 }
0061 
0062 FindSaneDevicesThread::~FindSaneDevicesThread()
0063 {
0064 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0065     QMutexLocker<QMutex> locker(s_mutexsane);
0066 #else
0067     QMutexLocker locker(s_mutexsane);
0068 #endif
0069     qDeleteAll(m_deviceList);
0070     wait();
0071 }
0072 
0073 void FindSaneDevicesThread::run()
0074 {
0075     SANE_Device const **devList;
0076     SANE_Status         status;
0077 
0078     // This is unfortunately not very reliable as many back-ends do not refresh
0079     // the device list after the sane_init() call...
0080     status = sane_get_devices(&devList, SANE_FALSE);
0081 
0082     qDeleteAll(m_deviceList);
0083     m_deviceList.clear();
0084     if (status == SANE_STATUS_GOOD) {
0085         int i = 0;
0086 
0087         while (devList[i] != nullptr) {
0088             /* Do not list cameras as scanner devices when requested.
0089              * Strings taken from SANE API documentation. */
0090             const QString type = QString::fromUtf8(devList[i]->type);
0091             if (m_deviceType == Interface::AllDevices
0092                 || (m_deviceType == Interface::NoCameraAndVirtualDevices && type != QLatin1String("still camera") && type != QLatin1String("video camera")
0093                     && type != QLatin1String("virtual device"))) {
0094                 InternalDeviceInformation *device = new InternalDeviceInformation(QString::fromUtf8(devList[i]->name),
0095                                                                                   QString::fromUtf8(devList[i]->vendor),
0096                                                                                   QString::fromUtf8(devList[i]->model),
0097                                                                                   type);
0098                 m_deviceList.append(std::move(device));
0099                 qCDebug(KSANECORE_LOG) << "Adding device " << device->vendor() << device->name() << device->model() << device->type() << " to device list";
0100             } else {
0101                 qCDebug(KSANECORE_LOG) << "Ignoring device type" << type;
0102             }
0103             i++;
0104         }
0105     }
0106 }
0107 
0108 QList<DeviceInformation *> FindSaneDevicesThread::devicesList() const
0109 {
0110     return m_deviceList;
0111 }
0112 
0113 void FindSaneDevicesThread::setDeviceType(const Interface::DeviceType type)
0114 {
0115     m_deviceType = type;
0116 }
0117 
0118 } // namespace KSaneCore
0119 
0120 #include "moc_finddevicesthread.cpp"