Skip to content

[camera] Use Pigeon for Windows C++->Dart #8001

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/camera/camera_windows/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 0.2.5+1

* Updates C++ to Dart communication to use Pigeon.
* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3.

## 0.2.5
Expand Down
83 changes: 40 additions & 43 deletions packages/camera/camera_windows/lib/camera_windows.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ class CameraWindows extends CameraPlatform {
/// Interface for calling host-side code.
final CameraApi _hostApi;

/// Camera specific method channels to allow communicating with specific cameras.
final Map<int, MethodChannel> _cameraChannels = <int, MethodChannel>{};
/// The per-camera handlers for messages that should be rebroadcast to
/// clients as [CameraEvent]s.
@visibleForTesting
final Map<int, HostCameraMessageHandler> hostCameraHandlers =
<int, HostCameraMessageHandler>{};

// The stream to receive frames from the native code.
StreamSubscription<dynamic>? _platformImageStreamSubscription;
Expand Down Expand Up @@ -105,15 +108,8 @@ class CameraWindows extends CameraPlatform {
int cameraId, {
ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown,
}) async {
/// Creates channel for camera events.
_cameraChannels.putIfAbsent(cameraId, () {
final MethodChannel channel =
MethodChannel('plugins.flutter.io/camera_windows/camera$cameraId');
channel.setMethodCallHandler(
(MethodCall call) => handleCameraMethodCall(call, cameraId),
);
return channel;
});
hostCameraHandlers.putIfAbsent(cameraId,
() => HostCameraMessageHandler(cameraId, cameraEventStreamController));

final PlatformSize reply;
try {
Expand All @@ -140,11 +136,7 @@ class CameraWindows extends CameraPlatform {
await _hostApi.dispose(cameraId);

// Destroy method channel after camera is disposed to be able to handle last messages.
if (_cameraChannels.containsKey(cameraId)) {
final MethodChannel? cameraChannel = _cameraChannels[cameraId];
cameraChannel?.setMethodCallHandler(null);
_cameraChannels.remove(cameraId);
}
hostCameraHandlers.remove(cameraId)?.dispose();
}

@override
Expand Down Expand Up @@ -398,33 +390,6 @@ class CameraWindows extends CameraPlatform {
return Texture(textureId: cameraId);
}

/// Converts messages received from the native platform into camera events.
///
/// This is only exposed for test purposes. It shouldn't be used by clients
/// of the plugin as it may break or change at any time.
@visibleForTesting
Future<dynamic> handleCameraMethodCall(MethodCall call, int cameraId) async {
switch (call.method) {
case 'camera_closing':
cameraEventStreamController.add(
CameraClosingEvent(
cameraId,
),
);
case 'error':
final Map<String, Object?> arguments =
(call.arguments as Map<Object?, Object?>).cast<String, Object?>();
cameraEventStreamController.add(
CameraErrorEvent(
cameraId,
arguments['description']! as String,
),
);
default:
throw UnimplementedError();
}
}

/// Returns a [MediaSettings]'s Pigeon representation.
PlatformMediaSettings _pigeonMediaSettings(MediaSettings? settings) {
return PlatformMediaSettings(
Expand Down Expand Up @@ -467,3 +432,35 @@ class CameraWindows extends CameraPlatform {
return PlatformResolutionPreset.max;
}
}

/// Callback handler for camera-level events from the platform host.
@visibleForTesting
class HostCameraMessageHandler implements CameraEventApi {
/// Creates a new handler that listens for events from camera [cameraId], and
/// broadcasts them to [streamController].
HostCameraMessageHandler(this.cameraId, this.streamController) {
CameraEventApi.setUp(this, messageChannelSuffix: cameraId.toString());
}

/// Removes the handler for native messages.
void dispose() {
CameraEventApi.setUp(null, messageChannelSuffix: cameraId.toString());
}

/// The camera ID this handler listens for events from.
final int cameraId;

/// The controller used to broadcast camera events coming from the
/// host platform.
final StreamController<CameraEvent> streamController;

@override
void error(String message) {
streamController.add(CameraErrorEvent(cameraId, message));
}

@override
void cameraClosing() {
streamController.add(CameraClosingEvent(cameraId));
}
}
Loading