c# Canon SDK: No callback after CameraCommand_TakePicture
Asked Answered
E

5

10

i've been trying to make this work for some time now... read a lot of posts but none of them could fix this issue.

I am connecting to a EOS 550D using the Canon SDK. I am running win7 64bit and Visual Studio c# 2010.

What I do step by step is:

--> 0 Init SDK

 err = EDSDK.EdsInitializeSDK();

--> 1 Getting camera list

 err = EDSDK.EdsGetCameraList(out cameraList);

--> 2 Getting child count

 err = EDSDK.EdsGetChildCount(cameraList, out cameraCount);

--> 3 If there is a child, get first child

  err = EDSDK.EdsGetChildAtIndex(cameraList, 0, out cameraDev);

--> 4 Opening a session

err = EDSDK.EdsOpenSession(cameraDev);

--> 5 Telling the sdk to save images locally

IntPtr saveTo = (IntPtr)EDSDK.EdsSaveTo.Host;
err = EDSDK.EdsSetPropertyData(cameraDev, EDSDK.PropID_SaveTo, 0, 4, saveTo);

--> 6 Setting the available capacity on the host machine

 EDSDK.EdsCapacity capacity = new EDSDK.EdsCapacity();

 if (err == EDSDK.EDS_ERR_OK)
 {
     capacity.NumberOfFreeClusters = 0x7FFFFFFF;
     capacity.BytesPerSector = 0x1000;
     capacity.Reset = 1;
     err = EDSDK.EdsSetCapacity(cameraDev, capacity);
 }

--> 7 Registring State event Handler

err = EDSDK.EdsSetCameraStateEventHandler(cameraDev, EDSDK.StateEvent_All, stateEventHandler,   new IntPtr(0));

--> 8 Registring Object Event Handler

 EDSDK.EdsObjectEventHandler edsObjectEventHandler = new EDSDK.EdsObjectEventHandler(objectEventHandler);
               err = EDSDK.EdsSetObjectEventHandler(cameraDev, EDSDK.ObjectEvent_All, edsObjectEventHandler, IntPtr.Zero);

....

I dont get any error while doing this, all seems to be fine.

Here are my Handler

 private uint objectEventHandler(uint inEvent, IntPtr inRef, IntPtr inContext)
    {
        Console.WriteLine("HALLLOOOOOOOOOO");
        switch (inEvent)
        {
            case EDSDK.ObjectEvent_DirItemCreated:
                //this.invokeNewItemCreatedEvent(new NewItemCreatedEventArgs(getCapturedItem(inRef)));
                Console.WriteLine("Directory Item Created");
                break;
            case EDSDK.ObjectEvent_DirItemRequestTransfer:
                Console.WriteLine("Directory Item Requested Transfer");
                break;
            default:
                Console.WriteLine(String.Format("ObjectEventHandler: event {0}, ref {1}", inEvent.ToString("X"), inRef.ToString()));
                break;
        }

        return 0x0;
    }








    public uint stateEventHandler(uint inEvent, uint inParameter, IntPtr inContext)
    {
        Console.WriteLine("stateEventHandler " + inEvent);
        switch (inEvent)
        {
            case EDSDK.StateEvent_JobStatusChanged:
                Console.WriteLine(String.Format("There are objects waiting to be transferred.  Job status {0}", inParameter));
                break;

            case EDSDK.StateEvent_ShutDownTimerUpdate:
                if (inParameter != 0)
                    Console.WriteLine(String.Format("shutdown timer update: {0}", inParameter));
                break;

            case EDSDK.ObjectEvent_DirItemRequestTransfer:
                //WHAT I NEED!!!
                Console.WriteLine("Hallo DirItemRequestTransfer");
                //DownloadImage(obj);
                break;


            default:
                Console.WriteLine(String.Format("StateEventHandler: event {0}, parameter {1}", inEvent, inParameter));
                break;
        }
        return 0;
    }

...

So now my problem is that none of the handler is ever called. Don't know why, I searche the net fpr quite some time, tried different approaches but did not get the callback...

Here is my method calling the take picture command:

 public void takePic()
    {
        if (cameraOpened)
        {
           Console.WriteLine( "taking a shot");

            err = EDSDK.EdsSendCommand(cameraDev, EDSDK.CameraCommand_TakePicture, 0);
            if (err != EDSDK.EDS_ERR_OK)
                Console.WriteLine("TakeCommand Error: " + err.ToString());

            Console.WriteLine("Finished taking a shot");

        }
    }

Maybe someone has an idea what I could try to make this work?

Thanks in advance!

Best regards, Tobias

