int CanonEDCamera::Shutdown()
{
   // save images on the memory card
   if (isLegacy_)
      EdsSendStatusCommand (camera_,  kEdsCameraStatusCommand_UILock, 0);
   EdsSaveTo toCamera = kEdsSaveTo_Camera;
   EdsError err = EdsSetPropertyData(camera_,  kEdsPropID_SaveTo, 0 , sizeof(EdsSaveTo),  &toCamera);
   if (isLegacy_)
      EdsSendStatusCommand (camera_,  kEdsCameraStatusCommand_UIUnLock, 0);

   // Close session with camera 
   err = EdsCloseSession(camera_); 
    
   // Release camera 
   if(camera_ != NULL) 
   { 
      EdsRelease(camera_); 
   } 
    
   // Terminate SDK 
   if(isSDKLoaded_) 
   { 
      EdsTerminateSDK(); 
   }

   return DEVICE_OK;
}
    EdsError Camera::requestOpenSession(const Settings &settings) {
        if (mHasOpenSession) {
            return EDS_ERR_SESSION_ALREADY_OPEN;
        }
        
        EdsError error = EdsOpenSession(mCamera);
        if (error != EDS_ERR_OK) {
            std::cerr << "ERROR - failed to open camera session" << std::endl;
            return error;
        }
        mHasOpenSession = true;
        
        mShouldKeepAlive = settings.getShouldKeepAlive();
        EdsUInt32 saveTo = settings.getPictureSaveLocation();
        error = EdsSetPropertyData(mCamera, kEdsPropID_SaveTo, 0, sizeof(saveTo) , &saveTo);
        if (error != EDS_ERR_OK) {
            std::cerr << "ERROR - failed to set save destination host/device" << std::endl;
            return error;
        }
        

		//UI lock
		if (error == EDS_ERR_OK)
		{
			error = EdsSendStatusCommand(mCamera, kEdsCameraStatusCommand_UILock, 0);
		}

		if (error == EDS_ERR_OK)
		{
			mIsLocked = true;
		}


        if (saveTo == kEdsSaveTo_Host) {
            // ??? - requires UI lock?
            EdsCapacity capacity = {0x7FFFFFFF, 0x1000, 1};
            error = EdsSetCapacity(mCamera, capacity);
            if (error != EDS_ERR_OK) {
                std::cerr << "ERROR - failed to set capacity of host" << std::endl;
                return error;
            }
        }
        
		//It releases it when locked
		if (mIsLocked)
		{
			EdsSendStatusCommand(mCamera, kEdsCameraStatusCommand_UIUnLock, 0);
		}

        return EDS_ERR_OK;
    }
/*
 *  Command to un/lock the camera to prevent changes
 *  being made directly on the camera. Necessary during
 *  bulb shooting as otherwise the camera may hang.
 *
 *  Possible values:
 *	kEdsCameraStatusCommand_UILock,
 *	kEdsCameraStatusCommand_UIUnLock,
 */
bool
Controller::lockCommand( int value )
{
    int result = EDS_ERR_OK;

    /*
     *  Retry if camera device is busy.
     */
    do {

	result = EdsSendStatusCommand(
			camera->handle(),
			value,
			0 );

	/*
	 *  If retry is required, the camera may become unstable if multiple
	 *  commands are issued in succession without an intervening interval.
	 *  So, put a delay in before command is reissued.
	 */
	if( result == EDS_ERR_DEVICE_BUSY ) {
	    emit eventReport( new Event( Event::CameraBusy, 0, "lock" ) );
	    EdsSendStatusCommand(
		camera->handle(),
		kEdsCameraStatusCommand_UIUnLock,
		0 );
	    QCoreApplication::processEvents();
	    Sleep( 500 );	// milliseconds
	}

    } while( result == EDS_ERR_DEVICE_BUSY );

    if( result != EDS_ERR_OK ) {
	emit eventReport( new Event( Event::LockFailure, result ) );
    }

    return( result == EDS_ERR_OK );
}
int CanonEDCamera::Initialize()
{
   EdsError err = EDS_ERR_OK; 
    
   // Initialize SDK 
   err = EdsInitializeSDK(); 
   if(err == EDS_ERR_OK) 
   { 
     isSDKLoaded_ = true; 
   } 
    
   // Get first camera 
   if(err == EDS_ERR_OK) 
   { 
      err = getFirstCamera (&camera_); 
   } 

   if (err == EDS_ERR_DEVICE_NOT_FOUND)
      return ERR_NO_CAMERA;
    

   // event handlers are static functions that need a reference to this camera object to function
   // provide that static ref here.  This approach will fail with multiple cameras.  In that case, 
   // consider making a map with cameras and references to our CanonEDCamera objects
   g_Self = this;

   // Set event handler 
   if(err == EDS_ERR_OK) 
   { 
      err = EdsSetObjectEventHandler(camera_,  kEdsObjectEvent_All, &CanonEDCamera::handleObjectEvent,  NULL); 
   } 
    
   // Set event handler 
   if(err == EDS_ERR_OK) 
   { 
      err = EdsSetPropertyEventHandler(camera_,  kEdsPropertyEvent_All, &CanonEDCamera::handlePropertyEvent,  NULL); 
   } 
    
   // Set event handler 
   if(err == EDS_ERR_OK) 
   { 
      err = EdsSetCameraStateEventHandler(camera_,  kEdsStateEvent_All, &CanonEDCamera::handleStateEvent,  NULL); 
   } 

   if(err == EDS_ERR_OK) 
   { 
      err = EdsOpenSession(camera_); 
   } 
     
   // Camera name
   if (err == EDS_ERR_OK)
   {
      EdsDeviceInfo  deviceInfo;
      err = EdsGetDeviceInfo(camera_, &deviceInfo);
      if (err == EDS_ERR_OK)
      {
         std::ostringstream os;
         os << "Canon SLR device subtype: " << deviceInfo.deviceSubType;
         LogMessage(os.str().c_str());
         if (deviceInfo.deviceSubType == 0)
            isLegacy_ = true;
         cameraModel_ = deviceInfo.szDeviceDescription;
         int nRet = CreateProperty("Model", cameraModel_.c_str(), MM::String, true);
         if (nRet != DEVICE_OK)
            return nRet;
      }

      // Set and Get various camera properties

      // lock the UI before setting properties - only needed on legacy cameras
      if (isLegacy_)
         EdsSendStatusCommand (camera_,  kEdsCameraStatusCommand_UILock, 0);
      EdsSaveTo toPC = kEdsSaveTo_Host;
      err = EdsSetPropertyData(camera_,  kEdsPropID_SaveTo, 0 , sizeof(EdsSaveTo),  &toPC);
      if (isLegacy_)
         EdsSendStatusCommand (camera_, kEdsCameraStatusCommand_UIUnLock, 0);
   }

   if (err == EDS_ERR_OK)
   {
      CPropertyAction* pAct = new CPropertyAction(this, &CanonEDCamera::OnBinning);
      int nRet = CreateProperty(MM::g_Keyword_Binning, "1", MM::Integer, false, pAct);
      if (nRet != DEVICE_OK)
         return nRet;
   }

   if (err == EDS_ERR_OK)
   {
      return DEVICE_OK;
   }

   std::ostringstream os;
   os << "Error during initialization: " << std::hex << err;
   LogMessage(os.str().c_str());

   return err;
}