@@ -11,7 +11,6 @@ import 'package:flutter/widgets.dart';
11
11
import 'package:stream_transform/stream_transform.dart' ;
12
12
13
13
import 'src/messages.g.dart' ;
14
- import 'type_conversion.dart' ;
15
14
16
15
/// An implementation of [CameraPlatform] for Windows.
17
16
class CameraWindows extends CameraPlatform {
@@ -27,14 +26,11 @@ class CameraWindows extends CameraPlatform {
27
26
/// Interface for calling host-side code.
28
27
final CameraApi _hostApi;
29
28
30
- /// Camera specific method channels to allow communicating with specific cameras.
31
- final Map <int , MethodChannel > _cameraChannels = < int , MethodChannel > {};
32
-
33
- // The stream to receive frames from the native code.
34
- StreamSubscription <dynamic >? _platformImageStreamSubscription;
35
-
36
- // The stream for vending frames to platform interface clients.
37
- StreamController <CameraImageData >? _frameStreamController;
29
+ /// The per-camera handlers for messages that should be rebroadcast to
30
+ /// clients as [CameraEvent] s.
31
+ @visibleForTesting
32
+ final Map <int , HostCameraMessageHandler > hostCameraHandlers =
33
+ < int , HostCameraMessageHandler > {};
38
34
39
35
/// The controller that broadcasts events coming from handleCameraMethodCall
40
36
///
@@ -105,15 +101,8 @@ class CameraWindows extends CameraPlatform {
105
101
int cameraId, {
106
102
ImageFormatGroup imageFormatGroup = ImageFormatGroup .unknown,
107
103
}) async {
108
- /// Creates channel for camera events.
109
- _cameraChannels.putIfAbsent (cameraId, () {
110
- final MethodChannel channel =
111
- MethodChannel ('plugins.flutter.io/camera_windows/camera$cameraId ' );
112
- channel.setMethodCallHandler (
113
- (MethodCall call) => handleCameraMethodCall (call, cameraId),
114
- );
115
- return channel;
116
- });
104
+ hostCameraHandlers.putIfAbsent (cameraId,
105
+ () => HostCameraMessageHandler (cameraId, cameraEventStreamController));
117
106
118
107
final PlatformSize reply;
119
108
try {
@@ -140,11 +129,7 @@ class CameraWindows extends CameraPlatform {
140
129
await _hostApi.dispose (cameraId);
141
130
142
131
// Destroy method channel after camera is disposed to be able to handle last messages.
143
- if (_cameraChannels.containsKey (cameraId)) {
144
- final MethodChannel ? cameraChannel = _cameraChannels[cameraId];
145
- cameraChannel? .setMethodCallHandler (null );
146
- _cameraChannels.remove (cameraId);
147
- }
132
+ hostCameraHandlers.remove (cameraId)? .dispose ();
148
133
}
149
134
150
135
@override
@@ -249,57 +234,6 @@ class CameraWindows extends CameraPlatform {
249
234
'resumeVideoRecording() is not supported due to Win32 API limitations.' );
250
235
}
251
236
252
- @override
253
- Stream <CameraImageData > onStreamedFrameAvailable (int cameraId,
254
- {CameraImageStreamOptions ? options}) {
255
- _installStreamController (
256
- onListen: () => _onFrameStreamListen (cameraId),
257
- onCancel: () => _onFrameStreamCancel (cameraId));
258
- return _frameStreamController! .stream;
259
- }
260
-
261
- StreamController <CameraImageData > _installStreamController (
262
- {void Function ()? onListen, void Function ()? onCancel}) {
263
- _frameStreamController = StreamController <CameraImageData >(
264
- onListen: onListen ?? () {},
265
- onPause: _onFrameStreamPauseResume,
266
- onResume: _onFrameStreamPauseResume,
267
- onCancel: onCancel ?? () {},
268
- );
269
- return _frameStreamController! ;
270
- }
271
-
272
- void _onFrameStreamListen (int cameraId) {
273
- _startPlatformStream (cameraId);
274
- }
275
-
276
- Future <void > _startPlatformStream (int cameraId) async {
277
- _startStreamListener ();
278
- await _hostApi.startImageStream (cameraId);
279
- }
280
-
281
- void _startStreamListener () {
282
- const EventChannel cameraEventChannel =
283
- EventChannel ('plugins.flutter.io/camera_android/imageStream' );
284
- _platformImageStreamSubscription =
285
- cameraEventChannel.receiveBroadcastStream ().listen ((dynamic imageData) {
286
- _frameStreamController!
287
- .add (cameraImageFromPlatformData (imageData as Map <dynamic , dynamic >));
288
- });
289
- }
290
-
291
- FutureOr <void > _onFrameStreamCancel (int cameraId) async {
292
- await _hostApi.stopImageStream (cameraId);
293
- await _platformImageStreamSubscription? .cancel ();
294
- _platformImageStreamSubscription = null ;
295
- _frameStreamController = null ;
296
- }
297
-
298
- void _onFrameStreamPauseResume () {
299
- throw CameraException ('InvalidCall' ,
300
- 'Pause and resume are not supported for onStreamedFrameAvailable' );
301
- }
302
-
303
237
@override
304
238
Future <void > setFlashMode (int cameraId, FlashMode mode) async {
305
239
// TODO(jokerttu): Implement flash mode support, https://github.com/flutter/flutter/issues/97537.
@@ -398,33 +332,6 @@ class CameraWindows extends CameraPlatform {
398
332
return Texture (textureId: cameraId);
399
333
}
400
334
401
- /// Converts messages received from the native platform into camera events.
402
- ///
403
- /// This is only exposed for test purposes. It shouldn't be used by clients
404
- /// of the plugin as it may break or change at any time.
405
- @visibleForTesting
406
- Future <dynamic > handleCameraMethodCall (MethodCall call, int cameraId) async {
407
- switch (call.method) {
408
- case 'camera_closing' :
409
- cameraEventStreamController.add (
410
- CameraClosingEvent (
411
- cameraId,
412
- ),
413
- );
414
- case 'error' :
415
- final Map <String , Object ?> arguments =
416
- (call.arguments as Map <Object ?, Object ?>).cast <String , Object ?>();
417
- cameraEventStreamController.add (
418
- CameraErrorEvent (
419
- cameraId,
420
- arguments['description' ]! as String ,
421
- ),
422
- );
423
- default :
424
- throw UnimplementedError ();
425
- }
426
- }
427
-
428
335
/// Returns a [MediaSettings] 's Pigeon representation.
429
336
PlatformMediaSettings _pigeonMediaSettings (MediaSettings ? settings) {
430
337
return PlatformMediaSettings (
@@ -467,3 +374,35 @@ class CameraWindows extends CameraPlatform {
467
374
return PlatformResolutionPreset .max;
468
375
}
469
376
}
377
+
378
+ /// Callback handler for camera-level events from the platform host.
379
+ @visibleForTesting
380
+ class HostCameraMessageHandler implements CameraEventApi {
381
+ /// Creates a new handler that listens for events from camera [cameraId] , and
382
+ /// broadcasts them to [streamController] .
383
+ HostCameraMessageHandler (this .cameraId, this .streamController) {
384
+ CameraEventApi .setUp (this , messageChannelSuffix: cameraId.toString ());
385
+ }
386
+
387
+ /// Removes the handler for native messages.
388
+ void dispose () {
389
+ CameraEventApi .setUp (null , messageChannelSuffix: cameraId.toString ());
390
+ }
391
+
392
+ /// The camera ID this handler listens for events from.
393
+ final int cameraId;
394
+
395
+ /// The controller used to broadcast camera events coming from the
396
+ /// host platform.
397
+ final StreamController <CameraEvent > streamController;
398
+
399
+ @override
400
+ void error (String message) {
401
+ streamController.add (CameraErrorEvent (cameraId, message));
402
+ }
403
+
404
+ @override
405
+ void cameraClosing () {
406
+ streamController.add (CameraClosingEvent (cameraId));
407
+ }
408
+ }
0 commit comments