qtwaincontext.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * MIT License
  3. *
  4. * Copyright (c) 2020 Alexey Edelev <semlanik@gmail.com>
  5. *
  6. * This file is part of QtTWAIN project https://git.semlanik.org/semlanik/QtTWAIN
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy of this
  9. * software and associated documentation files (the "Software"), to deal in the Software
  10. * without restriction, including without limitation the rights to use, copy, modify,
  11. * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
  12. * to permit persons to whom the Software is furnished to do so, subject to the following
  13. * conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in all copies
  16. * or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  19. * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  20. * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
  21. * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  22. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. */
  25. #include "qtwaincontext_p.h"
  26. #include "qtwainscanner.h"
  27. #include "qtwainscanner_p.h"
  28. #include <QDebug>
  29. using namespace QtTWAIN;
  30. QTWAINContext::QTWAINContext() : m_dsm(QDSMInterface::instance())
  31. , m_state(Initial)
  32. , m_windowHandle(nullptr)
  33. {
  34. //TODO: refactor app identity initialization to real app name read from QApplication
  35. //Ok for now
  36. memset(&m_appIdentity, 0, sizeof(m_appIdentity));
  37. m_appIdentity.Version.MajorNum = 0;
  38. m_appIdentity.Version.MinorNum = 1;
  39. m_appIdentity.Version.Language = TWLG_ENGLISH_USA;
  40. m_appIdentity.Version.Country = TWCY_USA;
  41. memcpy(m_appIdentity.Version.Info, "0.1", sizeof(m_appIdentity.Version.Info) > strlen("0.1") ? strlen("0.1") : sizeof(m_appIdentity.Version.Info));
  42. m_appIdentity.ProtocolMajor = TWON_PROTOCOLMAJOR;
  43. m_appIdentity.ProtocolMinor = TWON_PROTOCOLMINOR;
  44. m_appIdentity.SupportedGroups = DF_APP2 | DG_IMAGE | DG_CONTROL;
  45. memcpy(m_appIdentity.Manufacturer, "QtTWAIN", sizeof(m_appIdentity.Manufacturer) > strlen("QtTWAIN") ? strlen("QtTWAIN") : sizeof(m_appIdentity.Manufacturer));
  46. memcpy(m_appIdentity.ProductFamily, "QtTWAIN", sizeof(m_appIdentity.ProductFamily) > strlen("QtTWAIN") ? strlen("QtTWAIN") : sizeof(m_appIdentity.ProductFamily));
  47. memcpy(m_appIdentity.ProductName, "QtTWAIN", sizeof(m_appIdentity.ProductName) > strlen("QtTWAIN") ? strlen("QtTWAIN") : sizeof(m_appIdentity.ProductName));
  48. memset(&m_status, 0, sizeof(m_status));
  49. }
  50. QTWAINContext::~QTWAINContext()
  51. {
  52. closeDSM();
  53. }
  54. void QTWAINContext::openDSM(const WId winId)
  55. {
  56. if (m_state != Initial) {
  57. qDebug() << "DSM is already opened. Skip.";
  58. return;
  59. }
  60. m_windowHandle = reinterpret_cast<TW_HANDLE>(winId);
  61. if (m_windowHandle != nullptr) {
  62. if (TWRC_SUCCESS != m_dsm->entry(&m_appIdentity, nullptr, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &m_windowHandle)) {
  63. QtTWAIN::QDSMInterface::instance()->entry(&m_appIdentity, nullptr, DG_CONTROL, DAT_STATUS, MSG_GET, &m_status);
  64. qCritical() << "Unable to open DSM: " << m_status.ConditionCode;
  65. return;
  66. }
  67. m_state = DSMOpen;
  68. } else {
  69. qCritical() << "Unable to open without active window on screen";
  70. }
  71. }
  72. void QTWAINContext::closeDSM()
  73. {
  74. if (m_state != DSMOpen) {
  75. qDebug() << "DSM is incorrect state" << m_state << ", unable to close";
  76. return;
  77. }
  78. if (TWRC_SUCCESS == m_dsm->entry(&m_appIdentity, nullptr, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &m_windowHandle)) {
  79. m_windowHandle = nullptr;
  80. }
  81. }
  82. void QTWAINContext::fetchScannerList()
  83. {
  84. m_scannerList.clear();
  85. if (m_state != DSMOpen) {
  86. qCritical() << "Unable to fetch scanner list, DSM is incorrect state";
  87. return;
  88. }
  89. TW_IDENTITY dataSource;
  90. memset(&dataSource, 0, sizeof(TW_IDENTITY));
  91. if (TWRC_SUCCESS == m_dsm->entry(&m_appIdentity, nullptr, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &dataSource)) {
  92. qDebug() << "Default data source: " << dataSource.ProductName;
  93. }
  94. //Populate with all the connected data sources
  95. auto scanner_p = new QTWAINScannerPrivate(this);
  96. int result = m_dsm->entry(&m_appIdentity, nullptr, DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, &scanner_p->dataSource);
  97. do {
  98. if (result == TWRC_SUCCESS) {
  99. qDebug() << "Found scanner: " << scanner_p->dataSource.ProductName;
  100. m_scannerList[QString(m_appIdentity.ProductName)] = std::shared_ptr<QTWAINScanner>(new QTWAINScanner(scanner_p));
  101. } else {
  102. updateStatus();
  103. qDebug() << "Unable to add scanner: " << m_status.ConditionCode;
  104. delete scanner_p;
  105. }
  106. scanner_p = new QTWAINScannerPrivate(this);
  107. result = m_dsm->entry(&m_appIdentity, nullptr, DG_CONTROL, DAT_IDENTITY, MSG_GETNEXT, &(scanner_p->dataSource));
  108. } while(result == TWRC_SUCCESS);
  109. }
  110. void QTWAINContext::userSelectScanner()
  111. {
  112. TW_IDENTITY dataSource;
  113. if (TWRC_SUCCESS != m_dsm->entry(&m_appIdentity, nullptr, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &dataSource)) {
  114. updateStatus();
  115. qDebug() << "Unable to get scanner: " << m_status.ConditionCode;
  116. }
  117. }
  118. bool QTWAINContext::openDS(TW_IDENTITY *dataSource)
  119. {
  120. if (TWRC_SUCCESS != m_dsm->entry(&m_appIdentity, nullptr, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, dataSource)) {
  121. updateStatus();
  122. qDebug() << "Unable to open scanner: " << m_status.ConditionCode;
  123. return false;
  124. }
  125. return true;
  126. }
  127. void QTWAINContext::closeDS(TW_IDENTITY *dataSource)
  128. {
  129. if (TWRC_SUCCESS != m_dsm->entry(&m_appIdentity, nullptr, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, dataSource)) {
  130. updateStatus();
  131. qDebug() << "Unable to close scanner: " << m_status.ConditionCode;
  132. }
  133. }
  134. bool QTWAINContext::enableDS(TW_IDENTITY *dataSource)
  135. {
  136. TW_USERINTERFACE uiSettings;
  137. memset(&uiSettings, 0, sizeof(uiSettings));
  138. uiSettings.ShowUI = true;
  139. uiSettings.hParent = m_windowHandle;
  140. if (TWRC_SUCCESS != m_dsm->entry(&m_appIdentity, dataSource, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &uiSettings)) {
  141. updateStatus();
  142. qDebug() << "Unable to enable scanner: " << m_status.ConditionCode;
  143. return false;
  144. }
  145. return true;
  146. }
  147. bool QTWAINContext::disableDS(TW_IDENTITY *dataSource)
  148. {
  149. TW_USERINTERFACE uiSettings;
  150. memset(&uiSettings, 0, sizeof(uiSettings));
  151. if (TWRC_SUCCESS != m_dsm->entry(&m_appIdentity, dataSource, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &uiSettings)) {
  152. updateStatus();
  153. qDebug() << "Unable to disable scanner: " << m_status.ConditionCode;
  154. return false;
  155. }
  156. return true;
  157. }
  158. bool QTWAINContext::processEvent(TW_EVENT *event, TW_IDENTITY *dataSource)
  159. {
  160. return TWRC_DSEVENT == m_dsm->entry(&m_appIdentity, dataSource, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, event);
  161. }
  162. bool QTWAINContext::imageInfo(TW_IMAGEINFO *info, TW_IDENTITY *dataSource)
  163. {
  164. if (TWRC_SUCCESS != m_dsm->entry(&m_appIdentity, dataSource, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, info)) {
  165. updateStatus();
  166. qDebug() << "Unable to get information about image: " << m_status.ConditionCode;
  167. return false;
  168. }
  169. return true;
  170. }
  171. quint16 QTWAINContext::imageNativeTransfer(TW_HANDLE *imgHandle, TW_IDENTITY *dataSource)
  172. {
  173. return m_dsm->entry(&m_appIdentity, dataSource, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, imgHandle);
  174. }
  175. bool QTWAINContext::endTransfer(TW_PENDINGXFERS *pendingTransfers, TW_IDENTITY *dataSource)
  176. {
  177. if (TWRC_SUCCESS != m_dsm->entry(&m_appIdentity, dataSource, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, pendingTransfers)) {
  178. updateStatus();
  179. qDebug() << "Unable to complete image transfer: " << m_status.ConditionCode;
  180. return false;
  181. }
  182. return true;
  183. }
  184. void QTWAINContext::updateStatus(TW_IDENTITY *dataSource)
  185. {
  186. QtTWAIN::QDSMInterface::instance()->entry(&m_appIdentity, dataSource, DG_CONTROL, DAT_STATUS, MSG_GET, &m_status);
  187. }