[英]Canon EDSDK handler isn't called on mac
我正在为 Mac OSX 下的 Qt 中的佳能相机编写网络共享程序,出于某种原因,我的 sdk 处理程序没有被调用。 当我想用相机拍摄时一切顺利,但我的照片没有下载,因为 EdsSetObjectEventHandler 没有被调用。
但是出于某种原因,当我用相机拍摄时,我重新启动了应用程序,然后下载了一张照片。 我的意见是我需要使用他们的事件循环,但我不知道如何使用。
我的应用程序不会冻结,只是没有调用处理程序。 我可以拍摄很多照片(但仅限于相机缓存)。
这是我的代码。
初始化方法
void CameraControl::initEDS()
{
Q_D(CameraControl);
// Camera init
EdsUInt32 count = 0;
EdsDeviceInfo info;
EdsError err = EdsInitializeSDK();
if(err != EDS_ERR_OK)
qFatal("Error: Could not initialize library!");
EdsCameraListRef cameraList = NULL;
if(EdsGetCameraList(&cameraList) != EDS_ERR_OK)
qFatal("Error: Could not get camera list!");
if(EdsGetChildCount(cameraList, &count) != EDS_ERR_OK)
qFatal("Error: Could not get number of cameras!");
if(EdsGetChildAtIndex(cameraList, 0, &(d->m_camera)) != EDS_ERR_OK)
qFatal("Error: Could not get camera!");
if(EdsGetDeviceInfo(d->m_camera, &info) != EDS_ERR_OK)
qFatal("Error: Could not get camera info!");
EdsRelease(cameraList);
// Register handler - this are not called
if(EdsSetObjectEventHandler(d->m_camera, kEdsObjectEvent_All, handleObjectEvent, (EdsVoid*)this) != EDS_ERR_OK)
{
qFatal("Error: can't setup object handler");
}
if(info.deviceSubType == 0)
d->m_isLegacy = true;
else
d->m_isLegacy = false;
// open session
if(EdsOpenSession(d->m_camera) != EDS_ERR_OK)
qFatal("Can't open session with camera");
sleep(1);
EdsUInt32 saveTo = kEdsSaveTo_Host;
if(EdsSetPropertyData(d->m_camera, kEdsPropID_SaveTo, 0, sizeof(saveTo), &saveTo) != EDS_ERR_OK)
qFatal("Error: can't get property for saveTo");
if(!d->m_isLegacy)
{
EdsCapacity capacity = {0x7FFFFFFF, 0x1000, 1};
if(EdsSetCapacity(d->m_camera, capacity) != EDS_ERR_OK)
qFatal("Error: can't set capacity");
}
// get property camera name
EdsUInt32 dataSize = 0;
EdsDataType dataType = kEdsDataType_Unknown;
EdsChar dataString[EDS_MAX_NAME];
if(EdsGetPropertySize(d->m_camera, kEdsPropID_ProductName, 0, &dataType, &dataSize) != EDS_ERR_OK)
qFatal("Can't get property size");
if(dataType == kEdsDataType_String)
{
qDebug() << "property is string";
if(EdsGetPropertyData(d->m_camera, kEdsPropID_ProductName, 0, dataSize, &dataString) != EDS_ERR_OK)
qFatal("Can't get product name of camera");
}
}
捕获方法
void CameraControl::capture()
{
Q_D(CameraControl);
EdsError err;
if((err = EdsSendCommand(d->m_camera, kEdsCameraCommand_TakePicture, 0)) != EDS_ERR_OK)
{
QString str = QString("Error: can't shoot with camera - code: %1").arg(QString::number(err, 16));
qDebug() << str;
}
else
qDebug() << "picture taken";
}
处理程序方法
EdsError EDSCALLBACK handleObjectEvent(EdsUInt32 inEvent, EdsBaseRef inRef, EdsVoid* inContext)
{
EdsError err = EDS_ERR_OK;
CameraControl* control = static_cast<CameraControl*>(inContext);
qDebug() << "object handler called"; // never called
switch(inEvent)
{
case kEdsObjectEvent_DirItemRequestTransfer:
download(inRef, control); // download photo
default:
EdsRelease(inRef);
}
return EDS_ERR_OK;
}
有谁知道为什么会这样? 感谢您的帮助。
编辑 - 已解决
我找到了解决方案。 当您使用 EDSDK 时,您需要运行特定于平台的事件循环,但问题是您需要在主线程内部使用它,因为所有 USB 事件都在那里。 因此出现了问题-您需要特定于平台的事件循环,但在您需要的同一线程上(在我的情况下)Qt 事件循环。
解决方案
您需要不时运行 mac 事件循环来处理新事件。 所以我创建了processEvents()
方法,这个方法有CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false)
来处理队列中的所有事件。
我的对象的构造函数有新的计时器
Q_D(CameraControl);
d->m_timer.setInterval(500);
d->m_timer.setSingleShot(false);
connect(&d->m_timer, &QTimer::timeout, this, &CameraControl::processEvents);
d->m_timer.start();
定时器调用这个槽方法
void CameraControl::processEvents()
{
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
}
我希望这会帮助有同样问题的人。
有一个简单的解决方案:
将QT_EVENT_DISPATCHER_CORE_FOUNDATION=1
添加到环境变量。
这将强制 Qt 使用CFRunLoop而不是Unix Event Loop 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.