800 lines
19 KiB
C++
800 lines
19 KiB
C++
#include "HGSaneImpl.hpp"
|
|
#include "../base/HGInc.h"
|
|
|
|
HGSaneManagerImpl::HGSaneManagerImpl()
|
|
{
|
|
|
|
}
|
|
|
|
HGSaneManagerImpl::~HGSaneManagerImpl()
|
|
{
|
|
|
|
}
|
|
|
|
HGResult HGSaneManagerImpl::Create()
|
|
{
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneManagerImpl::Destroy()
|
|
{
|
|
if (!m_listSourceImpl.empty())
|
|
{
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneManagerImpl::GetSourceCount(HGUInt *count)
|
|
{
|
|
if (NULL == count)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
*count = (HGUInt)m_vSource.size();
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneManagerImpl::GetSourceName(HGUInt index, HGChar* name, HGUInt maxLen)
|
|
{
|
|
if (index >= (HGUInt)m_vSource.size() || NULL == name || 0 == maxLen)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
if (maxLen < m_vSource[index].first.size() + 1)
|
|
return HGBASE_ERR_FAIL;
|
|
strcpy(name, m_vSource[index].first.c_str());
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneManagerImpl::OpenSource(HGUInt index, class HGSaneSourceImpl **sourceImpl)
|
|
{
|
|
if (index >= (HGUInt)m_vSource.size() || NULL == sourceImpl)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
HGSaneSourceImpl *newSourceImpl = new HGSaneSourceImpl(this);
|
|
HGResult ret = newSourceImpl->Open(m_vSource[index].first.c_str(), m_vSource[index].second.c_str());
|
|
if (HGBASE_ERR_OK != ret)
|
|
{
|
|
delete newSourceImpl;
|
|
return ret;
|
|
}
|
|
|
|
m_listSourceImpl.push_back(newSourceImpl);
|
|
*sourceImpl = newSourceImpl;
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneManagerImpl::OpenSelectedSource(HGWindow parent, class HGSaneSourceImpl **sourceImpl)
|
|
{
|
|
if (NULL == sourceImpl)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
HGDll dll = NULL;
|
|
f_sane_init fInit = NULL;
|
|
f_sane_exit fExit = NULL;
|
|
SANEAPI saneAPI;
|
|
if (-2 == show_srclist_ui(parent, &dll, &fInit, &fExit, &saneAPI))
|
|
{
|
|
return HGBASE_ERR_NOTSUPPORT;
|
|
}
|
|
|
|
if (NULL == dll)
|
|
{
|
|
return HGSANE_ERR_FAIL;
|
|
}
|
|
|
|
HGSaneSourceImpl* newSourceImpl = new HGSaneSourceImpl(this);
|
|
HGResult ret = newSourceImpl->Init(dll, fInit, fExit, &saneAPI);
|
|
if (HGBASE_ERR_OK != ret)
|
|
{
|
|
delete newSourceImpl;
|
|
HGBase_DestroyDll(dll);
|
|
return ret;
|
|
}
|
|
|
|
m_listSourceImpl.push_back(newSourceImpl);
|
|
*sourceImpl = newSourceImpl;
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
void HGSaneManagerImpl::RemoveSource(class HGSaneSourceImpl* sourceImpl)
|
|
{
|
|
std::list<class HGSaneSourceImpl*>::iterator iter;
|
|
for (iter = m_listSourceImpl.begin(); iter != m_listSourceImpl.end(); ++iter)
|
|
{
|
|
if (*iter == sourceImpl)
|
|
{
|
|
m_listSourceImpl.erase(iter);
|
|
delete sourceImpl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
HGSaneSourceImpl::HGSaneSourceImpl(HGSaneManagerImpl *managerImpl)
|
|
{
|
|
m_managerImpl = managerImpl;
|
|
m_manuName.clear();
|
|
m_dll = NULL;
|
|
m_f_sane_init = NULL;
|
|
m_f_sane_exit = NULL;
|
|
memset(&m_saneApi, 0, sizeof(SANEAPI));
|
|
}
|
|
|
|
HGSaneSourceImpl::~HGSaneSourceImpl()
|
|
{
|
|
|
|
}
|
|
|
|
HGResult HGSaneSourceImpl::Init(const HGChar* saneManu, HGDll dll, f_sane_init fInit, f_sane_exit fExit, const SANEAPI *saneAPI)
|
|
{
|
|
assert(NULL == m_dll);
|
|
|
|
if (NULL == dll || NULL == fInit || NULL == fExit || NULL == saneAPI)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
if (NULL == saneAPI->sane_open_api || NULL == saneAPI->sane_close_api
|
|
|| NULL == saneAPI->sane_start_api || NULL == saneAPI->sane_read_api
|
|
|| NULL == saneAPI->sane_cancel_api || NULL == saneAPI->sane_get_devices_api
|
|
|| NULL == saneAPI->sane_get_option_descriptor_api || NULL == saneAPI->sane_control_option_api
|
|
|| NULL == saneAPI->sane_get_parameters_api || saneAPI->sane_set_io_mode_api
|
|
|| NULL == saneAPI->sane_strstatus_api || NULL == saneAPI->sane_io_control_api)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
if (SANE_STATUS_GOOD != fInit(NULL, NULL))
|
|
{
|
|
return HGSANE_ERR_FAIL;
|
|
}
|
|
|
|
m_manuName = saneManu;
|
|
m_dll = dll;
|
|
m_f_sane_init = fInit;
|
|
m_f_sane_exit = fExit;
|
|
memcpy(&m_saneApi, saneAPI, sizeof(SANEAPI));
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneSourceImpl::Open(const HGChar* saneManu, const HGChar* sanePath)
|
|
{
|
|
assert(NULL == m_dll);
|
|
|
|
if (NULL == saneManu || 0 == *saneManu
|
|
|| NULL == sanePath || 0 == *sanePath)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
HGResult ret = HGBase_CreateDll(sanePath, &m_dll);
|
|
if (HGBASE_ERR_OK != ret)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
ret = FindFunctions(saneManu);
|
|
if (HGBASE_ERR_OK != ret)
|
|
{
|
|
HGBase_DestroyDll(m_dll);
|
|
m_dll = NULL;
|
|
return ret;
|
|
}
|
|
|
|
if (SANE_STATUS_GOOD != m_f_sane_init(NULL, NULL))
|
|
{
|
|
HGBase_DestroyDll(m_dll);
|
|
m_dll = NULL;
|
|
return HGSANE_ERR_FAIL;
|
|
}
|
|
|
|
m_manuName = saneManu;
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneSourceImpl::Close()
|
|
{
|
|
assert(NULL != m_dll);
|
|
|
|
if (!m_listDeviceImpl.empty())
|
|
{
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
m_f_sane_exit();
|
|
HGBase_DestroyDll(m_dll);
|
|
m_dll = NULL;
|
|
m_managerImpl->RemoveSource(this);
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneSourceImpl::GetName(HGChar* name, HGUInt maxLen)
|
|
{
|
|
if (NULL == name || 0 == maxLen)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
if (maxLen < m_manuName.size() + 1)
|
|
return HGBASE_ERR_FAIL;
|
|
strcpy(name, m_manuName.c_str());
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneSourceImpl::GetDeviceCount(HGUInt* count)
|
|
{
|
|
if (NULL == count)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
const SANE_Device** device_list;
|
|
if (SANE_STATUS_GOOD != m_saneApi.sane_get_devices_api(&device_list, SANE_TRUE))
|
|
{
|
|
return HGSANE_ERR_FAIL;
|
|
}
|
|
|
|
*count = 0;
|
|
const SANE_Device** p;
|
|
for (p = device_list; *p != NULL; ++p)
|
|
++(*count);
|
|
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneSourceImpl::GetDeviceName(HGUInt index, HGChar* name, HGUInt maxLen)
|
|
{
|
|
if (NULL == name || 0 == maxLen)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
const SANE_Device** device_list;
|
|
if (SANE_STATUS_GOOD != m_saneApi.sane_get_devices_api(&device_list, SANE_TRUE))
|
|
{
|
|
return HGSANE_ERR_FAIL;
|
|
}
|
|
|
|
HGUInt count = 0;
|
|
const SANE_Device** p;
|
|
for (p = device_list; *p != NULL; ++p)
|
|
++count;
|
|
|
|
if (index >= count)
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
if (NULL == device_list[index]->name)
|
|
return HGBASE_ERR_FAIL;
|
|
if (maxLen < strlen(device_list[index]->name) + 1)
|
|
return HGBASE_ERR_FAIL;
|
|
strcpy(name, device_list[index]->name);
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneSourceImpl::OpenDevice(HGUInt index, HGSaneDeviceImpl** deviceImpl, HGChar* errInfo, HGUInt errInfoLen)
|
|
{
|
|
if (NULL == deviceImpl)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
const SANE_Device** device_list;
|
|
if (SANE_STATUS_GOOD != m_saneApi.sane_get_devices_api(&device_list, SANE_TRUE))
|
|
{
|
|
return HGSANE_ERR_FAIL;
|
|
}
|
|
|
|
HGUInt count = 0;
|
|
const SANE_Device** p;
|
|
for (p = device_list; *p != NULL; ++p)
|
|
++count;
|
|
|
|
if (index >= count)
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
HGSaneDeviceImpl* newDeviceImpl = new HGSaneDeviceImpl(this);
|
|
HGResult ret = newDeviceImpl->Open(device_list[index]->name, errInfo, errInfoLen);
|
|
if (HGBASE_ERR_OK != ret)
|
|
{
|
|
delete newDeviceImpl;
|
|
return ret;
|
|
}
|
|
|
|
m_listDeviceImpl.push_back(newDeviceImpl);
|
|
*deviceImpl = newDeviceImpl;
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneSourceImpl::OpenSelectedDevice(HGWindow parent, class HGSaneDeviceImpl** deviceImpl)
|
|
{
|
|
if (NULL == deviceImpl)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
SANE_Handle handle = NULL;
|
|
char devName[256] = {0};
|
|
if (-2 == show_devlist_ui(&m_saneApi, parent, &handle, devName, 256))
|
|
{
|
|
return HGBASE_ERR_NOTSUPPORT;
|
|
}
|
|
|
|
if (NULL == handle)
|
|
{
|
|
return HGSANE_ERR_FAIL;
|
|
}
|
|
|
|
HGSaneDeviceImpl* newDeviceImpl = new HGSaneDeviceImpl(this);
|
|
HGResult ret = newDeviceImpl->Init(devName, handle);
|
|
if (HGBASE_ERR_OK != ret)
|
|
{
|
|
delete newDeviceImpl;
|
|
m_saneApi.sane_close_api(handle);
|
|
return ret;
|
|
}
|
|
|
|
m_listDeviceImpl.push_back(newDeviceImpl);
|
|
*deviceImpl = newDeviceImpl;
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneSourceImpl::FindFunctions(const HGChar* saneManu)
|
|
{
|
|
HGResult ret = HGBASE_ERR_OK;
|
|
|
|
do
|
|
{
|
|
HGChar funcName[256];
|
|
|
|
sprintf(funcName, "sane_%s_init", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_f_sane_init);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_exit", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_f_sane_exit);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_get_devices", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_get_devices_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_open", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_open_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_close", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_close_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_start", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_start_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_read", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_read_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_cancel", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_cancel_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_set_io_mode", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_set_io_mode_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_strstatus", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_strstatus_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_get_parameters", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_get_parameters_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_get_option_descriptor", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_get_option_descriptor_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_control_option", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_control_option_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
sprintf(funcName, "sane_%s_io_control", saneManu);
|
|
ret = HGBase_GetDllProcAddress(m_dll, funcName, (HGPointer*)&m_saneApi.sane_io_control_api);
|
|
if (HGBASE_ERR_OK != ret)
|
|
break;
|
|
|
|
} while (0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void HGSaneSourceImpl::RemoveDevice(class HGSaneDeviceImpl* deviceImpl)
|
|
{
|
|
std::list<class HGSaneDeviceImpl*>::iterator iter;
|
|
for (iter = m_listDeviceImpl.begin(); iter != m_listDeviceImpl.end(); ++iter)
|
|
{
|
|
if (*iter == deviceImpl)
|
|
{
|
|
m_listDeviceImpl.erase(iter);
|
|
delete deviceImpl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
HGSaneDeviceImpl::HGSaneDeviceImpl(HGSaneSourceImpl* sourceImpl)
|
|
{
|
|
m_sourceImpl = sourceImpl;
|
|
m_devName.clear();
|
|
m_devHandle = NULL;
|
|
m_buffer = NULL;
|
|
m_bufferSize = 0;
|
|
m_dpi = 0;
|
|
m_eventFunc = NULL;
|
|
m_eventParam = NULL;
|
|
m_imageFunc = NULL;
|
|
m_imageParam = NULL;
|
|
m_stopThread = HGFALSE;
|
|
m_thread = NULL;
|
|
}
|
|
|
|
HGSaneDeviceImpl::~HGSaneDeviceImpl()
|
|
{
|
|
|
|
}
|
|
|
|
HGResult HGSaneDeviceImpl::Init(const HGChar* devName, SANE_Handle handle)
|
|
{
|
|
assert(NULL == m_devHandle);
|
|
|
|
if (NULL == devName || NULL == handle)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
m_devName = devName;
|
|
m_sourceImpl->m_saneApi.sane_set_io_mode_api(handle, SANE_FALSE);
|
|
m_devHandle = handle;
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneDeviceImpl::Open(const HGChar* devName, HGChar* errInfo, HGUInt errInfoLen)
|
|
{
|
|
assert(NULL == m_devHandle);
|
|
|
|
if (NULL == devName)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
SANE_Handle handle = NULL;
|
|
SANE_Status stat = m_sourceImpl->m_saneApi.sane_open_api(devName, &handle);
|
|
if (SANE_STATUS_GOOD != stat)
|
|
{
|
|
if (NULL != errInfo)
|
|
{
|
|
const char* err = m_sourceImpl->m_saneApi.sane_strstatus_api(stat);
|
|
if (NULL != err && errInfoLen >= strlen(err) + 1)
|
|
{
|
|
strcpy(errInfo, err);
|
|
}
|
|
}
|
|
|
|
return HGSANE_ERR_FAIL;
|
|
}
|
|
|
|
m_devName = devName;
|
|
m_sourceImpl->m_saneApi.sane_set_io_mode_api(handle, SANE_FALSE);
|
|
m_devHandle = handle;
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneDeviceImpl::Close()
|
|
{
|
|
assert(NULL != m_devHandle);
|
|
|
|
Stop();
|
|
m_sourceImpl->m_saneApi.sane_close_api(m_devHandle);
|
|
m_devHandle = NULL;
|
|
m_devName.clear();
|
|
m_sourceImpl->RemoveDevice(this);
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneDeviceImpl::GetName(HGChar* name, HGUInt maxLen)
|
|
{
|
|
if (NULL == name || 0 == maxLen)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
if (maxLen < m_devName.size() + 1)
|
|
return HGBASE_ERR_FAIL;
|
|
strcpy(name, m_devName.c_str());
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneDeviceImpl::ShowSettingDlg(HGWindow parent)
|
|
{
|
|
if (NULL != m_thread)
|
|
{
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
if (-2 == show_setting_ui(&m_sourceImpl->m_saneApi, m_devHandle, m_devName.c_str(), parent))
|
|
{
|
|
return HGBASE_ERR_NOTSUPPORT;
|
|
}
|
|
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneDeviceImpl::Start(HGSane_DeviceEventFunc eventFunc, HGPointer eventParam,
|
|
HGSane_DeviceImageFunc imageFunc, HGPointer imageParam, HGChar* errInfo, HGUInt errInfoLen)
|
|
{
|
|
if (NULL != m_thread)
|
|
{
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
SANE_Parameters params;
|
|
memset(¶ms, 0, sizeof(SANE_Parameters));
|
|
SANE_Status stat = m_sourceImpl->m_saneApi.sane_get_parameters_api(m_devHandle, ¶ms);
|
|
if (SANE_STATUS_GOOD != stat)
|
|
{
|
|
if (NULL != errInfo)
|
|
{
|
|
const char* err = m_sourceImpl->m_saneApi.sane_strstatus_api(stat);
|
|
if (NULL != err && errInfoLen >= strlen(err) + 1)
|
|
{
|
|
strcpy(errInfo, err);
|
|
}
|
|
}
|
|
|
|
return HGSANE_ERR_FAIL;
|
|
}
|
|
|
|
m_bufferSize = 5000 * 4000;
|
|
m_buffer = (HGByte *)malloc(m_bufferSize);
|
|
if (NULL == m_buffer)
|
|
{
|
|
return HGBASE_ERR_OUTOFMEMORY;
|
|
}
|
|
|
|
m_dpi = GetDpi();
|
|
stat = m_sourceImpl->m_saneApi.sane_start_api(m_devHandle);
|
|
if (SANE_STATUS_GOOD != stat)
|
|
{
|
|
if (NULL != errInfo)
|
|
{
|
|
const char* err = m_sourceImpl->m_saneApi.sane_strstatus_api(stat);
|
|
if (NULL != err && errInfoLen >= strlen(err) + 1)
|
|
{
|
|
strcpy(errInfo, err);
|
|
}
|
|
}
|
|
|
|
m_dpi = 0;
|
|
free(m_buffer);
|
|
m_buffer = NULL;
|
|
m_bufferSize = 0;
|
|
return HGSANE_ERR_FAIL;
|
|
}
|
|
|
|
m_eventFunc = eventFunc;
|
|
m_eventParam = eventParam;
|
|
m_imageFunc = imageFunc;
|
|
m_imageParam = imageParam;
|
|
m_stopThread = HGFALSE;
|
|
HGBase_OpenThread(ThreadFunc, this, &m_thread);
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneDeviceImpl::Stop()
|
|
{
|
|
if (NULL == m_thread)
|
|
{
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
m_stopThread = HGTRUE;
|
|
m_sourceImpl->m_saneApi.sane_cancel_api(m_devHandle);
|
|
HGBase_CloseThread(m_thread);
|
|
m_thread = NULL;
|
|
m_eventFunc = NULL;
|
|
m_eventParam = NULL;
|
|
m_imageFunc = NULL;
|
|
m_imageParam = NULL;
|
|
|
|
m_dpi = 0;
|
|
free(m_buffer);
|
|
m_buffer = NULL;
|
|
m_bufferSize = 0;
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGSaneDeviceImpl::StartWithUI(HGWindow parent, HGSane_DeviceImageFunc imageFunc, HGPointer imageParam)
|
|
{
|
|
if (NULL != m_thread)
|
|
{
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
m_dpi = GetDpi();
|
|
m_imageFunc = imageFunc;
|
|
m_imageParam = imageParam;
|
|
|
|
if (-2 == show_scan_ui(&m_sourceImpl->m_saneApi, m_devHandle, m_devName.c_str(), parent, ShowScanImageCallback, this))
|
|
{
|
|
return HGBASE_ERR_NOTSUPPORT;
|
|
}
|
|
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGUInt HGSaneDeviceImpl::GetDpi()
|
|
{
|
|
HGUInt dpi = 0;
|
|
SANE_Int num_dev_options = 0;
|
|
m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL);
|
|
for (int i = 1; i < num_dev_options; ++i)
|
|
{
|
|
const SANE_Option_Descriptor* desp = m_sourceImpl->m_saneApi.sane_get_option_descriptor_api(m_devHandle, i);
|
|
if (nullptr == desp)
|
|
continue;
|
|
|
|
if (SANE_TYPE_INT == desp->type)
|
|
{
|
|
SANE_Int value = 0;
|
|
m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, NULL);
|
|
if (0 == strcmp(desp->name, "resolution"))
|
|
{
|
|
dpi = (HGUInt)value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return dpi;
|
|
}
|
|
|
|
void HGAPI HGSaneDeviceImpl::ThreadFunc(HGThread thread, HGPointer param)
|
|
{
|
|
HGSaneDeviceImpl* p = (HGSaneDeviceImpl*)param;
|
|
while (!p->m_stopThread)
|
|
{
|
|
SANE_Parameters params;
|
|
memset(¶ms, 0, sizeof(SANE_Parameters));
|
|
SANE_Status stat1 = p->m_sourceImpl->m_saneApi.sane_get_parameters_api(p->m_devHandle, ¶ms);
|
|
|
|
SANE_Int readSize = 0;
|
|
SANE_Status stat2 = SANE_STATUS_GOOD;
|
|
while (readSize < p->m_bufferSize)
|
|
{
|
|
SANE_Int len = 0;
|
|
stat2 = p->m_sourceImpl->m_saneApi.sane_read_api(p->m_devHandle, p->m_buffer + readSize, p->m_bufferSize - readSize, &len);
|
|
readSize += len;
|
|
if (SANE_STATUS_GOOD != stat2)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (SANE_STATUS_GOOD == stat2)
|
|
{
|
|
// m_bufferSize空间不够
|
|
if (NULL != p->m_eventFunc)
|
|
p->m_eventFunc((HGSaneDevice)p, HGSANE_ERR_FAIL, p->m_sourceImpl->m_saneApi.sane_strstatus_api(SANE_STATUS_INVAL), p->m_eventParam);
|
|
break;
|
|
}
|
|
else if (SANE_STATUS_EOF == stat2)
|
|
{
|
|
if (0 == readSize)
|
|
{
|
|
if (NULL != p->m_eventFunc)
|
|
p->m_eventFunc((HGSaneDevice)p, HGBASE_ERR_OK, NULL, p->m_eventParam);
|
|
break;
|
|
}
|
|
else if (SANE_STATUS_GOOD != stat1 || readSize != params.bytes_per_line * params.lines)
|
|
{
|
|
if (NULL != p->m_eventFunc)
|
|
p->m_eventFunc((HGSaneDevice)p, HGSANE_ERR_FAIL, p->m_sourceImpl->m_saneApi.sane_strstatus_api(SANE_STATUS_INVAL), p->m_eventParam);
|
|
break;
|
|
}
|
|
}
|
|
else if (SANE_STATUS_CANCELLED == stat2)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (NULL != p->m_eventFunc)
|
|
p->m_eventFunc((HGSaneDevice)p, HGSANE_ERR_FAIL, p->m_sourceImpl->m_saneApi.sane_strstatus_api(stat2), p->m_eventParam);
|
|
break;
|
|
}
|
|
|
|
if (NULL != p->m_imageFunc)
|
|
{
|
|
HGUInt imgType = 0;
|
|
if (params.format == SANE_FRAME_GRAY)
|
|
{
|
|
if (1 == params.depth)
|
|
imgType = HGBASE_IMGTYPE_BINARY;
|
|
else if (8 == params.depth)
|
|
imgType = HGBASE_IMGTYPE_GRAY;
|
|
}
|
|
else if (params.format == SANE_FRAME_RGB)
|
|
{
|
|
imgType = HGBASE_IMGTYPE_RGB;
|
|
}
|
|
|
|
HGImageInfo imgInfo = { (HGUInt)params.pixels_per_line, (HGUInt)params.lines,
|
|
imgType, (HGUInt)params.bytes_per_line, HGBASE_IMGORIGIN_TOP };
|
|
HGImage img = NULL;
|
|
HGBase_CreateImageWithData(p->m_buffer, &imgInfo, &img);
|
|
if (NULL != img)
|
|
{
|
|
HGBase_SetImageDpi(img, p->m_dpi, p->m_dpi);
|
|
p->m_imageFunc((HGSaneDevice)p, img, p->m_imageParam);
|
|
HGBase_DestroyImage(img);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void HGSaneDeviceImpl::ShowScanImageCallback(const SANE_Parameters* imageFormat, const SANE_Byte* imageData, void* callbackParam)
|
|
{
|
|
HGSaneDeviceImpl* p = (HGSaneDeviceImpl*)callbackParam;
|
|
|
|
if (NULL != p->m_imageFunc)
|
|
{
|
|
HGUInt imgType = 0;
|
|
if (imageFormat->format == SANE_FRAME_GRAY)
|
|
{
|
|
if (1 == imageFormat->depth)
|
|
imgType = HGBASE_IMGTYPE_BINARY;
|
|
else if (8 == imageFormat->depth)
|
|
imgType = HGBASE_IMGTYPE_GRAY;
|
|
}
|
|
else if (imageFormat->format == SANE_FRAME_RGB)
|
|
{
|
|
imgType = HGBASE_IMGTYPE_RGB;
|
|
}
|
|
|
|
HGImageInfo imgInfo = { (HGUInt)imageFormat->pixels_per_line, (HGUInt)imageFormat->lines,
|
|
imgType, (HGUInt)imageFormat->bytes_per_line, HGBASE_IMGORIGIN_TOP };
|
|
HGImage img = NULL;
|
|
HGBase_CreateImageWithData((HGByte*)imageData, &imgInfo, &img);
|
|
if (NULL != img)
|
|
{
|
|
HGBase_SetImageDpi(img, p->m_dpi, p->m_dpi);
|
|
p->m_imageFunc((HGSaneDevice)p, img, p->m_imageParam);
|
|
HGBase_DestroyImage(img);
|
|
}
|
|
}
|
|
}
|