Edwardoedwards answered 2/12, 2012 at 12:34 Comment(0)
D
12

I know the SDK documentation says that the callback functions will be executed in another thread, but for me, using SDK 2.11 under Windows, the callbacks always happen on the main thread and seem to be sent via Windows messages. This means that if you don't have a message pump you won't get the callbacks. If your app is a C# GUI app you should have a message pump, but if it's a console app you probably won't have one, so try manually pumping messages after sending the TakePicture command. You can use Application.Run but you'll need to call Application.Exit somewhere or else your message loop will never exit (e.g. you can call it after downloading the picture from the camera).

Dematerialize answered 1/4, 2013 at 14:49 Comment(2)
This worked for me; I had been plugging away at it for two days, as the app was running behind a Nancy web server self-hosted as a topshelf service, delegates written in F# and queueing camera requests in a MailboxProcessor, so there were a million variables, turns out this is what fixed it. Specifically I had to call InitialzeSDK and SetCameraAddedHandler in a new thread, and call Application.Run() at the end of the thread.Steffi
Nice one figuring that out Sam!Bowser
W
1

I'm using the C++ version of the SDK for some months now.

After a quick scan, all seems fine in your code. I'm not sure about the C# garbage collection/scoping in this example, but you want to make sure your handlers still "around" after you've set them.

Also, for the final EdsContext parameter I use a pointer to my containing class instead of your zero pointer.

err = EDSDK.EdsSetObjectEventHandler(cameraDev, EDSDK.ObjectEvent_All, edsObjectEventHandler, IntPtr.Zero);

If you don't need to contain your event handlers in a class this might not be a problem, but perhaps multi-threading in your app bites you. From the EDSDK manual:

Designate application information to be passed by means of the callback function. Any data needed for your application can be passed. In multithreaded environments, the callback function is executed by a thread exclusively for the event. Use it appropriately, as in designating the this pointer to pass data to UI threads. Designate a NULL pointer if it is not needed.

You could also try and add a handlePropertyEvent handler that should trigger on changes in white balance/ switching to liveview, etc.

Washtub answered 8/12, 2012 at 9:11 Comment(0)
M
1

A 2024 answer, with console app and .NET 8. For me, the problem was that I was using a console application with no windows message pump. As sam explained in his answer, you need a message pump to get callbacks to your EdsObjectEventHandler.

It turns out that if you are using Canon EDSDK version 13.13.0 or newer, there is an API method called EdsGetEvent(). The method will notify the Canon SDK that you want to receive a waiting event, and the EdsGetEvent() must be called on the same thread that registered the event handlers. The method is part of the C++ API and not included in the C# sample projects that ships with the Canon SDK. You can use DllImport to include the method in the C# API like so:

// In your EDSDK class, add the following:
[DllImport("EDSDK.dll")]
public extern static uint EdsGetEvent();

From the Canon API documentation regarding EdsGetEvent() (version 13.17.12):

"This function acquires an event from camera. In console application, please call this function regularly to acquire the event from a camera."

Now you can call EDSDK.EdsGetEvent() after the camera has taken the picture and you should get a callback with the image.

Maidamaidan answered 29/2 at 18:41 Comment(0)
T
0

I am connecting to a EOS 550D using the Canon SDK. I am running win7 64bit and Visual Studio c# 2010.

Your problem is there: the Canon SDK is compiled for X86. Don't look further ! You must change your target architecture.

Toxicosis answered 26/6, 2013 at 20:22 Comment(1)
This isn't the problem. Sure, the C# project should be set to x86 rather than x64 or Any CPU since the native library is x86, but there would be a multitude of other problems if that were set incorrectly. In this case, I'm reasonably sure my answer is the answer.Dematerialize
T
0

The way you subscribe to the object event doesn't really subscribe to anything. This is how I do it and it works fine:

event EDSDK.EdsObjectEventHandler SDKObjectEvent;

void Init(IntPtr cameraDev)
{
    SDKObjectEvent += new EDSDK.EdsObjectEventHandler(objectEventHandler);
    EDSDK.EdsSetObjectEventHandler(cameraDev, EDSDK.ObjectEvent_All, SDKObjectEvent, IntPtr.Zero);
}

Same principle goes for EdsStateEventHandler, EdsPropertyEventHandler and EdsCameraAddedHandler (and a bit different but still with an event EdsProgressCallback)

Kind regards

Turnkey answered 10/4, 2014 at 13:13 Comment(1)
The way he sets the event handler is fine. He's doing the same thing as you, in fact, except that you are routing your event handler through a separate (probably unnecessary) event object.Dematerialize

© 2022 - 2024 — McMap. All rights reserved.