startCapture method
Future<void>
startCapture({
- void onKeyboard(
- MiniAVKeyboardEvent event,
- Object? userData
- void onMouse(
- MiniAVMouseEvent event,
- Object? userData
- void onGamepad(
- MiniAVGamepadEvent event,
- Object? userData
- void onMotion(
- MiniAVMotionEvent event,
- Object? userData
- Object? userData,
override
Start input capture. Provide callbacks for each input type you want to receive.
Implementation
@override
Future<void> startCapture({
void Function(MiniAVKeyboardEvent event, Object? userData)? onKeyboard,
void Function(MiniAVMouseEvent event, Object? userData)? onMouse,
void Function(MiniAVGamepadEvent event, Object? userData)? onGamepad,
void Function(MiniAVMotionEvent event, Object? userData)? onMotion,
Object? userData,
}) async {
// Motion is NOT delivered by this backend. The native bindings now mirror
// the C struct exactly (motion_rate_hz / motion_mode / motion_callback),
// but they are written zero/null and MINIAV_INPUT_TYPE_MOTION is never
// requested, so no C backend ever starts a sensor and
// miniav_input_deliver_motion's null-check keeps the pointer un-called.
// Wiring it up is: set the MOTION bit, install a NativeCallable in
// motion_callback, and bind MiniAV_Input_GetLatestMotion for the pull API.
// Until then `onMotion` is accepted (the shared interface signature) and
// provably never invoked here; the web backend implements motion fully.
_ensureNotDestroyed();
if (_pendingConfig == null) {
throw StateError('configure() must be called before startCapture()');
}
await stopCapture(); // Clean up any previous capture
// Create NativeCallable listeners for each provided callback
void ffiKeyboardCallback(
ffi.Pointer<bindings.MiniAVKeyboardEvent> eventPtr,
ffi.Pointer<ffi.Void> cbUserData,
) {
if (_isDestroyed || onKeyboard == null) return;
try {
onKeyboard(keyboardEventFromNative(eventPtr.ref), userData);
} catch (e, s) {
print('Error in keyboard callback: $e\n$s');
}
}
void ffiMouseCallback(
ffi.Pointer<bindings.MiniAVMouseEvent> eventPtr,
ffi.Pointer<ffi.Void> cbUserData,
) {
if (_isDestroyed || onMouse == null) return;
try {
onMouse(mouseEventFromNative(eventPtr.ref), userData);
} catch (e, s) {
print('Error in mouse callback: $e\n$s');
}
}
void ffiGamepadCallback(
ffi.Pointer<bindings.MiniAVGamepadEvent> eventPtr,
ffi.Pointer<ffi.Void> cbUserData,
) {
if (_isDestroyed || onGamepad == null) return;
try {
onGamepad(gamepadEventFromNative(eventPtr.ref), userData);
} catch (e, s) {
print('Error in gamepad callback: $e\n$s');
}
}
_keyboardCallbackHandle =
ffi.NativeCallable<bindings.MiniAVKeyboardCallbackFunction>.listener(
ffiKeyboardCallback,
);
_mouseCallbackHandle =
ffi.NativeCallable<bindings.MiniAVMouseCallbackFunction>.listener(
ffiMouseCallback,
);
_gamepadCallbackHandle =
ffi.NativeCallable<bindings.MiniAVGamepadCallbackFunction>.listener(
ffiGamepadCallback,
);
// Build the native config struct with callbacks
final configPtr = calloc<bindings.MiniAVInputConfig>();
try {
copyInputConfigToNative(
_pendingConfig!,
configPtr.ref,
keyboardCb: _keyboardCallbackHandle!.nativeFunction,
mouseCb: _mouseCallbackHandle!.nativeFunction,
gamepadCb: _gamepadCallbackHandle!.nativeFunction,
);
final configRes = bindings.MiniAV_Input_Configure(
_contextHandle!,
configPtr,
);
if (configRes != bindings.MiniAVResultCode.MINIAV_SUCCESS) {
await _cleanupCallbacks();
throw Exception('Failed to configure input context: ${configRes.name}');
}
} finally {
calloc.free(configPtr);
}
final startRes = bindings.MiniAV_Input_StartCapture(_contextHandle!);
if (startRes != bindings.MiniAVResultCode.MINIAV_SUCCESS) {
await _cleanupCallbacks();
throw Exception('Failed to start input capture: ${startRes.name}');
}
}