Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
43 changes: 33 additions & 10 deletions packages/camera/lib/new/src/camera_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,21 @@ import 'common/camera_interface.dart';
///
/// Use [CameraController.availableCameras] to get a list of available cameras.
///
/// This class is used as a simple interface that works for Android and iOS.
/// This class is used as a simple interface to control a camera on Android or
/// iOS.
///
/// When using iOS, simultaneously calling [start] on two [CameraController]s
/// will throw a [PlatformException].
/// Only one instance of [CameraController] can be active at a time. If you call
/// [initialize] on a [CameraController] while another is active, the old
/// controller will be disposed before initializing the new controller.
///
/// When using Android, simultaneously calling [start] on two
/// [CameraController]s may throw a [PlatformException] depending on the
/// hardware resources of the device.
/// Example using [CameraController]:
///
/// ```dart
/// final List<CameraDescription> cameras = async CameraController.availableCameras();
/// final CameraController controller = CameraController(description: cameras[0]);
/// controller.initialize();
/// controller.start();
/// ```
class CameraController {
/// Default constructor.
///
Expand All @@ -28,7 +35,6 @@ class CameraController {
///
/// This will choose the best [CameraConfigurator] for the current device.
factory CameraController({@required CameraDescription description}) {
assert(description != null);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary since its in the constructor.

return CameraController._(
description: description,
configurator: _createDefaultConfigurator(description),
Expand Down Expand Up @@ -59,6 +65,9 @@ class CameraController {
);
}

// Keep only one active instance of CameraController.
static CameraController _instance;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May I offer a different view about this approach? How about not having it as a static field? If the client developer unwisely calls initialize without disposing the previous CameraController, this may be a error, but also that may be that he is trying to access more than one camera at the same time (I don't know if this is possible in the hardware layer), but seems feasible to have more than one camera open and this to be alright.

Even if there is no chance of the developer accessing more than one camera at the same time, I believe that an exception should be raised explaining that the device is busy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review!

Our reasoning to keep this functionality is because the current implementation of the plugin only allows one controller to be active at a time. It isn't documented in the plugin, but that is how it works underneath. While we refactor the platform specific code, we want to keep the interface the same and not cause many breaking changes.

The other reason for this functionality is because the CameraController will only serve as a simple to use and narrowly defined interface usable on any platform. For more complex features (like accessing multiple cameras), we will also expose access to this through another interface or require platform specific code.


/// Details for the camera this controller accesses.
final CameraDescription description;

Expand All @@ -75,14 +84,28 @@ class CameraController {
throw UnimplementedError('$defaultTargetPlatform not supported');
}

/// Begins the flow of data between the inputs and outputs connected the camera instance.
/// Initializes the camera on the device.
///
/// You must call [dispose] when you are done using the camera, otherwise it
/// will remain locked and be unavailable to other applications.
Future<void> initialize() {
if (_instance != this) _instance?.dispose();
_instance = this;

return configurator.initialize();
}

/// Begins the flow of data between the inputs and outputs connected to the camera instance.
Future<void> start() => configurator.start();

/// Stops the flow of data between the inputs and outputs connected the camera instance.
/// Stops the flow of data between the inputs and outputs connected to the camera instance.
Future<void> stop() => configurator.stop();

/// Deallocate all resources and disables further use of the controller.
Future<void> dispose() => configurator.dispose();
Future<void> dispose() {
_instance = null;
return configurator.dispose();
}

static CameraConfigurator _createDefaultConfigurator(
CameraDescription description,
Expand Down
7 changes: 5 additions & 2 deletions packages/camera/lib/new/src/common/camera_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@ abstract class CameraConfigurator {
/// You must call [addPreviewTexture] first or this will only return null.
int get previewTextureId;

/// Begins the flow of data between the inputs and outputs connected the camera instance.
/// Initializes the camera on the device.
Future<void> initialize();

/// Begins the flow of data between the inputs and outputs connected to the camera instance.
///
/// This will start updating the texture with id: [previewTextureId].
Future<void> start();

/// Stops the flow of data between the inputs and outputs connected the camera instance.
/// Stops the flow of data between the inputs and outputs connected to the camera instance.
Future<void> stop();

/// Dispose all resources and disables further use of this configurator.
Expand Down