henrybetts / EOSFramework

A Cocoa framework for controlling Canon DSLR cameras.
MIT License
13 stars 3 forks source link

Last picture not downloaded if taking with an open session #1

Closed jacobokoenig closed 7 years ago

jacobokoenig commented 7 years ago

Hi,

Im trying to download the last picture in the camera's file, which is taken during the use of my app, but I am only getting the second to last picture which was taken before the app was run (and manager initiated, and sessions opened). Is there a reason why its not finding this last picture while the session is maintained open?

Thanks in advance for your help!!

henrybetts commented 7 years ago

hmmm... I'm not sure why that would be happening. Could you share some of your code? Are you iterating over the filesystem or are you responding to the camera:didCreateFile event?

jacobokoenig commented 7 years ago

Henry, first of all, thank you for your quick reply, and your work with this wrapper.

What I am doing is the following (hope you don't mind that its in Swift, if you need translation, please let me know):

  1. I iterate over the connected cameras to open sessions: ` //Get Cameras and Open its Session func getCamsWithOpenSession(vc: ViewController) -> [EOSCamera] { var cameras: [EOSCamera] = [] let cameraList = EOSManager.sharedManager().getCameras()

    for camera in cameraList {
    
       let cam = camera as! EOSCamera
    
       do {
           if !cam.isOpen {
               try cam.openSession()
               cameras.append(cam)
           } else {
               cameras.append(cam)
           }
       } catch {
           generalAlert("Could not open session on camera \(camera.index)", text: "Please restart the program to load cameras again")
       }
    }
    vc.cameraNumLbl.stringValue = "There are \(cameras.count) cameras connected"
    return cameras

    }`

  2. I try to access the last file in each, manually with the knowledge of the file system tree in the cameras, which works fine the first time around:
func getToFinalDirectory(cam: EOSCamera) -> [EOSFile] {
         do {
            let volumeList = cam.volumes()
            let volume = volumeList[0] as! EOSVolume
            for number in volume.files() {
                let num = number as! EOSFile
                var num2: [EOSFile] = []
                var num3: [EOSFile] = []
                let name = try num.info().name
                if name == "DCIM" {
                    num2 = num.files() as! [EOSFile]
                    num3 = num2[0].files() as! [EOSFile]
                    return num3
                }
            }
        } catch {
            //Handle Error
            print("catched error")
            return []
        }
        return []
    }
  1. Get last file in the last directory for each camera:
    func getLastFile(cam: EOSCamera, serial: String) {
        let files: [EOSFile] = cameraFunctionality().getToFinalDirectory(cam)
        files.last!.readDataWithDelegate(self, contextInfo: serial)
    }
  1. Save each photography downloaded into an array that I then use in the rest of my application.

I was not aware of the didCreateFile event (only the didReadData event that I'm using).

henrybetts commented 7 years ago

The problem could be that you're trying to get the most recent file, but I don't think the list of files is guaranteed to be in any particular order. You could try ordering the files - something like:

func getLastFile(cam: EOSCamera, serial: String) {
    let files: [EOSFile] = cameraFunctionality().getToFinalDirectory(cam)
    let ordered = files.sort {
        do {
            return try $0.info().name < $1.info().name
        }catch{
            return false
        }
    }
    ordered.last!.readDataWithDelegate(self, contextInfo: serial)
}

However, if you are wanting to download the images as they are being captured by the camera, there is a better method that you should use, which involves listening for camera events - let me know if you would like me to describe this.

jacobokoenig commented 7 years ago

Thanks Henry. Yes, could you describe that process? Im guessing it has to do with the didCreateFile event that you mentioned?

henrybetts commented 7 years ago

If you set the delegate property of an EOSCamera, there are several optional event handlers that can be implemented (see EOSCameraDelegate). In the past I have used the camera:didCreateFile event to detect when a new file is created.

However, there may be a better way: https://github.com/henrybetts/EOSFramework/commit/881269791a97a53bf64da6c6e028952a5522361e

I've just added a new event handler; camera:didRequestTransferOfFile, and a new property; EOSProperty_CaptureDestination. In theory, you can set the value of that property to either EOSCaptureDestination.Host or .Both, and when an image is taken, it should call the new event handler. You can then choose to download or read the file data, or cancel the request.

Unfortunately, I don't have access to a Canon DSLR at the moment so this new method is untested!

jacobokoenig commented 7 years ago

Henry, i found a great solution using didCreateFile(). Thank you very much for your help.

Can I ask you what motivated you to create this on Github, and make such an effort for us your fellow programmers? :)

henrybetts commented 7 years ago

Haha good question! I love the open source culture and find it a great way of learning. The projects that I've open sourced are just small byproducts of other projects that I am/was working on anyway.

By the way, I've just pushed some changes (https://github.com/henrybetts/EOSFramework/commit/d44b9a56ba67e68c8728d0fcd89877bbd55d52e3) that should make the framework a bit more swift friendly!