Skip to content
This repository has been archived by the owner on Jul 18, 2024. It is now read-only.

Camera controls in app #162

Open
scj643 opened this issue Jun 11, 2020 · 8 comments
Open

Camera controls in app #162

scj643 opened this issue Jun 11, 2020 · 8 comments

Comments

@scj643
Copy link

scj643 commented Jun 11, 2020

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.

@scj643
Copy link
Author

scj643 commented Jun 11, 2020

Actually, this should just implement a wraper to control camera options in general.

@scj643 scj643 changed the title Focus controls in app. Camera controls in app Jun 15, 2020
@scj643
Copy link
Author

scj643 commented Jun 15, 2020

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.

@scj643
Copy link
Author

scj643 commented Jun 15, 2020

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.

@scj643
Copy link
Author

scj643 commented Jun 15, 2020

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);
}

@scj643
Copy link
Author

scj643 commented Jun 15, 2020

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"];
                }
            }
        }
    }

@scj643
Copy link
Author

scj643 commented Jun 18, 2020

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

SyPCameraMessaging.m

@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

SyPLiveViewSession.m

(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.

@samuelbeek
Copy link

@scj643 is it possible to run both programs at the same time? to control autofocus without it being part of cameralive?

@scj643
Copy link
Author

scj643 commented Jun 23, 2020

No it is not since cameralive has control of the camera.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants