Open scj643 opened 4 years ago
Actually, this should just implement a wraper to control camera options in general.
It is possible to implement it the same way as Copy Camera Descripton
though we would need an implementation that runs while the camera is in live view.
https://gitlab.com/entangle/entangle is a project using Gphoto2 that has controls while in live view. A way to send messages to the main of the SyPLiveViewSession
would allow changing settings while in live view.
This is my implementation in SyPGPhotoCamera.m
- (void)autofocus
{
CameraWidget *widget = NULL, *child = NULL;
int val = 0;
int result = gp_camera_get_config(_camera, &widget, self.context.GPContext);
if (result == GP_OK)
{
result = gp_widget_get_child_by_name(widget, "autofocusdrive", &child);
}
if (result == GP_OK)
{
CameraWidgetType type;
result = gp_widget_get_type(widget, &type);
if (result == GP_OK & type == GP_WIDGET_TOGGLE)
{
result = gp_widget_get_value (child, &val);
}
if (result == GP_OK)
{
// Invert the value to toggle it.
val = !val;
result = gp_widget_set_value(child, &val);
}
if (result == GP_OK)
{
result = gp_camera_set_config (_camera, widget, self.context.GPContext);
}
}
gp_widget_free (widget);
}
A quick hack is to use NSUserDefaults
and set the properties you want changed as booleans there.
The implementation in main
of SyPLiveViewSession
if (!error)
{
while (!self.isCancelled)
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL focus = [defaults boolForKey:@"focus"];
@autoreleasepool {
SyPImageBuffer *buffer = [camera getImageWithError:&error];
if (buffer)
{
self.buffer = buffer;
dispatch_source_merge_data(source, 1);
}
if (error)
{
if ([SyPGPhotoContext errorIsFatal:error])
{
[self cancel];
}
self.errorHandler(error);
}
else if (focus == YES)
{
[camera autofocus];
[defaults setBool:NO forKey:@"focus"];
}
}
}
}
Ok, So I learned more Objective C and seems you could use NSNotificationCenter to trigger events on the camera. I am moving the camera in the live view session to another class called SyPCameraMessaging
@implementation SyPCameraMessaging
- (SyPCameraMessaging *)initWithCamera:(SyPGPhotoCamera *)camera
{
self.camera = camera;
self.shouldGetFrames = YES;
return self;
}
- (void) notificationHandler:(NSNotification *)notification
{
if ([notification.object isEqual: @"focus"])
{
self.shouldGetFrames = NO;
[self.camera autofocus];
self.shouldGetFrames = YES;
}
}
@end
(inside main)
SyPCameraMessaging *messaging = [[SyPCameraMessaging alloc] initWithCamera: [_context cameraForDescription:_description withError:&error]];
// Code to create the queues is here
[messaging.camera startLiveView];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:messaging selector:@selector(notificationHandler:) name:@"camera" object:nil];
if (!error)
{
while (!self.isCancelled)
{
@autoreleasepool {
SyPImageBuffer *buffer = nil;
if (messaging.shouldGetFrames)
{
buffer = [messaging.camera getImageWithError:&error];
}
if (buffer)
{
self.buffer = buffer;
dispatch_source_merge_data(source, 1);
}
if (error)
{
if ([SyPGPhotoContext errorIsFatal:error])
{
[self cancel];
}
self.errorHandler(error);
}
}
}
}
All functions like autofocussing would have to check for GP_ERROR_CAMERA_BUSY
and wait since the frame loop holds it.
@scj643 is it possible to run both programs at the same time? to control autofocus without it being part of cameralive?
No it is not since cameralive has control of the camera.
Bindings for driving the focus as well as the exposure and other settings would be nice. The XPC service would need to expose controls for the current camera.
https://github.com/gphoto/libgphoto2/blob/master/examples/focus.c is an example of driving the focus with libgphoto2.