Skip to content

Commit d2e0d4c

Browse files
Merge branch 'main' into android-examples-kotlin-1-9
2 parents aa1decc + aaa1b3f commit d2e0d4c

35 files changed

+697
-1094
lines changed

.ci/flutter_master.version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0fe615343bd9e9b6ef00eecaa906fe10f4a39040
1+
8591d0c16a6c7edfbea3b5b1bf08ae09db117b71

packages/camera/camera_windows/CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
## NEXT
1+
## 0.2.6
22

3+
* Reverts streaming frame support, as the implementation was incorrect and never
4+
exposed.
5+
6+
## 0.2.5+1
7+
8+
* Updates C++ to Dart communication to use Pigeon.
39
* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3.
410

511
## 0.2.5

packages/camera/camera_windows/lib/camera_windows.dart

Lines changed: 40 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import 'package:flutter/widgets.dart';
1111
import 'package:stream_transform/stream_transform.dart';
1212

1313
import 'src/messages.g.dart';
14-
import 'type_conversion.dart';
1514

1615
/// An implementation of [CameraPlatform] for Windows.
1716
class CameraWindows extends CameraPlatform {
@@ -27,14 +26,11 @@ class CameraWindows extends CameraPlatform {
2726
/// Interface for calling host-side code.
2827
final CameraApi _hostApi;
2928

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

3935
/// The controller that broadcasts events coming from handleCameraMethodCall
4036
///
@@ -105,15 +101,8 @@ class CameraWindows extends CameraPlatform {
105101
int cameraId, {
106102
ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown,
107103
}) 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));
117106

118107
final PlatformSize reply;
119108
try {
@@ -140,11 +129,7 @@ class CameraWindows extends CameraPlatform {
140129
await _hostApi.dispose(cameraId);
141130

142131
// 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();
148133
}
149134

150135
@override
@@ -249,57 +234,6 @@ class CameraWindows extends CameraPlatform {
249234
'resumeVideoRecording() is not supported due to Win32 API limitations.');
250235
}
251236

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-
303237
@override
304238
Future<void> setFlashMode(int cameraId, FlashMode mode) async {
305239
// TODO(jokerttu): Implement flash mode support, https://github.com/flutter/flutter/issues/97537.
@@ -398,33 +332,6 @@ class CameraWindows extends CameraPlatform {
398332
return Texture(textureId: cameraId);
399333
}
400334

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-
428335
/// Returns a [MediaSettings]'s Pigeon representation.
429336
PlatformMediaSettings _pigeonMediaSettings(MediaSettings? settings) {
430337
return PlatformMediaSettings(
@@ -467,3 +374,35 @@ class CameraWindows extends CameraPlatform {
467374
return PlatformResolutionPreset.max;
468375
}
469376
}
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

Comments
 (0)