void TX_CALLCONVENTION ofxTobiiEyeX::OnEngineConnectionStateChanged(TX_CONNECTIONSTATE connectionState, TX_USERPARAM param) { switch (connectionState) { case TX_CONNECTIONSTATE_CONNECTED: { bool success; ofLogNotice(smAddonName, "The connection state is now CONNECTED (We are connected to the EyeX Engine)"); success = txCommitSnapshotAsync((TX_HANDLE)param, OnSnapshotCommitted, nullptr) == TX_RESULT_OK; if (!success) { ofLogError(smAddonName, "Failed to initialize the data stream."); } else { ofLogNotice(smAddonName, "Waiting for eye position data to start streaming..."); } } break; case TX_CONNECTIONSTATE_DISCONNECTED: ofLogNotice(smAddonName, "The connection state is now DISCONNECTED (We are disconnected from the EyeX Engine)"); break; case TX_CONNECTIONSTATE_TRYINGTOCONNECT: ofLogNotice(smAddonName, "The connection state is now TRYINGTOCONNECT (We are trying to connect to the EyeX Engine)"); break; case TX_CONNECTIONSTATE_SERVERVERSIONTOOLOW: ofLogWarning(smAddonName, "The connection state is now SERVER_VERSION_TOO_LOW: this application requires a more recent version of the EyeX Engine to run."); break; case TX_CONNECTIONSTATE_SERVERVERSIONTOOHIGH: ofLogWarning(smAddonName, "The connection state is now SERVER_VERSION_TOO_HIGH: this application requires an older version of the EyeX Engine to run."); break; } }
/* * Callback function invoked when the status of the connection to the EyeX Engine has changed. */ void TX_CALLCONVENTION OnEngineConnectionStateChanged(TX_CONNECTIONSTATE connectionState, TX_USERPARAM userParam) { switch (connectionState) { case TX_CONNECTIONSTATE_CONNECTED: { BOOL success; printf("The connection state is now CONNECTED (We are connected to the EyeX Engine)\n"); // commit the snapshot with the global interactor as soon as the connection to the engine is established. // (it cannot be done earlier because committing means "send to the engine".) success = txCommitSnapshotAsync(g_hGlobalInteractorSnapshot, OnSnapshotCommitted, NULL) == TX_RESULT_OK; if (!success) { printf("Failed to initialize the data stream.\n"); } else { printf("Waiting for gaze data to start streaming...\n"); } } break; case TX_CONNECTIONSTATE_DISCONNECTED: printf("The connection state is now DISCONNECTED (We are disconnected from the EyeX Engine)\n"); break; case TX_CONNECTIONSTATE_TRYINGTOCONNECT: printf("The connection state is now TRYINGTOCONNECT (We are trying to connect to the EyeX Engine)\n"); break; case TX_CONNECTIONSTATE_SERVERVERSIONTOOLOW: printf("The connection state is now SERVER_VERSION_TOO_LOW: this application requires a more recent version of the EyeX Engine to run.\n"); break; case TX_CONNECTIONSTATE_SERVERVERSIONTOOHIGH: printf("The connection state is now SERVER_VERSION_TOO_HIGH: this application requires an older version of the EyeX Engine to run.\n"); break; } }
void EyeXGaze::HandleQuery(TX_CONSTHANDLE hAsyncData) { std::lock_guard<std::mutex> lock(_mutex); TX_HANDLE hQuery(TX_EMPTY_HANDLE); // query를 받기위한 핸들 txGetAsyncDataContent(hAsyncData, &hQuery); // asyncdatacontent를 hquery에 저장 const int bufferSize = 20; TX_CHAR stringBuffer[bufferSize]; // query 를 가지고 rectangular bounds 생성 TX_HANDLE hBounds(TX_EMPTY_HANDLE); txGetQueryBounds(hQuery, &hBounds); // query의 bound 알아낸다 TX_REAL pX, pY, pWidth, pHeight; txGetRectangularBoundsData(hBounds, &pX, &pY, &pWidth, &pHeight);// bound에서 rectangular한 좌표 추출 txReleaseObject(&hBounds); Gdiplus::Rect queryBounds((INT)pX, (INT)pY, (INT)pWidth, (INT)pHeight); // query 를 가지고 Snapshot 생성 TX_HANDLE hSnapshot(TX_EMPTY_HANDLE); txCreateSnapshotForQuery(hQuery, &hSnapshot); TX_CHAR windowIdString[bufferSize]; sprintf_s(windowIdString, bufferSize, WINDOW_HANDLE_FORMAT, _hWnd); if (QueryIsForWindowId(hQuery, windowIdString)) { TX_ACTIVATABLEPARAMS params = { TX_FALSE }; for (auto region : _regions) { Gdiplus::Rect regionBounds((INT)region.bounds.left,(INT)region.bounds.top, (INT)(region.bounds.right - region.bounds.left), (INT)(region.bounds.bottom - region.bounds.top)); if (queryBounds.IntersectsWith(regionBounds)) { TX_HANDLE hInteractor(TX_EMPTY_HANDLE); sprintf_s(stringBuffer, bufferSize, "%d", region.id); TX_RECT bounds; bounds.X = region.bounds.left; bounds.Y = region.bounds.top; bounds.Width = region.bounds.right - region.bounds.left; bounds.Height = region.bounds.bottom - region.bounds.top; txCreateRectangularInteractor(hSnapshot, &hInteractor, stringBuffer, &bounds, TX_LITERAL_ROOTID, windowIdString); txCreateActivatableBehavior(hInteractor, ¶ms); txReleaseObject(&hInteractor); } } } txCommitSnapshotAsync(hSnapshot, OnSnapshotCommitted, nullptr); txReleaseObject(&hSnapshot); txReleaseObject(&hQuery); }
void EyeXGaze::OnEngineConnectionStateChanged(TX_CONNECTIONSTATE connectionState) { switch (connectionState) { case TX_CONNECTIONSTATE_CONNECTED: { // commit snapshot to EyeX Engine txCommitSnapshotAsync(g_hGlobalInteractorSnapshot, OnSnapshotCommitted, NULL); } PostMessage(_hWnd, _statusChangedMessage, true, 0); break; case TX_CONNECTIONSTATE_DISCONNECTED: case TX_CONNECTIONSTATE_TRYINGTOCONNECT: case TX_CONNECTIONSTATE_SERVERVERSIONTOOLOW: case TX_CONNECTIONSTATE_SERVERVERSIONTOOHIGH: PostMessage(_hWnd, _statusChangedMessage, false, 0); break; } };
/* * Callback function invoked when the status of the connection to the EyeX Engine has changed. */ void TX_CALLCONVENTION eyeXHost::OnEngineConnectionStateChanged(TX_CONNECTIONSTATE connectionState) { string connectionStateMessage; auto snapshotCommittedTrampoline = [](TX_CONSTHANDLE hAsyncData, TX_USERPARAM userParam) { static_cast<eyeXHost*>(userParam)->OnSnapshotCommitted(hAsyncData); }; switch (connectionState) { case TX_CONNECTIONSTATE_CONNECTED: { bool success; cout << "The connection state is now CONNECTED (We are connected to the EyeX Engine)" << "\n"; success = txCommitSnapshotAsync(g_hGlobalInteractorSnapshot, snapshotCommittedTrampoline, NULL) == TX_RESULT_OK; if (!success) { cout << "Failed to initialize the data stream." << "\n"; } else { cout << "Waiting for gaze data to start streaming..." << "\n"; } } break; case TX_CONNECTIONSTATE_DISCONNECTED: cout << "TX_CONNECTIONSTATE_DISCONNECTED" << "\n"; break; case TX_CONNECTIONSTATE_TRYINGTOCONNECT: cout << "TX_CONNECTIONSTATE_TRYINGTOCONNECT" << "\n"; break; case TX_CONNECTIONSTATE_SERVERVERSIONTOOLOW: cout << "TX_CONNECTIONSTATE_SERVERVERSIONTOOLOW" << "\n"; break; case TX_CONNECTIONSTATE_SERVERVERSIONTOOHIGH: cout << "TX_CONNECTIONSTATE_SERVERVERSIONTOOHIGH" << "\n"; break; } }
void TX_CALLCONVENTION OnEngineConnectionStateChanged(TX_CONNECTIONSTATE connectionState, TX_USERPARAM userParam) { switch (connectionState) { case TX_CONNECTIONSTATE_CONNECTED: { BOOL success; success = txCommitSnapshotAsync(g_hGlobalInteractorSnapshot, OnSnapshotCommitted, NULL) == TX_RESULT_OK; break; } case TX_CONNECTIONSTATE_DISCONNECTED: break; case TX_CONNECTIONSTATE_TRYINGTOCONNECT: break; case TX_CONNECTIONSTATE_SERVERVERSIONTOOLOW: break; case TX_CONNECTIONSTATE_SERVERVERSIONTOOHIGH: break; } }
void EyeXHost::HandleQuery(TX_CONSTHANDLE hAsyncData) { std::lock_guard<std::mutex> lock(_mutex); // NOTE. This method will fail silently if, for example, the connection is lost before the snapshot has been committed, // or if we run out of memory. This is by design, because there is nothing we can do to recover from these errors anyway. TX_HANDLE hQuery(TX_EMPTY_HANDLE); txGetAsyncDataContent(hAsyncData, &hQuery); const int bufferSize = 20; TX_CHAR stringBuffer[bufferSize]; // read the query bounds from the query, that is, the area on the screen that the query concerns. // the query region is always rectangular. TX_HANDLE hBounds(TX_EMPTY_HANDLE); txGetQueryBounds(hQuery, &hBounds); TX_REAL pX, pY, pWidth, pHeight; txGetRectangularBoundsData(hBounds, &pX, &pY, &pWidth, &pHeight); txReleaseObject(&hBounds); Gdiplus::Rect queryBounds((INT)pX, (INT)pY, (INT)pWidth, (INT)pHeight); // create a new snapshot with the same window id and bounds as the query. TX_HANDLE hSnapshot(TX_EMPTY_HANDLE); txCreateSnapshotForQuery(hQuery, &hSnapshot); TX_CHAR windowIdString[bufferSize]; sprintf_s(windowIdString, bufferSize, WINDOW_HANDLE_FORMAT, _hWnd); if (QueryIsForWindowId(hQuery, windowIdString)) { // define options for our activatable regions: no, we don't want tentative focus events. TX_ACTIVATABLEPARAMS params = { TX_FALSE }; // iterate through all regions and create interactors for those that overlap with the query bounds. for (auto region : _regions) { Gdiplus::Rect regionBounds((INT)region.bounds.left, (INT)region.bounds.top, (INT)(region.bounds.right - region.bounds.left), (INT)(region.bounds.bottom - region.bounds.top)); if (queryBounds.IntersectsWith(regionBounds)) { TX_HANDLE hInteractor(TX_EMPTY_HANDLE); sprintf_s(stringBuffer, bufferSize, "%d", region.id); TX_RECT bounds; bounds.X = region.bounds.left; bounds.Y = region.bounds.top; bounds.Width = region.bounds.right - region.bounds.left; bounds.Height = region.bounds.bottom - region.bounds.top; txCreateRectangularInteractor(hSnapshot, &hInteractor, stringBuffer, &bounds, TX_LITERAL_ROOTID, windowIdString); txCreateActivatableBehavior(hInteractor, ¶ms); txReleaseObject(&hInteractor); } } } txCommitSnapshotAsync(hSnapshot, OnSnapshotCommitted, nullptr); txReleaseObject(&hSnapshot); txReleaseObject(&hQuery); }