0

Mac OSX の Qt でキャノン カメラのテザリングをプログラミングしていますが、何らかの理由で sdk のハンドラが呼び出されません。カメラで撮影したいときはすべてうまくいきますが、EdsSetObjectEventHandler が呼び出されないため、写真がダウンロードされません。

しかし、何らかの理由でカメラで撮影した後、アプリケーションを再起動すると、1 つの写真がダウンロードされます。私の意見では、イベントループを使用する必要がありますが、方法がわかりません。

私のアプリケーションは、ハンドラーが呼び出されないだけでフリーズしません。多くの写真を撮ることができます (ただし、カメラのキャッシュにのみ)。

これが私のコードです。

初期化方法

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;
}

なぜこれが起こっているのか知っている人はいますか?ご協力ありがとうございました。

4

2 に答える 2

1

編集 - 解決済み

これに対する解決策を見つけました。EDSDK を使用する場合、プラットフォーム固有のイベント ループを実行する必要がありますが、問題は、すべての USB イベントがそこに行くため、メイン スレッド内で必要になることです。したがって、問題が発生しました-プラットフォーム固有のイベントループが必要ですが、同じスレッドで(私の状況では) Qt イベントループが必要です。

解決

新しいイベントを処理するには、時々 mac event loop を実行する必要があります。そこで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);
}

これが同じ問題を抱えている人に役立つことを願っています。

于 2014-05-13T07:48:48.160 に答える