//-----------------------------------------------------------------------------
// (C) Copyright 2005 - 2023 by MATRIX VISION GmbH
//
// This software is provided by MATRIX VISION GmbH "as is"
// and any express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular purpose
// are disclaimed.
//
// In no event shall MATRIX VISION GmbH be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused and
// on any theory of liability, whether in contract, strict liability, or tort
// (including negligence or otherwise) arising in any way out of the use of
// this software, even if advised of the possibility of such damage.

//-----------------------------------------------------------------------------
#ifndef MVIMPACT_ACQUIRE_H_
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#   define MVIMPACT_ACQUIRE_H_ MVIMPACT_ACQUIRE_H_
#endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
//-----------------------------------------------------------------------------
#ifdef SWIG
#   ifdef SWIGPYTHON
#       ifndef WRAP_PYTHON
#           define WRAP_PYTHON
#       endif
#   endif
#   ifdef SWIGJAVA
#       ifndef WRAP_JAVA
#           define WRAP_JAVA
#       endif
#   endif
#endif

#ifdef WRAP_PYTHON
#   ifndef PYTHON_ONLY
#       define PYTHON_ONLY(X) X
#   endif
#   ifndef PYTHON_CPP_SWITCH
#       define PYTHON_CPP_SWITCH(PYTHON_WRAPPER_CODE,CPP_WRAPPER_CODE) PYTHON_WRAPPER_CODE
#   endif
#   ifndef WRAP_ANY
#       define WRAP_ANY
#   endif // #ifndef WRAP_ANY
#else // #ifdef WRAP_PYTHON
#   ifndef PYTHON_ONLY
#       define PYTHON_ONLY(X)
#   endif
#   ifndef PYTHON_CPP_SWITCH
#       define PYTHON_CPP_SWITCH(PYTHON_WRAPPER_CODE,CPP_WRAPPER_CODE) CPP_WRAPPER_CODE
#   endif
#endif // #ifdef WRAP_PYTHON

#ifdef WRAP_JAVA
#   ifndef JAVA_ONLY
#       define JAVA_ONLY(X) X
#   endif
#   ifndef JAVA_CPP_SWITCH
#       define JAVA_CPP_SWITCH(JAVA_WRAPPER_CODE,CPP_WRAPPER_CODE) JAVA_WRAPPER_CODE
#   endif
#   ifndef WRAP_ANY
#       define WRAP_ANY
#   endif // #ifndef WRAP_ANY
#else // #ifdef WRAP_JAVA
#   ifndef JAVA_ONLY
#       define JAVA_ONLY(X)
#   endif
#   ifndef JAVA_CPP_SWITCH
#       define JAVA_CPP_SWITCH(JAVA_WRAPPER_CODE,CPP_WRAPPER_CODE) CPP_WRAPPER_CODE
#   endif
#endif // #ifdef WRAP_JAVA

#if defined(WRAP_PYTHON) || defined(WRAP_JAVA)
#   ifndef PYTHON_OR_JAVA_ONLY
#       define PYTHON_OR_JAVA_ONLY(X) X
#   endif
#else
#   ifndef PYTHON_OR_JAVA_ONLY
#       define PYTHON_OR_JAVA_ONLY(X)
#   endif
#endif // #if defined(WRAP_PYTHON) || defined(WRAP_JAVA)

#if !defined(MVIMPACT_DEPRECATED_CPP)
#   ifdef WRAP_ANY
#       define MVIMPACT_DEPRECATED_CPP(FUNCTION)
#   elif defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__ ) >= 301) // is at least GCC 3.1 compiler?
#       define MVIMPACT_DEPRECATED_CPP(FUNCTION) FUNCTION __attribute__ ((deprecated))
#   elif defined(_MSC_VER)
#       if _MSC_VER >= 1310 // is at least VC 2003 compiler?
#           define MVIMPACT_DEPRECATED_CPP(FUNCTION) __declspec(deprecated) FUNCTION
#       else
#           define MVIMPACT_DEPRECATED_CPP(FUNCTION) FUNCTION
#       endif // #if _MSC_VER >= 1310
#   else
#       define MVIMPACT_DEPRECATED_CPP(FUNCTION) FUNCTION
#   endif // compiler check
#endif // #if !defined(MVIMPACT_DEPRECATED_CPP)

#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
#   ifdef MVIA_FUNCTION
#       undef MVIA_FUNCTION
#   endif // MVIA_FUNCTION
#   ifdef _MSC_VER // is Microsoft compiler?
#       pragma warning( push )
#       if _MSC_VER < 1300 // is 'old' VC 6 compiler?
#           pragma warning( disable : 4786 ) // 'identifier was truncated to '255' characters in the debug information'
#           define MVIA_FUNCTION "No function name information as the __FUNCTION__ macro is not supported by this(VC 6) compiler"
#           pragma message( "WARNING: This header(" __FILE__ ") uses the __FUNCTION__ macro, which is not supported by this compiler. A default definition(\"" MVIA_FUNCTION "\") will be used!" )
#           pragma message( "WARNING: This header(" __FILE__ ") uses inheritance for exception classes. However this compiler can't handle this correctly. Trying to catch a specific exception by writing a catch block for a base class will not work!" )
#       else
#           define MVIA_FUNCTION __FUNCTION__
#       endif // #if _MSC_VER < 1300
#       pragma warning( disable : 4512 ) // 'assignment operator could not be generated' (reason: assignment operators declared 'private' but not implemented)
#   elif defined(__BORLANDC__) // is Borland compiler?
#       pragma option push -b // force enums to the size of integer
#       define MVIA_FUNCTION __FUNC__
#   else
#       define MVIA_FUNCTION __FUNCTION__
#   endif // #ifdef _MSC_VER
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS)

#ifndef WRAP_ANY
#   include <algorithm>
#   include <assert.h>
#   include <common/auto_array_ptr.h>
#   include <common/crt/mvstring.h>
#   include <common/function_cast.h>
#   include <limits.h>
#   include <map>
#   ifdef __BORLANDC__ // is Borland compiler?
#       include <mem.h> // Borland has own ideas about where 'memset' should be defined...
#   endif // #ifdef __BORLANDC__
#   include <set>
#   include <sstream>
#   include <stack>
#   include <stdexcept>
#   include <stdlib.h>
#   include <string>
#   include <vector>
#endif // #ifdef WRAP_ANY

#ifndef WRAP_ANY
#   ifdef MVIMPACT_H_
namespace mvIMPACT
{
// needed to keep the C-header working
using mvIMPACT_C::IPL_BUFHANDLE;
} // namespace mvIMPACT
#   endif // #ifdef MVIMPACT_H_
#endif // #ifndef WRAP_ANY

// C-API header will be imported into mvIMPACT::acquire if included from here
#include <mvDeviceManager/Include/mvDeviceManager.h>

namespace mvIMPACT
{
/// \namespace mvIMPACT::acquire This namespace contains classes and functions belonging to the image acquisition module of this SDK.
namespace acquire
{

/// \defgroup CommonInterface Common
/// \brief Classes and functions that are available for all interface layouts.
///
/// This group contains classes and functions that are available for all interface layouts.
///
/// @{

// predeclares
#ifndef DOXYGEN_SHOULD_SKIP_THIS
class CameraDescriptionManager;
class CameraSettingsBlueCOUGAR;
class CameraSettingsBlueFOX;
class ComponentList;
class ComponentLocator;
class Device;
class DigitalInput;
class DigitalOutput;
class HDRControl;
class IOSubSystem;
class ImageProcessing;
class ImageRequestControl;
class Request;
class RTCtrProgram;
class RTCtrProgramStep;
class WhiteBalanceSettings;
#endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS

#ifdef MVIMPACT_H_
//-----------------------------------------------------------------------------
/// \brief A base class for exceptions generated by mvIMPACT Acquire.
/**
 * \if DOXYGEN_CPP_DOCUMENTATION
 * If \a mvIMPACT.h has been included before including this interface, this class will
 * be derived from \b mvIMPACT::ImpactException, which is derived from \b std::runtime_error.
 * If this interface is used without the rest of the \b mvIMPACT library, this class
 * will be derived directly from \b std::runtime_error, but apart from that will provide the
 * same interface and class layout.
 * \endif
*/
class ImpactAcquireException : public mvIMPACT::ImpactException
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::ImpactAcquireException object.
    explicit ImpactAcquireException(
        /// [in] The string representation of the error.
        const std::string& errorString,
        /// [in] The origin of the error (function name and line)
        const std::string& errorOrigin,
        /// [in] The numerical representation of the error.
        int errorCode ) : ImpactException( errorString, errorOrigin, errorCode ) {}
    virtual ~ImpactAcquireException() throw() {}
    /// \brief Returns a string representation of the error associated with the exception.
    /**
     * This function will return the name of the enum of the error code.
     *
     * \b EXAMPLE
     *
     * In case of error \b -2102 this function would return \b mvIMPACT::acquire::DMR_DRV_ALREADY_IN_USE, which
     * is the error codes corresponding enum name.
     */
    std::string getErrorCodeAsString( void ) const
    {
        return DMR_ErrorCodeToString( getErrorCode() );
    }
    /// \brief Returns a string representation of a error.
    /**
     * This function will return the name of the enum of the error code.
     *
     * \b EXAMPLE
     *
     * In case of error \b -2102 this function would return \b mvIMPACT::acquire::DMR_DRV_ALREADY_IN_USE, which
     * is the error codes corresponding enum name.
     */
    static std::string getErrorCodeAsString(
        /// [in] The error code to query a string representation for.
        int errorCode )
    {
        return DMR_ErrorCodeToString( errorCode );
    }
};
#else
//-----------------------------------------------------------------------------
/// \brief A base class for exceptions generated by mvIMPACT Acquire.
class ImpactAcquireException : public std::runtime_error
//-----------------------------------------------------------------------------
{
    const int m_errorCode;
    const std::string m_errorOrigin;
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::ImpactAcquireException object.
    explicit ImpactAcquireException(
        /// [in] The string representation of the error.
        const std::string& errorString,
        /// [in] The origin of the error (function name and line)
        const std::string& errorOrigin,
        /// [in] The numerical representation of the error.
        int errorCode ) : std::runtime_error( errorString ), m_errorCode( errorCode ), m_errorOrigin( errorOrigin ) {}
    virtual ~ImpactAcquireException() throw() {}
    /// \brief Returns an error string containing information about the reason for the error.
    std::string getErrorString( void ) const
    {
        return what();
    }
    /// \brief Returns a unique numerical representation for this error.
    int getErrorCode( void ) const
    {
        return m_errorCode;
    }
    /// \brief Returns a string representation of the error associated with the exception.
    /**
     * This function will return the name of the enum of the error code.
     *
     * \b EXAMPLE
     *
     * In case of error \b -2102 this function would return \b mvIMPACT::acquire::DMR_DRV_ALREADY_IN_USE, which
     * is the error codes corresponding enum name.
     */
    std::string getErrorCodeAsString( void ) const
    {
        return DMR_ErrorCodeToString( m_errorCode );
    }
    /// \brief Returns a string representation of a error.
    /**
     * This function will return the name of the enum of the error code.
     *
     * \b EXAMPLE
     *
     * In case of error \b -2102 this function would return \b mvIMPACT::acquire::DMR_DRV_ALREADY_IN_USE, which
     * is the error codes corresponding enum name.
     */
    static std::string getErrorCodeAsString(
        /// [in] The error code to query a string representation for.
        int errorCode )
    {
        return DMR_ErrorCodeToString( errorCode );
    }
    /// \brief Returns information about the origin of the error.
    /**
     * The string returned by this function will contain the name of the function
     * and the line number where the exception was raised.
     */
    std::string getErrorOrigin( void ) const
    {
        return m_errorOrigin;
    }
};
#endif // #ifdef MVIMPACT_H_

//-----------------------------------------------------------------------------
/// \brief A base class for device manager related exceptions.
class EDeviceManager : public ImpactAcquireException
//-----------------------------------------------------------------------------
{
public:
    /// \brief Creates a new \b mvIMPACT::acquire::EDeviceManager object.
    explicit EDeviceManager(
        /// [in] The error string.
        const std::string& errorString,
        /// [in] The error origin.
        const std::string& errorOrigin,
        /// [in] The error code.
        TDMR_ERROR errorCode ) : ImpactAcquireException( errorString, errorOrigin, errorCode ) {}
    virtual ~EDeviceManager() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief A base class for exceptions related to the property module.
/**
 * This exception object will only be raised if an unknown error occurred.
 * To check for errors related to the property module a catch block for
 * \b mvIMPACT::acquire::EPropertyHandling objects can be written to catch all property module related
 * exceptions.
 */
class EPropertyHandling : public ImpactAcquireException
//-----------------------------------------------------------------------------
{
public:
    /// \brief Creates a new \b mvIMPACT::acquire::EPropertyHandling object.
    explicit EPropertyHandling(
        /// [in] The error string.
        const std::string& errorString,
        /// [in] The error origin.
        const std::string& errorOrigin,
        /// [in] The error code.
        TPROPHANDLING_ERROR errorCode ) : ImpactAcquireException( errorString, errorOrigin, errorCode ) {}
    virtual ~EPropertyHandling() throw() {}
};

//-----------------------------------------------------------------------------
// COMPONENT EXCEPTION CLASSES :
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// \brief A base class for \b mvIMPACT::acquire::Component object related exceptions from the property module.
/**
 * This exception object will never be raised in the code. It can't be constructed
 * directly but to check for \b mvIMPACT::acquire::Component related errors a catch block for
 * \b mvIMPACT::acquire::EComponent objects can be written to catch all \b mvIMPACT::acquire::Component related
 * exceptions.
 */
class EComponent : public EPropertyHandling
//-----------------------------------------------------------------------------
{
protected:
    /// \brief Creates a new \b mvIMPACT::acquire::EComponent object.
    explicit EComponent(
        /// [in] The error string.
        const std::string& errorString,
        /// [in] The error origin.
        const std::string& errorOrigin,
        /// [in] The error code.
        TPROPHANDLING_ERROR errorCode ) : EPropertyHandling( errorString, errorOrigin, errorCode ) {}
    virtual ~EComponent() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_NOT_A_LIST error.
class ENotAList : public EComponent
//-----------------------------------------------------------------------------
{
public:
    explicit ENotAList( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EComponent( boMsgIsNameOnly ? "Component '" + msg + "' is not a list. Unable to perform list operation" : msg, errorOrigin, PROPHANDLING_NOT_A_LIST ) {}
    virtual ~ENotAList() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_NOT_A_PROPERTY error.
class ENotAProperty : public EComponent
//-----------------------------------------------------------------------------
{
public:
    explicit ENotAProperty( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EComponent( boMsgIsNameOnly ? "Component '" + msg + "' is not a property. Unable to perform property operation" : msg, errorOrigin, PROPHANDLING_NOT_A_PROPERTY ) {}
    virtual ~ENotAProperty() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_NOT_A_METHOD error.
class ENotAMethod : public EComponent
//-----------------------------------------------------------------------------
{
public:
    explicit ENotAMethod( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EComponent( boMsgIsNameOnly ? "Component '" + msg + "' is not a method. Unable to perform function call operation" : msg, errorOrigin, PROPHANDLING_NOT_A_METHOD ) {}
    virtual ~ENotAMethod() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_NO_READ_RIGHTS error.
class ENoReadRights : public EComponent
//-----------------------------------------------------------------------------
{
public:
    explicit ENoReadRights( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EComponent( boMsgIsNameOnly ? "No read rights for component '" + msg + "'" : msg, errorOrigin, PROPHANDLING_NO_READ_RIGHTS ) {}
    virtual ~ENoReadRights() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_NO_WRITE_RIGHTS error.
class ENoWriteRights : public EComponent
//-----------------------------------------------------------------------------
{
public:
    explicit ENoWriteRights( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EComponent( boMsgIsNameOnly ? "No write rights for component '" + msg + "'" : msg, errorOrigin, PROPHANDLING_NO_WRITE_RIGHTS ) {}
    virtual ~ENoWriteRights() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_NO_MODIFY_SIZE_RIGHTS error.
class ENoModifySizeRights : public EComponent
//-----------------------------------------------------------------------------
{
public:
    explicit ENoModifySizeRights( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EComponent( boMsgIsNameOnly ? "Component '" + msg + "'s size is fixed and therefore cannot be modified" : msg, errorOrigin, PROPHANDLING_NO_MODIFY_SIZE_RIGHTS ) {}
    virtual ~ENoModifySizeRights() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_INCOMPATIBLE_COMPONENTS error.
class EIncompatibleComponents : public EComponent
//-----------------------------------------------------------------------------
{
public:
    explicit EIncompatibleComponents( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EComponent( boMsgIsNameOnly ? "Component '" + msg + "' has been compared with an incompatible type (might differ in components, size, etc.)" : msg, errorOrigin, PROPHANDLING_INCOMPATIBLE_COMPONENTS ) {}
    virtual ~EIncompatibleComponents() throw() {}
};

//-----------------------------------------------------------------------------
// PROPERTY EXCEPTION CLASSES :
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// \brief A base class for \b mvIMPACT::acquire::Property related exceptions from the property module.
/**
 * This exception object will never be raised in the code. It can't be constructed
 * directly but to check for \b mvIMPACT::acquire::Property related errors a catch block for
 * \b mvIMPACT::acquire::EProperty objects can be written to catch all \b mvIMPACT::acquire::Property related
 * exceptions.
 */
class EProperty : public EComponent
//-----------------------------------------------------------------------------
{
protected:
    /// \brief Creates a new \b mvIMPACT::acquire::EProperty object.
    explicit EProperty(
        /// [in] The error string.
        const std::string& errorString,
        /// [in] The error origin.
        const std::string& errorOrigin,
        /// [in] The error code.
        TPROPHANDLING_ERROR errorCode ) : EComponent( errorString, errorOrigin, errorCode ) {}
    virtual ~EProperty() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_INVALID_PROP_VALUE error.
class EInvalidValue : public EProperty
//-----------------------------------------------------------------------------
{
public:
    explicit EInvalidValue( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EProperty( boMsgIsNameOnly ? "Invalid value for property '" + msg + "'" : msg, errorOrigin, PROPHANDLING_INVALID_PROP_VALUE ) {}
    virtual ~EInvalidValue() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_PROP_VAL_ID_OUT_OF_BOUNDS error.
class EValIDOutOfBounds : public EProperty
//-----------------------------------------------------------------------------
{
public:
    explicit EValIDOutOfBounds( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EProperty( boMsgIsNameOnly ? "Value ID out of bounds for property '" + msg + "'" : msg, errorOrigin, PROPHANDLING_PROP_VAL_ID_OUT_OF_BOUNDS ) {}
    virtual ~EValIDOutOfBounds() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_PROP_TRANSLATION_TABLE_CORRUPTED error.
class ETranslationTableCorrupted : public EProperty
//-----------------------------------------------------------------------------
{
public:
    explicit ETranslationTableCorrupted( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EProperty( boMsgIsNameOnly ? "The translation dictionary of property '" + msg + "' is corrupted" : msg, errorOrigin, PROPHANDLING_PROP_TRANSLATION_TABLE_CORRUPTED ) {}
    virtual ~ETranslationTableCorrupted() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_PROP_TRANSLATION_TABLE_NOT_DEFINED error.
class ETranslationTableNotDefined : public EProperty
//-----------------------------------------------------------------------------
{
public:
    explicit ETranslationTableNotDefined( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EProperty( boMsgIsNameOnly ? "Translation dictionary has not been defined for property '" + msg + "'" : msg, errorOrigin, PROPHANDLING_PROP_TRANSLATION_TABLE_NOT_DEFINED ) {}
    virtual ~ETranslationTableNotDefined() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_INVALID_PROP_VALUE_TYPE error.
class EInvalidValueType : public EProperty
//-----------------------------------------------------------------------------
{
public:
    explicit EInvalidValueType( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EProperty( boMsgIsNameOnly ? "Property '" + msg + "' does not support this value type" : msg, errorOrigin, PROPHANDLING_INVALID_PROP_VALUE_TYPE ) {}
    virtual ~EInvalidValueType() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_PROP_VAL_TOO_LARGE error.
class EValTooLarge : public EProperty
//-----------------------------------------------------------------------------
{
public:
    explicit EValTooLarge( const std::string& msg, const std::string& errorOrigin ) : EProperty( msg, errorOrigin, PROPHANDLING_PROP_VAL_TOO_LARGE ) {}
    explicit EValTooLarge( const std::string& value, const std::string& maxValue, const std::string& propName, const std::string& errorOrigin ) : EProperty( "The value '" + value + "' is larger than the maximum value(" + maxValue + ") for property '" + propName + "'", errorOrigin, PROPHANDLING_PROP_VAL_TOO_LARGE ) {}
    virtual ~EValTooLarge() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_PROP_VAL_TOO_SMALL error.
class EValTooSmall : public EProperty
//-----------------------------------------------------------------------------
{
public:
    explicit EValTooSmall( const std::string& msg, const std::string& errorOrigin ) : EProperty( msg, errorOrigin, PROPHANDLING_PROP_VAL_TOO_SMALL ) {}
    explicit EValTooSmall( const std::string& value, const std::string& minValue, const std::string& propName, const std::string& errorOrigin ) : EProperty( "The value'" + value + "' is smaller than the minimum value(" + minValue + ") for property '" + propName + "'", errorOrigin, PROPHANDLING_PROP_VAL_TOO_SMALL ) {}
    virtual ~EValTooSmall() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_PROP_VALIDATION_FAILED error.
class EValidationFailed : public EProperty
//-----------------------------------------------------------------------------
{
public:
    explicit EValidationFailed( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EProperty( boMsgIsNameOnly ? "The assigned value doesn't pass the validation test for property '" + msg + "'" : msg, errorOrigin, PROPHANDLING_PROP_VALIDATION_FAILED ) {}
    virtual ~EValidationFailed() throw() {}
};

//-----------------------------------------------------------------------------
// PROPERTYLIST EXCEPTION CLASSES :
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// \brief A base class for component list related exceptions from the property module.
/**
 * This exception object will never be raised in the code. It can't be constructed
 * directly but to check for component list related errors a catch block for
 * \b mvIMPACT::acquire::EPropertyList objects can be written to catch all exceptions related
 * to lists and list operations.
 */
class EPropertyList : public EComponent
//-----------------------------------------------------------------------------
{
protected:
    /// \brief Creates a new \b mvIMPACT::acquire::EPropertyList object.
    explicit EPropertyList(
        /// [in] The error string.
        const std::string& errorString,
        /// [in] The error origin.
        const std::string& errorOrigin,
        /// [in] The error code.
        TPROPHANDLING_ERROR errorCode ) : EComponent( errorString, errorOrigin, errorCode ) {}
    virtual ~EPropertyList() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_COMPONENT_NOT_FOUND error.
class EComponentNotFound : public EPropertyList
//-----------------------------------------------------------------------------
{
public:
    explicit EComponentNotFound( const std::string& msg, const std::string& errorOrigin ) : EPropertyList( msg, errorOrigin, PROPHANDLING_COMPONENT_NOT_FOUND ) {}
    virtual ~EComponentNotFound() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_LIST_ENTRY_OCCUPIED error.
class EListEntryOccupied : public EPropertyList
//-----------------------------------------------------------------------------
{
public:
    explicit EListEntryOccupied( const std::string& errorOrigin ) : EPropertyList( "List entry occupied already", errorOrigin, PROPHANDLING_LIST_ENTRY_OCCUPIED ) {}
    virtual ~EListEntryOccupied() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_COMPONENT_ID_INVALID error.
class EComponentIDInvalid : public EPropertyList
//-----------------------------------------------------------------------------
{
public:
    explicit EComponentIDInvalid( const std::string& errorOrigin ) : EPropertyList( "Invalid component ID", errorOrigin, PROPHANDLING_COMPONENT_ID_INVALID ) {}
    virtual ~EComponentIDInvalid() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_LIST_ID_INVALID error.
class EInvalidListID : public EPropertyList
//-----------------------------------------------------------------------------
{
public:
    explicit EInvalidListID( const std::string& errorOrigin ) : EPropertyList( "Invalid property list ID", errorOrigin, PROPHANDLING_LIST_ID_INVALID ) {}
    explicit EInvalidListID( const std::string& msg, const std::string& errorOrigin ) : EPropertyList( msg, errorOrigin, PROPHANDLING_LIST_ID_INVALID ) {}
    virtual ~EInvalidListID() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_LIST_CANT_ACCESS_DATA error.
class ECantAccessData : public EPropertyList
//-----------------------------------------------------------------------------
{
public:
    explicit ECantAccessData( const std::string& msg, const std::string& errorOrigin, bool boMsgIsPathOnly = true ) : EPropertyList( boMsgIsPathOnly ? "Cannot access data from '" + msg + "'" : msg, errorOrigin, PROPHANDLING_LIST_CANT_ACCESS_DATA ) {}
    virtual ~ECantAccessData() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_CANT_REGISTER_COMPONENT error.
class ECantRegisterComponent : public EPropertyList
//-----------------------------------------------------------------------------
{
public:
    explicit ECantRegisterComponent( const std::string& errorOrigin ) : EPropertyList( "Cannot register component in the current list.", errorOrigin, PROPHANDLING_CANT_REGISTER_COMPONENT ) {}
    explicit ECantRegisterComponent( const std::string& msg, const std::string& errorOrigin ) : EPropertyList( msg, errorOrigin, PROPHANDLING_CANT_REGISTER_COMPONENT ) {}
    virtual ~ECantRegisterComponent() throw() {}
};

//-----------------------------------------------------------------------------
// METHOD EXCEPTION CLASSES :
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// \brief A base class for \b mvIMPACT::acquire::Method object related exceptions from the property module.
/**
 * This exception object will never be raised in the code. It can't be constructed
 * directly but to check for \b mvIMPACT::acquire::Method object related errors a catch block for
 * \b mvIMPACT::acquire::EMethod objects can be written to catch only \b Method related exceptions.
 */
class EMethod : public EComponent
//-----------------------------------------------------------------------------
{
protected:
    /// \brief Creates a new \b mvIMPACT::acquire::EMethod object.
    explicit EMethod(
        /// [in] The error string.
        const std::string& errorString,
        /// [in] The error origin.
        const std::string& errorOrigin,
        /// [in] The error code.
        TPROPHANDLING_ERROR errorCode ) : EComponent( errorString, errorOrigin, errorCode ) {}
    virtual ~EMethod() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_METHOD_PTR_INVALID error.
class EMethodPtrInvalid : public EMethod
//-----------------------------------------------------------------------------
{
public:
    explicit EMethodPtrInvalid( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EMethod( boMsgIsNameOnly ? "The function pointer for Method '" + msg + "' is invalid" : msg, errorOrigin, PROPHANDLING_METHOD_PTR_INVALID ) {}
    virtual ~EMethodPtrInvalid() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_METHOD_INVALID_PARAM_LIST error.
class EInvalidParameterList : public EMethod
//-----------------------------------------------------------------------------
{
public:
    explicit EInvalidParameterList( const std::string& errorOrigin ) : EMethod( "The functions parameter list is invalid", errorOrigin, PROPHANDLING_METHOD_INVALID_PARAM_LIST ) {}
    explicit EInvalidParameterList( const std::string& msg, const std::string& errorOrigin ) : EMethod( msg, errorOrigin, PROPHANDLING_METHOD_INVALID_PARAM_LIST ) {}
    virtual ~EInvalidParameterList() throw() {}
};

//-----------------------------------------------------------------------------
// PROPERTYHANDLING EXCEPTION CLASSES :
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_UNSUPPORTED_PARAMETER error.
class EUnsupportedParameter : public EPropertyHandling
//-----------------------------------------------------------------------------
{
public:
    explicit EUnsupportedParameter( const std::string& errorOrigin ) : EPropertyHandling( "Unsupported parameter", errorOrigin, PROPHANDLING_UNSUPPORTED_PARAMETER ) {}
    virtual ~EUnsupportedParameter() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_SIZE_MISMATCH error.
class ESizeMismatch : public EPropertyHandling
//-----------------------------------------------------------------------------
{
public:
    explicit ESizeMismatch( const std::string& errorString, const std::string& errorOrigin ) : EPropertyHandling( errorString, errorOrigin, PROPHANDLING_SIZE_MISMATCH ) {}
    virtual ~ESizeMismatch() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_IMPLEMENTATION_MISSING error.
class EImplementationMissing : public EPropertyHandling
//-----------------------------------------------------------------------------
{
public:
    explicit EImplementationMissing( const std::string& errorOrigin ) : EPropertyHandling( "This feature has not been implemented so far", errorOrigin, PROPHANDLING_IMPLEMENTATION_MISSING ) {}
    explicit EImplementationMissing( const std::string& msg, const std::string& errorOrigin ) : EPropertyHandling( msg, errorOrigin, PROPHANDLING_IMPLEMENTATION_MISSING ) {}
    virtual ~EImplementationMissing() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_INVALID_INPUT_PARAMETER error.
class EInvalidInputParameter : public EPropertyHandling
//-----------------------------------------------------------------------------
{
public:
    explicit EInvalidInputParameter( const std::string& errorOrigin ) : EPropertyHandling( "One or more of the input parameters are invalid (unassigned pointers?)", errorOrigin, PROPHANDLING_INVALID_INPUT_PARAMETER ) {}
    explicit EInvalidInputParameter( const std::string& msg, const std::string& errorOrigin ) : EPropertyHandling( msg, errorOrigin, PROPHANDLING_INVALID_INPUT_PARAMETER ) {}
    virtual ~EInvalidInputParameter() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_INPUT_BUFFER_TOO_SMALL error.
class EInputBufferTooSmall : public EPropertyHandling
//-----------------------------------------------------------------------------
{
public:
    explicit EInputBufferTooSmall( const std::string& errorOrigin ) : EPropertyHandling( "The user supplied input buffer was too small for the result", errorOrigin, PROPHANDLING_INPUT_BUFFER_TOO_SMALL ) {}
    virtual ~EInputBufferTooSmall() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_WRONG_PARAM_COUNT error.
class EWrongParamCount : public EPropertyHandling
//-----------------------------------------------------------------------------
{
public:
    explicit EWrongParamCount( const std::string& errorOrigin ) : EPropertyHandling( "Wrong parameter count", errorOrigin, PROPHANDLING_WRONG_PARAM_COUNT ) {}
    explicit EWrongParamCount( const std::string& msg, const std::string& errorOrigin ) : EPropertyHandling( msg, errorOrigin, PROPHANDLING_WRONG_PARAM_COUNT ) {}
    virtual ~EWrongParamCount() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_UNSUPPORTED_OPERATION error.
class EUnsupportedOperation : public EPropertyHandling
//-----------------------------------------------------------------------------
{
public:
    explicit EUnsupportedOperation( const std::string& errorOrigin ) : EPropertyHandling( "This component does not support this operation", errorOrigin, PROPHANDLING_UNSUPPORTED_OPERATION ) {}
    virtual ~EUnsupportedOperation() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_CANT_SERIALIZE_DATA error.
class ECantSerializeData : public EPropertyHandling
//-----------------------------------------------------------------------------
{
public:
    explicit ECantSerializeData( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EPropertyHandling( boMsgIsNameOnly ? "No serialize rights for list '" + msg + "'" : msg, errorOrigin, PROPHANDLING_CANT_SERIALIZE_DATA ) {}
    virtual ~ECantSerializeData() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_INVALID_FILE_CONTENT error.
class EInvalidFileContent : public EPropertyHandling
//-----------------------------------------------------------------------------
{
public:
    explicit EInvalidFileContent( const std::string& msg, const std::string& errorOrigin, bool boMsgIsNameOnly = true ) : EPropertyHandling( boMsgIsNameOnly ? "The file '" + msg + "' does not contain valid data for this operation" : msg, errorOrigin, PROPHANDLING_INVALID_FILE_CONTENT ) {}
    virtual ~EInvalidFileContent() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief An exception thrown in case of a \b mvIMPACT::acquire::PROPHANDLING_CANT_ALLOCATE_LIST error.
class ECantAllocateNewList : public EPropertyHandling
//-----------------------------------------------------------------------------
{
public:
    explicit ECantAllocateNewList( const std::string& errorOrigin ) : EPropertyHandling( "Cannot allocate a new list until an old one has been deleted", errorOrigin, PROPHANDLING_CANT_ALLOCATE_LIST ) {}
    virtual ~ECantAllocateNewList() throw() {}
};

//-----------------------------------------------------------------------------
/// \brief A factory class to raise mvIMPACT Acquire related exceptions.
/**
 * This class contains a collection of static member functions that are used inside the
 * interface to raise the appropriate exception in case of an error
 */
class ExceptionFactory
//-----------------------------------------------------------------------------
{
public:
    /// \brief Returns the last error string that did occur inside the framework within the current thread.
    /**
     * \return The last error string that did occur inside the framework within the current thread.
     */
    static std::string getLastErrorString( void )
    {
        size_t stringSize = 0;
        TDMR_ERROR lastError = DMR_NO_ERROR;
        TDMR_ERROR result = DMR_GetLastError( &lastError, 0, &stringSize );
        if( result != DMR_NO_ERROR )
        {
            return "";
        }
        char* pStringBuffer = new char[stringSize];
        result = DMR_GetLastError( &lastError, pStringBuffer, &stringSize );
        const std::string errorString( ( result == DMR_NO_ERROR ) ? pStringBuffer : "" );
        delete [] pStringBuffer;
        return errorString;
    }
    /// \brief Raises an exception from an error code, its origin in terms of the function name and the line number the error did occur and an optional component handle.
    static void raiseException(
        /// [in] The name of the function this exception was raised from.
        const char* pFunctionName,
        /// [in] The line number in the source this exception was raised from.
        int lineNumber,
        /// [in] The error code.
        int errorCode,
        /// [in] A handle to an object.
        HOBJ objectHandle = INVALID_ID );
    /// \brief Raises an exception from an error code, its origin in terms of the function name and the line number the error did occur and an exception string.
    static void raiseException(
        /// [in] The name of the function this exception was raised from.
        const char* pFunctionName,
        /// [in] The line number in the source this exception was raised from.
        int lineNumber,
        /// [in] The error code.
        TDMR_ERROR errorCode,
        /// [in] The actual exception text.
        const std::string& msg )
    {
        std::ostringstream oss;
        oss << pFunctionName << " (line: " << lineNumber << ")";
        throw EDeviceManager( msg, oss.str(), errorCode );
    }
};

#ifdef DOXYGEN_SHOULD_SKIP_THIS
#   define MVIMPACT_H_ // force doxygen to include mvIMPACT related functions
#endif // #ifdef DOXYGEN_SHOULD_SKIP_THIS

//-----------------------------------------------------------------------------
/// \brief A base class to implement access to internal driver objects.
/**
 * Instances of this class can't be constructed directly.
 */
class ComponentAccess
//-----------------------------------------------------------------------------
{
    friend class ComponentLocatorBase;
protected:
    /// \brief An internal constant that defines by which factor dynamic buffers will grow when the current size is not sufficient.
    enum { BUFFER_INCREMENT_FACTOR = 6 };
    /// \brief A unique identifier for the internal driver object referenced by this instance of \b mvIMPACT::acquire::ComponentAccess.
    HOBJ m_hObj;
    /// \brief A helper function to query certain component related string parameters.
    /**
     * This function might throw an exception, if an invalid parameter has been queried.
     * \return A string containing the data to be queried.
     */
    std::string compGetStringParam( /// The type of the parameter to read
        TOBJ_StringQuery query,
        /// [in] An additional parameter
        int param1 = 0,
        /// [in] An additional parameter
        int param2 = 0 ) const
    {
        char* pStr = 0;
        std::string stringParam;
        const TPROPHANDLING_ERROR result = OBJ_GetSWithInplaceConstruction( m_hObj, query, &pStr, stringAllocator, param1, param2 );
        if( result == PROPHANDLING_NO_ERROR )
        {
            if( pStr )
            {
                stringParam = std::string( pStr );
            }
            delete [] pStr;
        }
        else
        {
            delete [] pStr;
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return stringParam;
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::ComponentAccess object to a driver object.
    explicit ComponentAccess(
        /// [in] A valid handle to a component object
        HOBJ hObj ) : m_hObj( hObj )
    {
        const TPROPHANDLING_ERROR result = OBJ_CheckHandle( m_hObj, hcmOwnerList );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
    }
    /// \brief Constructs a new unbound \b mvIMPACT::acquire::ComponentAccess object.
    explicit ComponentAccess( void ) : m_hObj( INVALID_ID ) {}
    /// \brief An internal helper function for fast string allocation.
    static char* stringAllocator( const char* pBuf, size_t reqBufSize )
    {
        char* pStr = new char[reqBufSize];
        mv_strncpy_s( pStr, pBuf, reqBufSize );
        return pStr;
    }
public:
    virtual ~ComponentAccess( void ) {}
    /// \brief Constructs a new \b mvIMPACT::acquire::ComponentAccess from an existing one.
    ComponentAccess(
        /// [in] A constant reference to the \b mvIMPACT::acquire::ComponentAccess object, this object shall be created from
        const ComponentAccess& src ) : m_hObj( src.m_hObj ) {}
    /// \brief Allows implicit conversion to a HOBJ.
    operator HOBJ() const
    {
        return m_hObj;
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::ComponentAccess objects.
    ComponentAccess& operator=( const ComponentAccess& rhs )
    {
        m_hObj = rhs.m_hObj;
        return *this;
    }
    /// \brief Returns the current changed counter for the component referenced by this object.
    /**
     *  This changed counter is incremented internally each time the component is modified.
     *  To check if this component has been modified since the last time, this check has been
     *  performed, keep track of the last return value of this function and compare
     *  it with the new value. This can be helpful e.g. to keep a GUI up to date. The value returned
     *  by this function will always be larger than or equal to the value returned by
     *  \b mvIMPACT::acquire::ComponentAccess::changedCounterAttr (except in case of a
     *  wrap around) when called at the same time for the same object as it's always incremented
     *  when the component has been modified in
     *  any way while the latter one will only be incremented if the attributes (e.g. the
     *  flags) but \b NOT if e.g. the value(s) of a property has been modified.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  //-----------------------------------------------------------------------------
     *  struct ComponentRef
     *  //-----------------------------------------------------------------------------
     *  {
     *    mvIMPACT::acquire::Component c_;
     *    unsigned int lastChangedCount_;
     *    ComponentRef( mvIMPACT::acquire::Component c ) : c_( c ), lastChangedCount_( 0 ) {}
     *  };
     *
     *  //-----------------------------------------------------------------------------
     *  void fn( ComponentRef& cr )
     *  //-----------------------------------------------------------------------------
     *  {
     *    if( cr.c_.isValid() )
     *    {
     *      const unsigned int currentChangedCount = cr.c_.changedCounter();
     *      if( currentChangedCount != cr.lastChangedCount_ )
     *      {
     *        // something has happened since the last check!
     *        doWhatNeedsToBeDone();
     *        // and remember the current changed counter
     *        cr.lastChangedCount_ = currentChangedCount;
     *      }
     *    }
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  import mvIMPACT.acquire.*;
     *
     *  //-----------------------------------------------------------------------------
     *  public class ComponentRef
     *  //-----------------------------------------------------------------------------
     *  {
     *    private Component c_;
     *    private long lastChangedCount_;
     *    public ComponentRef( Component c ) : c_( c ), lastChangedCount_( 0 ) {}
     *    public Component getComponent()
     *    {
     *      return c_;
     *    }
     *    public long getLastChangedCounter()
     *    {
     *      return lastChangedCount_;
     *    }
     *    public void setLastChangedCounter( long changedCounter )
     *    {
     *      lastChangedCount_ = lastChangedCount;
     *    }
     *  }
     *
     *  // ...more code, class definition etc.
     *
     *  //-----------------------------------------------------------------------------
     *  public static void fn( ComponentRef cr )
     *  //-----------------------------------------------------------------------------
     *  {
     *    if( cr.c_.isValid() )
     *    {
     *      final long currentChangedCount = cr.getComponent().changedCounter();
     *      if( currentChangedCount != cr.getLastChangedCounter() )
     *      {
     *        // something has happened since the last check!
     *        doWhatNeedsToBeDone();
     *        // and remember the current changed counter
     *        cr.setLastChangedCounter( currentChangedCount );
     *      }
     *    }
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  class ComponentRef
     *    def __init__(self, c):
     *      self.c_ = c
     *      self.lastChangedCount_ = 0
     *
     *  def fn(cr):
     *    if cr.c_.isValid:
     *      currentChangedCount = cr.c_.changedCounter()
     *      if currentChangedCount != cr.lastChangedCount_:
     *        # something has happened since the last check!
     *        doWhatNeedsToBeDone()
     *        # and remember the current changed counter
     *        cr.lastChangedCount_ = currentChangedCount
     * \endcode
     * \endif
     *
     * \return The current changed counter of this object.
     */
    unsigned int changedCounter( void ) const
    {
        unsigned int changedCounter;
        const TPROPHANDLING_ERROR result = OBJ_GetChangedCounter( m_hObj, &changedCounter );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return changedCounter;
    }
    /// \brief Returns the current attribute changed counter for the component referenced by this object.
    /**
     * This changed counter is incremented internally each time the components attributes have been modified.
     * To check if this components attributes have been modified since the last time, this check has been
     * performed, keep track of the last return value of this function and compare
     * it with the new value. This can be helpful e.g. to keep a GUI up to date.
     *
     * \note
     * Attributes changes are e.g. a modification to a property's translation dictionary,
     * but \b NOT a property's value. Because of this the value returned by this function
     * will always be less or equal than the value returned by the function
     * \b mvIMPACT::acquire::ComponentAccess::changedCounter (except in case of a
     * wrap around) when called at the same time for the same object.
     * \sa \b mvIMPACT::acquire::ComponentAccess::changedCounter
     * \return The current attributes changed counter of this object.
     */
    unsigned int changedCounterAttr( void ) const
    {
        unsigned int changedCounter;
        const TPROPHANDLING_ERROR result = OBJ_GetChangedCounterAttr( m_hObj, &changedCounter );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return changedCounter;
    }
    /// \brief Returns a unique identifier for the component referenced by this object.
    /**
     *  \return A unique identifier for the component referenced by this object.
     */
    HOBJ hObj( void ) const
    {
        return m_hObj;
    }
    /// \brief Returns the name of the component referenced by this object.
    /**
     *  \return The name of the component referenced by this object.
     */
    std::string name( void ) const
    {
        return compGetStringParam( sqObjName );
    }
    /// \brief Returns the display name of the component referenced by this object.
    /**
     *
     * \since 1.11.20
     *
     *  \return The display name of the component referenced by this object. This might be an empty string if no display name has been specified.
     */
    std::string displayName( void ) const
    {
        return compGetStringParam( sqObjDisplayName );
    }
};

//-----------------------------------------------------------------------------
/// \brief A base class to implement access to internal driver components.
/**
 *  Objects of this class can be constructed directly even if nothing is known about the type
 *  of driver object we are referring to. This class acts as a base class to provide
 *  access to internal properties, methods and component lists offered by the driver.
 *
 *  This object can be used to navigate through component lists of
 *  unknown content.
 *
 *  Consider the following structure:
 *
 * \code
 *  LA
 *  |-LB
 *  |-LC
 *  |  |-PE
 *  |  |-PF
 *  |  |-PG
 *  |-PD
 * \endcode
 *
 *  Where the prefix 'L' means this is a list, 'P' that this is a property.
 *  Assuming that we have and iterator referencing list 'C', calling \b mvIMPACT::acquire::Component::firstChild
 *  e.g. would return a new iterator referencing object 'PE', while calling \b mvIMPACT::acquire::Component::nextSibling
 *  would have returned a reference to 'PD' and \b mvIMPACT::acquire::Component::parent would have
 *  returned a reference to object 'LA'.
 *
 *  \b "EXAMPLE 1":
 *
 * A new \b mvIMPACT::acquire::Component is created with the \a ID of list 'C':
 *
 *  \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  Component it(ID_of_list_C);
 *  it = it.firstChild();    // now we are referencing 'PE'
 *  it = it.lastSibling();   // moves to 'PG'
 *  it = it.firstSibling();  // moves back to PE'
 *  it = it.nextSibling();   // moves to 'PF'
 *  it = it.firstSibling();  // moves back to PE'
 *  it = it.parent();        // we are referencing 'LC' again
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  Component it = new Component(ID_of_list_C);
 *  it = it.firstChild();    // now we are referencing 'PE'
 *  it = it.lastSibling();   // moves to 'PG'
 *  it = it.firstSibling();  // moves back to PE'
 *  it = it.nextSibling();   // moves to 'PF'
 *  it = it.firstSibling();  // moves back to PE'
 *  it = it.parent();        // we are referencing 'LC' again
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  it = acquire.Component(ID_of_list_C);
 *  it = it.firstChild()    # now we are referencing 'PE'
 *  it = it.lastSibling()   # moves to 'PG'
 *  it = it.firstSibling()  # moves back to PE'
 *  it = it.nextSibling()   # moves to 'PF'
 *  it = it.firstSibling()  # moves back to PE'
 *  it = it.parent()        # we are referencing 'LC' again
 * \endcode
 * \endif
 *
 *  \b "EXAMPLE 2":
 *
 *  Iterate over a complete list including sub lists. This will result in a list
 *  of all lists and properties that reside in the list the iterator currently
 *  is moving through to be written to the standard output. The name of the component
 *  and every parent component will be printed into the standard output:
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 * //-----------------------------------------------------------------------------
 *  void ParseList( Component iter, const string& path = "" )
 *  //-----------------------------------------------------------------------------
 *  {
 *    while( iter.isValid() )
 *    {
 *      if( iter.isVisible() )
 *      {
 *        if( iter.isList() )
 *        {
 *          // do some list specific stuff
 *          cout << "List     " << path << iter.name() << "/" << endl;
 *          // move down into the list and append its name to the path
 *          ParseList( iter.firstChild(), path + iter.name() + "/" );
 *        }
 *        else if( iter.isProp() )
 *        {
 *          // do property specific stuff e.g. read the value
 *          Property prop( iter );
 *          cout << "Property " << path << prop.name() << "(value(s): ";
 *          unsigned int valCount = prop.valCount();
 *          for( unsigned int i=0; i<valCount; i++ )
 *          {
 *            cout << prop.readS();
 *            if( i < valCount - 1 )
 *            {
 *              cout << ", ";
 *            }
 *          }
 *          cout << ")" << endl;
 *        }
 *      }
 *      ++iter;
 *    }
 *  }
 *
 *  //-----------------------------------------------------------------------------
 *  int main( int argc, char* argv[] )
 *  //-----------------------------------------------------------------------------
 *  {
 *    ComponentList baselist;
 *    // ....
 *    Component it( baselist );
 *    ParseList( it );
 *    // ....
 *    return 0;
 * }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 * //-----------------------------------------------------------------------------
 * public class FeatureListParser
 * //-----------------------------------------------------------------------------
 * {
 *   static
 *   {
 *     try
 *     {
 *       System.loadLibrary( "mvIMPACT_Acquire.java" );
 *     }
 *     catch( UnsatisfiedLinkError e )
 *     {
 *       System.err.println( "Native code library failed to load. Make sure the 'mvIMPACT_Acquire.java' library can be found in the systems search path.\n" + e );
 *       System.exit( 1 );
 *     }
 *  }
 *
 *  //-----------------------------------------------------------------------------
 *  public static void ParseList( Component iter, final String path )
 *  //-----------------------------------------------------------------------------
 *  {
 *    while( iter.isValid() )
 *    {
 *      if( iter.isVisible() )
 *      {
 *        if( iter.isList() )
 *        {
 *          // do some list specific stuff
 *          System.out.println( String.format( "List     %s%s/", path, iter.name() ) );
 *          // move down into the list and append its name to the path
 *          ParseList( iter.firstChild(), path + iter.name() + "/" );
 *        }
 *        else if( iter.isProp() )
 *        {
 *          // do property specific stuff e.g. read the value
 *          Property prop = new Property(iter.hObj());
 *          StringBuilder values = new StringBuilder();
 *
 *          final long valCount = prop.valCount();
 *          for( long i=0; i<valCount; i++ )
 *          {
 *            values.append( prop.readS( ( int )i ) );
 *            if( i < valCount - 1 )
 *            {
 *              values.append( ", " );
 *            }
 *          }
 *          System.out.println( String.format( "Property %s%s(value(s): %s)", path, prop.name(), values.toString() ) );
 *        }
 *      }
 *      iter = iter.nextSibling();
 *    }
 *  }
 *
 *  //-----------------------------------------------------------------------------
 *  public static void main( String[] args )
 *  //-----------------------------------------------------------------------------
 *  {
 *    // ....
 *    Component baselist( gethObjOfListToParse() );
 *    ParseList( it );
 *    // ....
 *  }
 * }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 * def ParseList(iter, path = ""):
 *  while iter.isValid:
 *    if iter.isVisible:
 *      if iter.isList:
 *        # do some list specific stuff
 *        print("List     {0}{1}/".format(path, iter.name()))
 *        # move down into the list and append its name to the path
 *        ParseList(iter.firstChild(), path + iter.name() + "/")
 *      elif iter.isProp:
 *        # do property specific stuff e.g. read the value
 *        prop = acquire.Property(iter.hObj())
 *        values = []
 *        valCount = prop.valCount()
 *        for i in range(valCount):
 *          values.append(prop.readS(i))
 *        print("Property {0}{1}(value(s): {2})".format(path, prop.name(), string.join(values, ",")))
 *    iter = iter.nextSibling()
 *
 * it = acquire.Component(gethObjOfListToParse())
 * ParseList(it)
 * \endcode
 * \endif
 */
class Component : public ComponentAccess
//-----------------------------------------------------------------------------
{
private:
    //-----------------------------------------------------------------------------
    template<typename _FnQuery> size_t queryFeatureCount( _FnQuery pFnQuery ) const
    //-----------------------------------------------------------------------------
    {
        size_t featureCount = 0;
        const TPROPHANDLING_ERROR result = pFnQuery( m_hObj, 0, 0, &featureCount );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return featureCount;
    }
    //-----------------------------------------------------------------------------
    template<typename _FnQuery> size_t queryFeatures( std::vector<Component>& v, _FnQuery pFnQuery ) const
    //-----------------------------------------------------------------------------
    {
        v.clear();
        size_t featureCount = queryFeatureCount( pFnQuery );
        if( featureCount > 0 )
        {
            std::vector<HOBJ> buf;
            buf.resize( featureCount );
            const TPROPHANDLING_ERROR result = pFnQuery( m_hObj, 0, &( *( buf.begin() ) ), &featureCount );
            if( result != PROPHANDLING_NO_ERROR )
            {
                ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
            }
            v.resize( featureCount );
            for( size_t i = 0; i < featureCount; i++ )
            {
                v[i] = Component( buf[i] );
            }
        }
        return static_cast<size_t>( v.size() );
    }
    //-----------------------------------------------------------------------------
    template<typename _FnQuery> HOBJ queryFeature( _FnQuery pFnQuery, int index ) const
    //-----------------------------------------------------------------------------
    {
        HOBJ hObj;
        size_t featureCount = 1;
        const TPROPHANDLING_ERROR result = pFnQuery( m_hObj, index, &hObj, &featureCount );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return hObj;
    }
    //-----------------------------------------------------------------------------
    template<typename _FnQuery> std::string queryAsString( _FnQuery pFnQuery ) const
    //-----------------------------------------------------------------------------
    {
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        auto_array_ptr<char> pBuf( bufSize );
        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = pFnQuery( m_hObj, pBuf.get(), bufSize ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            pBuf.realloc( bufSize );
        }
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return std::string( pBuf.get() );
    }
public:
    /// \brief Constructs a new access object to a driver object.
    explicit Component(
        /// [in] A valid handle to a component object
        HOBJ hObj ) : ComponentAccess( hObj ) {}
    /// \brief Constructs a new unbound access object.
    explicit Component( void ) {}
    /// \brief Constructs a new \b mvIMPACT::acquire::Component from an existing one.
    Component(
        /// [in] A constant reference to the \b mvIMPACT::acquire::Component object, this object shall be created from
        const Component& src ) : ComponentAccess( src ) {}
    /// \brief Moves to the next sibling(the next feature in the current list of features).
    /**
     *  \return A self reference
     */
    Component& operator++( void ) // prefix
    {
        HOBJ nextSibling;
        const TPROPHANDLING_ERROR result = OBJ_GetNextSibling( m_hObj, &nextSibling );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        m_hObj = nextSibling;
        return *this;
    }
    /// \brief Moves to the next sibling(the next feature in the current list of features).
    /**
     *  \return A new \b mvIMPACT::acquire::Component object
     */
    Component operator++( int ) // postfix
    {
        Component temp( *this );
        ++*this;
        return temp;
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::Component objects.
    Component& operator=( const Component& rhs )
    {
        ComponentAccess::operator=( rhs );
        return *this;
    }
    /// \brief Moves to the first sibling(the first feature in the current list of features).
    /**
     *  \return A new \b mvIMPACT::acquire::Component object
     */
    Component firstSibling( void ) const
    {
        HOBJ hNew = INVALID_ID;
        const TPROPHANDLING_ERROR result = OBJ_GetFirstSibling( m_hObj, &hNew );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return ( hNew != INVALID_ID ) ? Component( hNew ) : Component();
    }
    /// \brief Moves to the last sibling(the last feature in the current list of features).
    /**
     *
     * \since 1.10.64
     *
     *  \return A new \b mvIMPACT::acquire::Component object
     */
    Component lastSibling( void ) const
    {
        HOBJ hNew = INVALID_ID;
        const TPROPHANDLING_ERROR result = OBJ_GetLastSibling( m_hObj, &hNew );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return ( hNew != INVALID_ID ) ? Component( hNew ) : Component();
    }
    /// \brief Moves to the next sibling(the next feature in the current list of features).
    /**
     *  \return A new \b mvIMPACT::acquire::Component object
     */
    Component nextSibling( void )
    {
        return ++*this;
    }
    /// \brief Moves to the first child of this component(moves down one level).
    /**
     * Calling this function will only succeed, if the current \b mvIMPACT::acquire::Component
     * references a list.
     *
     * \return A new \b mvIMPACT::acquire::Component object
     */
    Component firstChild( void ) const
    {
        HOBJ hNew = INVALID_ID;
        const TPROPHANDLING_ERROR result = OBJ_GetFirstChild( m_hObj, &hNew );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return ( hNew != INVALID_ID ) ? Component( hNew ) : Component();
    }
    /// \brief Moves to the parent of this component(moves up one level).
    /**
     *  \return A new \b mvIMPACT::acquire::Component object
     */
    Component parent( void ) const
    {
        HOBJ hNew = INVALID_ID;
        const TPROPHANDLING_ERROR result = OBJ_GetParent( m_hObj, &hNew );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return ( hNew != INVALID_ID ) ? Component( hNew ) : Component();
    }
    /// \brief Returns a string containing general information about the component referenced by this object.
    /**
     *  \return A string containing general information about the component referenced by this object.
     */
    std::string docString( void ) const
    {
        return compGetStringParam( sqObjDocString );
    }
    /// \brief Returns the flags associated with this component.
    /**
     *  \return The flags associated with this component.
     */
    TComponentFlag flags( void ) const
    {
        TComponentFlag flags;
        const TPROPHANDLING_ERROR result = OBJ_GetFlags( m_hObj, &flags );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return flags;
    }
    /// \brief Returns the flags associated with this component as a string.
    /**
     *  \return The flags associated with this component as a string.
     */
    std::string flagsAsString(
        /// [in] A user definable string to separate the individual flags. The default value is ' | ' resulting in the string to look e.g. like this: <b>'cfWriteAccess | cfReadAccess'</b>
        const std::string& separator = " | " ) const
    {
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        auto_array_ptr<char> pBuf( bufSize );
        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_GetFlagsS( m_hObj, separator.c_str(), pBuf.get(), pBuf.parCnt() ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            pBuf.realloc( bufSize );
        }
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return std::string( pBuf.get() );
    }
    /// \brief Checks if this component is currently referencing the default for this component.
    /**
     *  This function will return true only for derived components that have not been modified.
     *  \return
     *  - true if the component is currently set to its default value
     *  - false otherwise.
     */
    bool isDefault( void ) const
    {
        unsigned int isDefault;
        const TPROPHANDLING_ERROR result = OBJ_IsDefault( m_hObj, &isDefault );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return isDefault != 0;
    }
    /// \brief Checks if this component is of type \b mvIMPACT::acquire::ComponentList.
    /**
     *  \return
     *  - true if the component references a list
     *  - false otherwise
     */
    bool isList( void ) const
    {
        return ( type() & ctList ) != 0;
    }
    /// \brief Checks if this component is of type \b mvIMPACT::acquire::Method.
    /**
     *  \return
     *  - true if the component references a method
     *  - false otherwise
     */
    bool isMeth( void ) const
    {
        return ( type() & ctMeth ) != 0;
    }
    /// \brief Checks if this component is of type \b mvIMPACT::acquire::Property or a derived type.
    /**
     *  \return
     *  - true if the component references a property
     *  - false otherwise
     */
    bool isProp( void ) const
    {
        return ( type() & ctProp ) != 0;
    }
    /// \brief Checks if the internal component referenced by this object is still valid.
    /**
     *  This function can be used to verify whether a referenced component
     *  is still valid or not. When e.g. referencing a driver property after
     *  \b mvIMPACT::acquire::Device::close has been called this function would return false.
     *  Calling any other function that tries to access the referenced component
     *  in that case would raise an exception.
     *  \return
     *  - true if this object currently references a valid component
     *  - false otherwise.
     */
    bool isValid( void ) const
    {
        return OBJ_CheckHandle( m_hObj, hcmFull ) == PROPHANDLING_NO_ERROR;
    }
    /// \brief Checks if the component is currently shadowed due to a settings made elsewhere or not.
    /**
     * Settings applied to certain components might affect the behaviour of others. For example
     * an activated automatic gain control might shadow the value written to the
     * gain property by the user as the gain is calculated internally. In order to
     * check if modifying the actual component will affect the behaviour of the
     * system this function may be used. When it returns \a true, the \b mvIMPACT::acquire::Component
     * will have an impact on the system, if \a false is returned, the feature might be
     * modified, but this will currently NOT influence the acquisition process or the overall behaviour
     * of the device or driver.
     *
     * This is what is called visibility. The user still might modify or read the
     * current \b mvIMPACT::acquire::Component when it's not visible however the actual data will
     * be used only if the \b Component is visible (\b mvIMPACT::acquire::cfInvisible
     * must \b NOT be set).
     *
     * The visibility of a \b mvIMPACT::acquire::Component object will change only if other
     * \b mvIMPACT::acquire::Component objects are modified and \b NEVER when a program
     * runs but does not change any \b mvIMPACT::acquire::Component.
     */
    bool isVisible( void ) const
    {
        return ( flags() & cfInvisible ) == 0;
    }
    /// \brief Checks if the caller has write/modify access to the component.
    /**
     *  \return
     *  - true if the caller is allowed to call write/modify operation for this component.
     *  - false otherwise.
     */
    bool isWriteable( void ) const
    {
        return ( flags() & cfWriteAccess ) != 0;
    }
    /// \brief Restores the default for the referenced component.
    /**
     * Calling this function will restore the default value for the
     * component referenced by this object.
     *
     * If this function is called for an object of type \b mvIMPACT::acquire::ComponentList
     * every component in that list is restored to the default value.
     *
     * \note The caller must have the right to modify the component. Otherwise
     * an exception will be thrown.
     *
     * \return A const reference to the component.
     */
    const Component& restoreDefault( void ) const
    {
        const TPROPHANDLING_ERROR result = OBJ_RestoreDefault( m_hObj );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Returns the type of the referenced component.
    /**
     *  \return The type of the referenced component.
     */
    TComponentType type( void ) const
    {
        TComponentType type;
        const TPROPHANDLING_ERROR result = OBJ_GetType( m_hObj, &type );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return type;
    }
    /// \brief Returns the type of the component referenced by \a hObj.
    /**
     *  \return The type of the component referenced by \a hObj.
     */
    static TComponentType type(
        /// [in] The component the type shall be retrieved for
        HOBJ hObj )
    {
        return Component( hObj ).type();
    }
    /// \brief Returns the type of the referenced component as a string.
    /**
     *  \return The type of the referenced component as a string.
     */
    std::string typeAsString( void ) const
    {
        return queryAsString( OBJ_GetTypeS );
    }
    /// \brief Returns the recommended visibility for this component.
    /**
     * The visibility can be used e.g. to develop a GUI that displays a
     * crucial subset of features only.
     *
     * Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TComponentVisibility.
     * \return The recommended visibility for this component.
     */
    TComponentVisibility visibility( void ) const
    {
        TComponentVisibility visibility;
        const TPROPHANDLING_ERROR result = OBJ_GetVisibility( m_hObj, &visibility );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return visibility;
    }
    /// \brief Returns the recommended visibility of the referenced component as a string.
    /**
     *  \return The recommended visibility of the referenced component as a string.
     */
    std::string visibilityAsString( void ) const
    {
        return queryAsString( OBJ_GetVisibilityS );
    }
    /// \brief Returns the recommended visibility converted to a string.
    /**
     *  \return The recommended visibility converted to a string.
     */
    static std::string visibilityAsString(
        /// [in] The visibility to query the string representation for
        TComponentVisibility visibility )
    {
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        auto_array_ptr<char> pBuf( bufSize );
        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_VisibilityToString( visibility, pBuf.get(), bufSize ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            pBuf.realloc( bufSize );
        }
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        return std::string( pBuf.get() );
    }
    /// \brief Returns the recommended representation for this component.
    /**
     * The representation can be used e.g. to develop a GUI that creates convenient controls
     *  for certain features.
     *
     * Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TComponentRepresentation.
     *
     *  \since 2.14.0
     *
     * \return The recommended representation for this component.
     */
    TComponentRepresentation representation( void ) const
    {
        TComponentRepresentation representation;
        const TPROPHANDLING_ERROR result = OBJ_GetRepresentation( m_hObj, &representation );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return representation;
    }
    /// \brief Returns the recommended representation of the referenced component as a string.
    /**
     *
     *  \since 2.14.0
     *
     *  \return The recommended representation of the referenced component as a string.
     */
    std::string representationAsString( void ) const
    {
        return queryAsString( OBJ_GetRepresentationS );
    }
    /// \brief Returns the recommended representation converted to a string.
    /**
     *
     *  \since 2.14.0
     *
     *  \return The recommended representation converted to a string.
     */
    static std::string representationAsString(
        /// [in] The representation to query the string representation for
        TComponentRepresentation representation )
    {
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        auto_array_ptr<char> pBuf( bufSize );
        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_RepresentationToString( representation, pBuf.get(), bufSize ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            pBuf.realloc( bufSize );
        }
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        return std::string( pBuf.get() );
    }
    /// \brief Returns the number of features selected by the current one.
    /**
     * \sa
     * \b mvIMPACT::acquire::Component::selectedFeatures, \n
     * \b mvIMPACT::acquire::Component::selectedFeature
     *
     * \since 1.11.20
     *
     * \return The number of features selected by the current one.
     */
    unsigned int selectedFeatureCount( void ) const
    {
        return static_cast<unsigned int>( queryFeatureCount( OBJ_GetSelectedFeatures ) );
    }
    /// \brief Returns the number of features selecting the current one.
    /**
     * \sa
     * \b mvIMPACT::acquire::Component::selectingFeatures, \n
     * \b mvIMPACT::acquire::Component::selectingFeature
     *
     * \since 1.11.20
     *
     * \return The number of features selecting the current one.
     */
    unsigned int selectingFeatureCount( void ) const
    {
        return static_cast<unsigned int>( queryFeatureCount( OBJ_GetSelectingFeatures ) );
    }
    /// \brief Retrieves the list of components that are selected by the current one.
    /**
     * This function retrieves the list of components that are selected by
     * the current one. This information is mainly useful for GUI applications that want to arrange
     * features in a way that dependencies between features can easily been spotted.
     *
     * When a component 'selects' other components, this indicates that selected components may change whenever
     * the selecting component changes. An example for a selector might be a property defining the index within
     * a LUT while the value of a particular LUT entry could be a selected feature. Assuming 2 properties
     * \a LUTIndex and \a LUTValue then changing \a LUTIndex will invalidate and possibly change \a LUTValue.
     *
     * \sa
     * \b mvIMPACT::acquire::Component::selectedFeatureCount, \n
     * \b mvIMPACT::acquire::Component::selectedFeature
     *
     * \since 1.11.20
     *
     * \return The number of features selected by the current one.
     */
    unsigned int selectedFeatures(
        /// [out] An array that will retrieve the list of components that are selected by the current one.
        std::vector<Component>& v ) const
    {
        return static_cast<unsigned int>( queryFeatures( v, OBJ_GetSelectedFeatures ) );
    }
    /// \brief Retrieves the list of components that are selecting the current one.
    /**
     * This function retrieves the list of components that are selecting
     * the current one. This information is mainly useful for GUI applications that want to arrange
     * features in a way that dependencies between features can easily been spotted.
     *
     * When a component 'selects' other components, this indicates that selected components may change whenever
     * the selecting component changes. An example for a selector might be a property defining the index within
     * a LUT while the value of a particular LUT entry could be a selected feature. Assuming 2 properties
     * \a LUTIndex and \a LUTValue then changing \a LUTIndex will invalidate and possibly change \a LUTValue.
     *
     * \sa
     * \b mvIMPACT::acquire::Component::selectingFeatureCount, \n
     * \b mvIMPACT::acquire::Component::selectingFeature
     *
     * \since 1.11.20
     *
     * \return The number of features selecting the current one.
     */
    unsigned int selectingFeatures(
        /// [out] An array that will retrieve the list of components that are selecting the current one.
        std::vector<Component>& v ) const
    {
        return static_cast<unsigned int>( queryFeatures( v, OBJ_GetSelectingFeatures ) );
    }
    /// \brief Retrieves a component that is selected by the current one.
    /**
     * This function retrieves a component that is selected by the current one.
     * This information is mainly useful for GUI applications that want to arrange
     * features in a way that dependencies between features can easily been spotted.
     *
     * When a component 'selects' other components, this indicates that selected components may change whenever
     * the selecting component changes. An example for a selector might be a property defining the index within
     * a LUT while the value of a particular LUT entry could be a selected feature. Assuming 2 properties
     * \a LUTIndex and \a LUTValue then changing \a LUTIndex will invalidate and possibly change \a LUTValue.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * C++ offers the more efficient function \b mvIMPACT::acquire::Component::selectedFeatures to obtain this
     * information.
     * \endif
     *
     * To find out how many \b mvIMPACT::acquire::Component objects are selected by the current one call
     * \b mvIMPACT::acquire::Component::selectedFeatureCount. This value minus 1 will also be the
     * max. value for \a index.
     * \sa
     * \b mvIMPACT::acquire::Component::selectedFeatureCount, \n
     * \b mvIMPACT::acquire::Component::selectedFeatures
     *
     * \since 1.11.20
     *
     * \return A \b mvIMPACT::acquire::Component that is selected by the current one.
     */
    Component selectedFeature(
        /// [in] The index for the component to query.
        unsigned int index ) const
    {
        return Component( queryFeature( OBJ_GetSelectedFeatures, static_cast<int>( index ) ) );
    }
    /// \brief Retrieves a component that is selecting the current one.
    /**
     * This function retrieves a component that is selecting the current one.
     * This information is mainly useful for GUI applications that want to arrange
     * features in a way that dependencies between features can easily been spotted.
     *
     * When a component 'selects' other components, this indicates that selected components may change whenever
     * the selecting component changes. An example for a selector might be a property defining the index within
     * a LUT while the value of a particular LUT entry could be a selected feature. Assuming 2 properties
     * \a LUTIndex and \a LUTValue then changing \a LUTIndex will invalidate and possibly change \a LUTValue.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * C++ offers the more efficient function \b mvIMPACT::acquire::Component::selectingFeatures to obtain this
     * information.
     * \endif
     *
     * To find out how many \b mvIMPACT::acquire::Component objects are selecting the current one call
     * \b mvIMPACT::acquire::Component::selectingFeatureCount. This value minus 1 will also be the
     * max. value for \a index.
     * \sa
     * \b mvIMPACT::acquire::Component::selectingFeatureCount, \n
     * \b mvIMPACT::acquire::Component::selectingFeatures
     *
     * \since 1.11.20
     *
     * \return A \b mvIMPACT::acquire::Component that is selecting the current one.
     */
    Component selectingFeature(
        /// [in] The index for the component to query.
        unsigned int index ) const
    {
        return Component( queryFeature( OBJ_GetSelectingFeatures, static_cast<int>( index ) ) );
    }
};

//-----------------------------------------------------------------------------
/// \brief A simple helper class to wrap the creation of a callback object.
/**
 * Applications need to derive from this class and must re-implement the function
 * \b mvIMPACT::acquire::ComponentCallback::execute.
 *
 * By deriving from this class it will become possible to receive a notification whenever
 * an object derived from \b mvIMPACT::acquire::Component has changed. So e.g. an application
 * could register a callback on the \b mvIMPACT::acquire::Device::state property to get
 * notified when e.g. a certain device has been unplugged or restarted.
 *
 * \note
 * A \c change is not necessarily a changed value of a property but also any other change
 * in behaviour like a change in visibility or availability. So when a callback has been registered
 * for a certain read-only component that becomes writable for some reason the registered
 * callback would be executed as well.
 *
 * A single instance of an object derived from this class can hold an arbitrary number of
 * components which are monitored. components can be registered by calling the \b mvIMPACT::acquire::ComponentCallback::registerComponent
 * function, so it is not necessary to create and hold a callback instance for every feature that shall be
 * monitored. Since when the callback is executed the information about the object that has
 * triggered it will be supplied as one the input parameters it is easy to decide what has
 * to be done.
 *
 * \attention
 * Reading and understanding the documentation supplied with the \b mvIMPACT::acquire::ComponentCallback::execute function
 * is vital to write error-free code!
 *
 * \attention
 * It is \b NOT save to call \b mvIMPACT::acquire::ComponentCallback::registerComponent and \b mvIMPACT::acquire::ComponentCallback::unregisterComponent
 * from parallel threads! If this is absolutely necessary appropriate synchronization code must be wrapped around these calls by the calling code!
 *
 * \since 1.12.18
 *
 */
class ComponentCallback
//-----------------------------------------------------------------------------
{
#ifndef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    struct CallbackUserData
    //-----------------------------------------------------------------------------
    {
        void* pUserData_;
        ComponentCallback* pCallback_;
        explicit CallbackUserData() : pUserData_( 0 ), pCallback_( 0 ) {}
    };
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        CallbackHandle handle_;
        CallbackUserData callbackUserData_;
        std::set<HOBJ> objectsRegistered_;
        int m_refCnt;
        explicit ReferenceCountedData() : handle_( 0 ), callbackUserData_(), objectsRegistered_(), m_refCnt( 1 ) {}
    }* m_pRefData;
#endif // #ifdef DOXYGEN_SHOULD_SKIP_THIS
#ifndef WRAP_ANY
    //-----------------------------------------------------------------------------
    static void DMR_CALL myCallback( HOBJ hObj, void* pUserData )
    //-----------------------------------------------------------------------------
    {
        Component c( hObj );
        CallbackUserData* p = reinterpret_cast<CallbackUserData*>( pUserData );
        p->pCallback_->execute( c, p->pUserData_ );
    }
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            while( !m_pRefData->objectsRegistered_.empty() )
            {
                if( OBJ_CheckHandle( *m_pRefData->objectsRegistered_.begin(), hcmOwnerList ) == PROPHANDLING_NO_ERROR )
                {
                    unregisterComponent( Component( *m_pRefData->objectsRegistered_.begin() ), false );
                }
                else
                {
                    m_pRefData->objectsRegistered_.erase( *m_pRefData->objectsRegistered_.begin() );
                }
            }
            OBJ_DeleteCallback( m_pRefData->handle_ );
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    bool unregisterComponent( Component c, bool boRaiseExceptionOnError )
    {
        std::set<HOBJ>::iterator it = m_pRefData->objectsRegistered_.find( c.hObj() );
        if( it == m_pRefData->objectsRegistered_.end() )
        {
            return false;
        }
        const TPROPHANDLING_ERROR result = OBJ_DetachCallback( c.hObj(), m_pRefData->handle_ );
        if( boRaiseExceptionOnError && ( result != PROPHANDLING_NO_ERROR ) )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        m_pRefData->objectsRegistered_.erase( *it );
        return true;
    }
#endif // #ifndef WRAP_ANY
public:
    /// \brief Creates a new \b mvIMPACT::acquire::ComponentCallback instance.
    explicit ComponentCallback(
        /// [in] A pointer to user specific data bound to this callback. This data will
        /// be passed back to the user whenever the callback function gets executed and can be used to attach
        /// custom data to the callback function.
        void* pUserData = 0 ) : m_pRefData( new ReferenceCountedData() )
    {
        m_pRefData->callbackUserData_.pUserData_ = pUserData;
        m_pRefData->callbackUserData_.pCallback_ = this;
        const TPROPHANDLING_ERROR result = OBJ_CreateCallback( ctOnChanged, myCallback, &m_pRefData->callbackUserData_, &m_pRefData->handle_ );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
    }
    /// \brief Copy constructor.
    /**
     * Creates a new object from an existing device object. Keep in mind that this new object
     * will provide access to the very same objects. This constructor
     * is only provided for internal reference counting to guarantee correct operation of the
     * objects of this class under all platforms and languages.
     */
    explicit ComponentCallback( const ComponentCallback& src ) : m_pRefData( src.m_pRefData )
    {
        ++( m_pRefData->m_refCnt );
    }
    /// \brief Class destructor.
    /**
     * This will automatically unregister all components still referencing this callback and will
     * free all internal resources.
     */
    virtual ~ComponentCallback()
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::ComponentCallback objects.
    ComponentCallback& operator=( const ComponentCallback& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            // inc. the NEW reference count
            ++( m_pRefData->m_refCnt );
        }
        return *this;
    }
    /// \brief Checks if a component is currently registered for this callback or not.
    /**
     * \return
     *  - true if the component currently is registered for this callback
     *  - false otherwise
     */
    bool isComponentRegistered(
        /// [in] The component that shall be tested against this callback
        Component c ) const
    {
        return m_pRefData->objectsRegistered_.find( c.hObj() ) != m_pRefData->objectsRegistered_.end();
    }
    /// \brief Registers a component for this callback.
    /**
     * \return
     *  - true if the component could be registered successfully for this callback.
     *  - false otherwise
     */
    bool registerComponent(
        /// [in] The component to register for this callback
        Component c )
    {
        if( isComponentRegistered( c ) )
        {
            return false;
        }
        const TPROPHANDLING_ERROR result = OBJ_AttachCallback( c.hObj(), m_pRefData->handle_ );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        m_pRefData->objectsRegistered_.insert( c.hObj() );
        return true;
    }
    /// \brief Unregisters a component for this callback.
    /**
     * \return
     *  - true if the component could be unregistered successfully for this callback.
     *  - false otherwise
     */
    bool unregisterComponent(
        /// [in] The component to unregister from this callback
        Component c )
    {
        return unregisterComponent( c, true );
    }
    /// \brief The callback function.
    /**
     * Re-implement this function in a derived class in order to implement a custom behaviour.
     *
     * \note
     * Please note that this function will be executed within the thread context that is \b causing this callback,
     * thus by any thread belonging to the internal device driver instance. There is a high chance that this is
     * a different thread than any known to by the application, thus appropriate mechanisms to ensure
     * correct execution must be implemented by an application(e.g. GUI applications might send an
     * event to the main thread instead of directly accessing GUI elements from here).
     *
     * As each device driver instance internally creates multiple threads and since components can be modified by the
     * driver framework from any of these threads, the thread context might in fact be different each time
     * this function gets called. Accessing data from objects that are inherited from \b mvIMPACT::acquire::Component is
     * thread safe so e.g. property values can be read out in parallel securely!
     * However this 'execute' in a worst case (when several components have been registered to a single callback) might in
     * fact be called in parallel so everything that happens in here should be designed accordingly!
     *
     * \attention
     * It is \b NOT recommended to do time consuming stuff here! This function should be considered as something like an
     * interrupt instead: Just take a note about what did just happen and leave. The calling thread will block until this
     * function does return which might have all sorts of consequences if this takes a lot of time. In the worst case
     * e.g. image data might get lost!
     *
     * \b GenICam \b event \b specific:
     * When dealing with GenICam device events from a single device only within this callback
     * due to the internal design it is guaranteed that this callback will NOT be executed in parallel
     * since the device events will be received sequentially and will always be reported by the same
     * (device driver instance related) thread! So when e.g. registering for changes to the following
     * properties:
     * - mvIMPACT::acquire::GenICam::EventControl::eventLine4RisingEdgeTimestamp
     * - mvIMPACT::acquire::GenICam::EventControl::eventLine5RisingEdgeTimestamp
     * - mvIMPACT::acquire::GenICam::EventControl::eventExposureEndTimestamp
     * for a single device only then the following things are guaranteed:
     * - The thread context used by the \b mvIMPACT::acquire::ComponentCallback::execute function will always be the same until the device is either closed or the connection is lost e.g. due to a reboot
     * - \b mvIMPACT::acquire::ComponentCallback::execute function will \b NOT be called concurrently
     * - The event property changes will be reported in the same order as generated by the device
     */
    virtual void execute(
        /// [in] The component that did cause the callback to be executed
        Component& PYTHON_OR_JAVA_ONLY( c ),
        /// [in] A pointer to user specific data that was bound to this callback instance
        /// upon construction
        void* PYTHON_OR_JAVA_ONLY( pUserData ) ) {}
};

//-----------------------------------------------------------------------------
/// \brief A base class to locate components within the driver.
/**
 * Every driver will offer a set of properties, methods and component lists.
 * \b mvIMPACT::acquire::Property objects contain data such as the current gain in dB, the state of a
 * digital input, etc.. \b mvIMPACT::acquire::Method objects can be executed like a normal function and
 * \b mvIMPACT::acquire::ComponentList objects are used to group certain
 * objects together to form a logical unit.
 *
 * When it's necessary to locate one or more of these objects without knowing
 * exactly where to look for them this locator class can be used to look for the component.
 */
class ComponentLocatorBase : public ComponentAccess
//-----------------------------------------------------------------------------
{
    HLIST m_searchbase;
public:
    /// \brief Constructs a new unbound locator.
    explicit ComponentLocatorBase() : m_searchbase( INVALID_ID ) {}
    /// \brief Constructs a new bound to the specified base list locator.
    explicit ComponentLocatorBase(
        /// [in] A unique identifier to the base list from where to start to search for
        /// the search base.
        HLIST baselist ) : ComponentAccess( baselist ), m_searchbase( baselist ) {}
    /// \brief Constructs a new locator and searches the search base list.
    explicit ComponentLocatorBase(
        /// [in] A unique identifier to the base list from where to start to search for
        /// the search base.
        HLIST baselist,
        /// [in] The name or path ('/' separated) to the search base.
        const std::string& pathToSearchBase ) : ComponentAccess( baselist ), m_searchbase( INVALID_ID )
    {
        bindSearchBase( baselist, pathToSearchBase );
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::ComponentLocatorBase from an existing one.
    ComponentLocatorBase(
        /// [in] A constant reference to the \b mvIMPACT::acquire::ComponentLocatorBase object, this object shall be created from
        const ComponentLocatorBase& src ) : ComponentAccess( src ), m_searchbase( src.m_searchbase ) {}
    /// \brief Allows assignments of \b mvIMPACT::acquire::ComponentLocatorBase objects.
    ComponentLocatorBase& operator=( const ComponentLocatorBase& rhs )
    {
        ComponentAccess::operator=( rhs );
        m_searchbase = rhs.m_searchbase;
        return *this;
    }
    /// \brief Binds an access object to an internal driver object.
    /**
     * \return
     * - true if successful
     * - false otherwise. In case false is returned by this function the component could not
     * be bound, which means subsequent calls using \a access will fail or throw an exception.
     */
    bool bindComponent(
        /// [in,out] The access object to bind to the driver object.
        Component& access,
        /// [in] The path and/or name of the object to be located.
        const std::string& name,
        /// [in] Specifies how and what to search for. Valid flags(these flags can be combined using the '|' operator) for this parameter
        /// are:
        /// - smIgnoreLists
        /// - smIgnoreMethods
        /// - smIgnoreProperties
        int searchMode = 0,
        /// [in] The maximum depth (in lists) where to search for the component.
        /// By e.g. setting this value to 2, the current list and all
        /// its sub lists will be searched for the object, but no sublists
        /// of sub lists. -1 will search in ALL sub lists.
        int maxSearchDepth = INT_MAX ) const
    {
        access.m_hObj = findComponent( name, searchMode, maxSearchDepth );
        return access.isValid();
    }
    /// \brief Assign a new search base to the locator.
    /**
     *  This new search base will be searched starting from the base list specified.
     *  \return The unique identifier of the new search base.
     */
    HLIST bindSearchBase(
        /// [in] A unique identifier for the base list used to start searching the search base.
        HLIST baselist,
        /// [in] The name or path to the search base.
        const std::string& pathToSearchBase = "" )
    {
        if( pathToSearchBase.empty() )
        {
            m_hObj = m_searchbase = baselist;
        }
        else
        {
            HLIST hList;
            const TPROPHANDLING_ERROR result = OBJ_GetHandleEx( baselist, pathToSearchBase.c_str(), &hList, smIgnoreProperties | smIgnoreMethods, 0 );
            if( result != PROPHANDLING_NO_ERROR )
            {
                ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, baselist );
            }
            m_hObj = baselist;
            m_searchbase = hList;
        }
        return m_searchbase;
    }
    /// \brief Tries to locate a certain component in a hierarchy of components.
    /**
     *  \return A unique identifier to the component if found or \b mvIMPACT::acquire::INVALID_ID if the component couldn't
     *  be found.
     */
    HOBJ findComponent(
        /// [in] The path and/or name of the object to be located.
        const std::string& name,
        /// [in] Specifies how and what to search for. Valid flags(these flags can be combined using the '|' operator) for this parameter
        /// are:
        /// - smIgnoreLists
        /// - smIgnoreMethods
        /// - smIgnoreProperties
        int searchMode = 0,
        /// [in] The maximum depth (in lists) where to search for the component.
        /// By e.g. setting this value to 2, the current list and all
        /// its sub lists will be searched for the object, but no sublists
        /// of sub lists. -1 will search in ALL sub lists.
        int maxSearchDepth = INT_MAX ) const
    {
        HOBJ hObj;
        const TPROPHANDLING_ERROR result = OBJ_GetHandleEx( m_searchbase, name.c_str(), &hObj, searchMode, maxSearchDepth );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_searchbase );
        }
        return hObj;
    }
    /// \brief Returns the unique identifier of the base list from where to start searching for a component.
    /**
     *  \return The unique identifier of the base list from where searching for a component will start currently.
     */
    HLIST searchbase_id( void ) const
    {
        return m_searchbase;
    }
};

//-----------------------------------------------------------------------------
/// \brief A class to locate components within the driver.
/**
 * Every driver will offer a set of properties, methods and component lists.
 * \b mvIMPACT::acquire::Property objects contain data such as the current gain in dB, the state of a
 * digital input, etc.. \b mvIMPACT::acquire::Method objects can be executed like a normal function and
 * \b mvIMPACT::acquire::ComponentList objects are used to group certain
 * objects together to form a logical unit.
 *
 * When it's necessary to locate one or more of these objects without knowing
 * exactly where to look for them this locator class can be used to look for the component.
 */
class ComponentLocator : public ComponentLocatorBase
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new unbound locator.
    explicit ComponentLocator() : ComponentLocatorBase() {}
    /// \brief Constructs a new bound to the specified base list locator.
    explicit ComponentLocator(
        /// [in] A unique identifier to the base list from where to start to search for
        /// the search base.
        HLIST baselist ) : ComponentLocatorBase( baselist ) {}
    /// \brief Constructs a new locator and searches the search base list.
    explicit ComponentLocator(
        /// [in] A unique identifier to the base list from where to start to search for
        /// the search base.
        HLIST baselist,
        /// [in] The name or path ('/' separated) to the search base.
        const std::string& pathToSearchBase ) : ComponentLocatorBase( baselist, pathToSearchBase ) {}
    /// \brief Constructs a new \b mvIMPACT::acquire::ComponentLocator from an existing one.
    ComponentLocator(
        /// [in] A constant reference to the \b mvIMPACT::acquire::ComponentLocator object, this object shall be created from
        const ComponentLocator& src ) : ComponentLocatorBase( src ) {}
    /// \brief Allows assignments of \b mvIMPACT::acquire::ComponentLocator objects.
    ComponentLocator& operator=( const ComponentLocator& rhs )
    {
        ComponentLocatorBase::operator=( rhs );
        return *this;
    }
};

#if !defined(WRAP_ANY) && !defined(BUILD_FOR_JAVA) // don't wrap deprecated stuff
//-----------------------------------------------------------------------------
/// \brief A class to iterate over component lists.
/**
 * \deprecated
 * These days this class is just a typedef mapping the class <b>mvIMPACT::acquire::Component</b> to this type for
 * compatibility reasons. New applications should work with the <b>mvIMPACT::acquire::Component</b> class instead.
 *
 *  This object can be used to navigate through component lists of
 *  unknown content.
 *
 *  Consider the following structure:
 *
 * \code
 *  LA
 *  |-LB
 *  |-LC
 *  |  |-PE
 *  |  |-PF
 *  |  |-PG
 *  |-PD
 * \endcode
 *
 *  Where the prefix 'L' means that this is a list, 'P' that this is a property.
 *  Assuming that we have and iterator referencing list 'C', calling \b mvIMPACT::acquire::ComponentIterator::firstChild
 *  e.g. would return a new iterator referencing object 'PE', while calling \b mvIMPACT::acquire::ComponentIterator::nextSibling
 *  would have returned a reference to 'PD' and \b mvIMPACT::acquire::ComponentIterator::parent would have
 *  returned a reference to object 'LA'.
 *
 *  \b "EXAMPLE 1":
 *
 * A new \b mvIMPACT::acquire::ComponentIterator is created with the \a ID of list 'C':
 *
 *  \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  ComponentIterator it(ID_of_list_C);
 *  it = it.firstChild();    // now we are referencing 'PE'
 *  it = it.lastSibling();   // moves to 'PG'
 *  it = it.firstSibling();  // moves back to PE'
 *  it = it.nextSibling();   // moves to 'PF'
 *  it = it.firstSibling();  // moves back to PE'
 *  it = it.parent();        // we are referencing 'LC' again
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  ComponentIterator it = new ComponentIterator(ID_of_list_C);
 *  it = it.firstChild();    // now we are referencing 'PE'
 *  it = it.lastSibling();   // moves to 'PG'
 *  it = it.firstSibling();  // moves back to PE'
 *  it = it.nextSibling();   // moves to 'PF'
 *  it = it.firstSibling();  // moves back to PE'
 *  it = it.parent();        // we are referencing 'LC' again
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  it = acquire.ComponentIterator(ID_of_list_C);
 *  it = it.firstChild()    # now we are referencing 'PE'
 *  it = it.lastSibling()   # moves to 'PG'
 *  it = it.firstSibling()  # moves back to PE'
 *  it = it.nextSibling()   # moves to 'PF'
 *  it = it.firstSibling()  # moves back to PE'
 *  it = it.parent()        # we are referencing 'LC' again
 * \endcode
 * \endif
 *
 *  \b "EXAMPLE 2":
 *
 *  Iterate over a complete list including sub lists. This will result in a list
 *  of all lists and properties that reside in the list the iterator currently
 *  is moving through to be written to the standard output. The name of the component
 *  and every parent component will be printed into the standard output:
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 * //-----------------------------------------------------------------------------
 *  void ParseList( ComponentIterator iter, const string& path = "" )
 *  //-----------------------------------------------------------------------------
 *  {
 *    while( iter.isValid() )
 *    {
 *      if( iter.isVisible() )
 *      {
 *        if( iter.isList() )
 *        {
 *          // do some list specific stuff
 *          cout << "List     " << path << iter.name() << "/" << endl;
 *          // move down into the list and append its name to the path
 *          ParseList( iter.firstChild(), path + iter.name() + "/" );
 *        }
 *        else if( iter.isProp() )
 *        {
 *          // do property specific stuff e.g. read the value
 *          Property prop(iter);
 *          cout << "Property " << path << prop.name() << "(value(s): ";
 *          unsigned int valCount = prop.valCount();
 *          for( unsigned int i=0; i<valCount; i++ )
 *          {
 *            cout << prop.readS();
 *            if( i < valCount - 1 )
 *            {
 *              cout << ", ";
 *            }
 *          }
 *          cout << ")" << endl;
 *        }
 *      }
 *      ++iter;
 *    }
 *  }
 *
 *  //-----------------------------------------------------------------------------
 *  int main( int argc, char* argv[] )
 *  //-----------------------------------------------------------------------------
 *  {
 *    ComponentList baselist;
 *    // ....
 *    ComponentIterator it(baselist);
 *    ParseList(it);
 *    // ....
 *    return 0;
 * }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 * //-----------------------------------------------------------------------------
 * public class FeatureListParser
 * //-----------------------------------------------------------------------------
 * {
 *   static
 *   {
 *     try
 *     {
 *       System.loadLibrary( "mvIMPACT_Acquire.java" );
 *     }
 *     catch( UnsatisfiedLinkError e )
 *     {
 *       System.err.println( "Native code library failed to load. Make sure the 'mvIMPACT_Acquire.java' library can be found in the systems search path.\n" + e );
 *       System.exit( 1 );
 *     }
 *  }
 *
 *  //-----------------------------------------------------------------------------
 *  public static void ParseList( Component iter, final String path )
 *  //-----------------------------------------------------------------------------
 *  {
 *    while( iter.isValid() )
 *    {
 *      if( iter.isVisible() )
 *      {
 *        if( iter.isList() )
 *        {
 *          // do some list specific stuff
 *          System.out.println( String.format( "List     %s%s/", path, iter.name() ) );
 *          // move down into the list and append its name to the path
 *          ParseList( iter.firstChild(), path + iter.name() + "/" );
 *        }
 *        else if( iter.isProp() )
 *        {
 *          // do property specific stuff e.g. read the value
 *          Property prop = new Property(iter.hObj());
 *          StringBuilder values = new StringBuilder();
 *
 *          final long valCount = prop.valCount();
 *          for( long i=0; i<valCount; i++ )
 *          {
 *            values.append( prop.readS( ( int )i ) );
 *            if( i < valCount - 1 )
 *            {
 *              values.append( ", " );
 *            }
 *          }
 *          System.out.println( String.format( "Property %s%s(value(s): %s)", path, prop.name(), values.toString() ) );
 *        }
 *      }
 *      iter = iter.nextSibling();
 *    }
 *  }
 *
 *  //-----------------------------------------------------------------------------
 *  public static void main( String[] args )
 *  //-----------------------------------------------------------------------------
 *  {
 *    // ....
 *    ComponentIterator baselist = gethObjOfListToParse();
 *    ParseList(it);
 *    // ....
 *  }
 * }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 * def ParseList(iter, path = ""):
 *  while iter.isValid:
 *    if iter.isVisible:
 *      if iter.isList:
 *        # do some list specific stuff
 *        print("List     {0}{1}/".format(path, iter.name()))
 *        # move down into the list and append its name to the path
 *        ParseList(iter.firstChild(), path + iter.name() + "/")
 *      elif iter.isProp:
 *        # do property specific stuff e.g. read the value
 *        prop = acquire.Property(iter.hObj())
 *        values = []
 *        valCount = prop.valCount()
 *        for i in range(valCount):
 *          values.append(prop.readS(i))
 *        print("Property {0}{1}(value(s): {2})".format(path, prop.name(), string.join(values, ",")))
 *    iter = iter.nextSibling()
 *
 * it = acquire.ComponentIterator(gethObjOfListToParse())
 * ParseList(it)
 * \endcode
 * \endif
 */
typedef Component ComponentIterator;
#endif // #if !defined(WRAP_ANY) && !defined(BUILD_FOR_JAVA) // don't wrap deprecated stuff

//-----------------------------------------------------------------------------
/// \brief A class to provide access to component lists.
/**
 *  This class provides access to internal component lists of the driver.
 */
class ComponentList : public Component
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::ComponentList object.
    explicit ComponentList(
        /// [in] A valid handle to a list object
        HLIST hList ) : Component( hList )
    {
        if( !isList() )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, PROPHANDLING_NOT_A_LIST, hList );
        }
    }
    /// \brief Constructs a new unbound \b mvIMPACT::acquire::ComponentList object.
    explicit ComponentList() {}
    /// \brief Constructs a new \b mvIMPACT::acquire::ComponentList from an existing one.
    ComponentList(
        /// [in] A constant reference to the \b mvIMPACT::acquire::ComponentList object, this object shall be created from
        const ComponentList& src ) : Component( src ) {}
    /// \brief Allows assignments of \b mvIMPACT::acquire::ComponentList objects.
    ComponentList& operator=( const ComponentList& rhs )
    {
        Component::operator=( rhs );
        return *this;
    }
    /// \brief Returns The number of valid component entries in the referenced list.
    /**
     *  \return The number of valid component entries in the referenced list.
     */
    unsigned int size( void ) const
    {
        unsigned int size;
        const TPROPHANDLING_ERROR result = OBJ_GetElementCount( m_hObj, &size );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return size;
    }
    /// \brief Returns a string containing information about what's in this list.
    /**
     *  This string might not be defined by every list but in any case this function
     *  will return a valid string. However this string might be empty.
     */
    std::string contentDescriptor( void ) const
    {
        return compGetStringParam( sqListContentDescriptor );
    }
};

//-----------------------------------------------------------------------------
/// \brief A class to call arbitrary driver functions.
/**
 *  Normally all functions needed by the user and offered by the driver will be
 *  provided as a normal function somewhere within this interface. In rare cases
 *  however it might be necessary to call a function, which hasn't been implemented
 *  in this interface. In that case this class will serve as a backdoor.
 */
class Method : public Component
//-----------------------------------------------------------------------------
{
    // do not allow assignments
    Method& operator=( const Method& );

    static bool isCharacterInStringList( std::string::value_type c, const std::vector<std::string>& strings )
    {
        const std::vector<std::string>::size_type stringCount = strings.size();
        for ( std::vector<std::string>::size_type i = 0; i < stringCount; i++ )
        {
            if( strings[i].find( c ) != std::string::npos )
            {
                return true;
            }
        }
        return false;
    }
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::Method object.
    explicit Method(
        /// [in] A valid handle to method object
        HOBJ hMeth ) : Component( hMeth )
    {
        if( !isMeth() )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, PROPHANDLING_NOT_A_METHOD, hMeth );
        }
    }
    /// \brief Constructs a new unbound \b mvIMPACT::acquire::Method object.
    explicit Method() {}
    /// \brief Constructs a new \b mvIMPACT::acquire::Method from an existing one.
    Method(
        /// [in] A constant reference to the \b mvIMPACT::acquire::Method object, this object shall be created from
        const Method& src ) : Component( src ) {}
    /// \brief Calls an underlying driver function.
    /**
     * This function can be used to call any driver function which is registered
     * for the device it is called for. To call a function successfully the parameters
     * passed to the function must match the parameters expected by the function.
     *
     * The parameters are passed as a list of strings.
     *
     * To find out what kind of parameters are expected by the function use
     * the function \b mvIMPACT::acquire::Method::paramList().
     *
     * floating point values can be passed either with a '.' or a ',' acting as the
     * decimal point.
     *
     * 'empty' strings can be passed as a single underline('_').rs.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     *
     * \code
     * // call a function expecting a string and a float
     * vector<string> params;
     * params.push_back( "stringParam" );
     * params.push_back( "3.14" );
     * meth.call( params );
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     * // call a function expecting a string and a float
     * ArrayList<String> list = new ArrayList<String>();
     * list.add( "stringParam" );
     * list.add( "3.14" );
     * StringVector params = new StringVector( list );
     * meth.call( params );
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     * # call a function expecting a string and a float
     * params = []
     * params.append("stringParam")
     * params.append("3.14")
     * meth.call(params)
     * \endcode
     * \endif
     * \return An integer value. For a typical function that is part of the driver SDK this integer value will be
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int call(
        /// [in] The parameters to be passed to the function as a list of strings
        const std::vector<std::string>& params ) const
    {
        if( params.empty() )
        {
            return call();
        }
        const std::vector<std::string>::size_type paramCount = params.size();
        if( paramCount == 1 )
        {
            return call( params[0] );
        }
        const std::string separators( " $%&!?=*#:;()" );
        const std::string::size_type separatorCount = separators.size();
        for( std::string::size_type i = 0; i < separatorCount; i++ )
        {
            if( !isCharacterInStringList( separators[i], params ) )
            {
                const std::string delimiter( separators.substr( i, 1 ) );
                std::string parameterList;
                for( std::vector<std::string>::size_type j = 0; j < paramCount; j++ )
                {
                    if( !parameterList.empty() )
                    {
                        parameterList.append( delimiter );
                    }
                    parameterList.append( params[j] );
                }
                return call( parameterList, delimiter );
            }
        }
        throw EInvalidParameterList( "A valid parameter delimiter could not be determined from the internal list('" + separators + "'). At least one occurrence of each of these characters has been detected in parameter list passed to this function" );
    }
    /// \brief Calls an underlying driver function.
    /**
     * This function can be used to call any driver function which is registered
     * for the device it is called for. To call a function successfully the parameters
     * passed to the function must match the parameters expected by the function.
     *
     * All parameters are passed as a single string, which is parsed with respect to the
     * given delimiter characters internally.
     *
     * To find out what kind of parameters are expected by the function use
     * the function \b mvIMPACT::acquire::Method::paramList().
     *
     * floating point values can be passed either with a '.' or a ',' acting as the
     * decimal point.
     *
     * 'empty' strings can be passed as a single underline('_').
     *
     * \attention
     * The characters '.', ',' and '_' can't be used as delimiters.
     *
     * \if (DOXYGEN_CPP_DOCUMENTATION || DOXYGEN_JAVA_DOCUMENTATION)
     *
     * \code
     * // call a function expecting a string and a float
     * // value parameters separated by spaces
     * meth.call( "stringParam 3,14" );
     * // call of a function expecting 2 integers an a string
     * // where an empty string shall be passed
     * // parameters are separated by '%'
     * meth.call( "1000%666%_", "%" );
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     * # call a function expecting a string and a float
     * # value parameters separated by spaces
     * meth.call("stringParam 3,14")
     * # call of a function expecting 2 integers an a string
     * # where an empty string shall be passed
     * # parameters are separated by '%'
     * meth.call("1000%666%_", "%")
     * \endcode
     * \endif
     * \return An integer value. For a typical function that is part of the driver SDK this integer value will be
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int call(
        /// [in] The parameters to be passed to the function as a single string
        const std::string& params,
        /// [in] A string containing valid delimiter characters for the parameter string
        const std::string& delimiters = " " ) const
    {
        int retval;
        const TPROPHANDLING_ERROR result = OBJ_Execute( m_hObj, params.c_str(), delimiters.c_str(), &retval );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return retval;
    }
    /// \brief Calls an underlying driver function expecting no parameters.
    /**
     * This function can be used to call any driver function which is registered
     * for the device it is called for that does \b NOT expect any parameters
     *
     * To find out what kind of parameters are expected by the function use
     * the function \b mvIMPACT::acquire::Method::paramList().
     *
     * \return An integer value. For a typical function that is part of the driver SDK this integer value will be
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int call( void ) const
    {
        int retval;
        const TPROPHANDLING_ERROR result = OBJ_Execute( m_hObj, 0, 0, &retval );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return retval;
    }
    /// \brief Returns the parameter list of the methods as a string.
    /**
     *  This function returns a string containing one character for each parameter this \b mvIMPACT::acquire::Method
     *  object expects and one for the return type of the function call.
     *
     *  The first character is the return type of the function all others are parameters. void functions
     *  don't specify parameters.
     *
     *  The characters have the following meaning:
     *  - i specifies a 32-bit integer value
     *  - I specifies a 64-bit integer value
     *  - s specifies a pointer to a C-string
     *  - f specifies a double precision float value
     *  - p specifies a pointer value
     *  - v specifies a void return value
     *
     *  \b EXAMPLES:
     *
     *  - 'v': This is a function returning nothing (void). It expects no parameters.
     *  - 'viis': This is a function returning nothing (void). It expects 2 integer values
     *  and one pointer to a C-string.
     *  - 'if': This function returns an integer value and expects a float value.
     *  \return The parameter list of the method as a string.
     */
    std::string paramList( void ) const
    {
        return compGetStringParam( sqMethParamString );
    }
};

//-----------------------------------------------------------------------------
/// \brief Defines valid limits which can be queried for a \b mvIMPACT::acquire::Property object.
enum TPropertyLimits
//-----------------------------------------------------------------------------
{
    /// \brief Set/Get the maximum value for this \b mvIMPACT::acquire::Property.
    /**
     *  Pass this as the index to set or get the maximum number of values this property
     *  can store with a call to the \b mvIMPACT::acquire::Property object's corresponding
     *  \b read or \b write method.
     */
    plMaxValue = PROP_MAX_VAL,
    /// \brief Set/Get the minimum value for this \b mvIMPACT::acquire::Property.
    /**
     *  Pass this as the index to set or get the maximum number of values this property
     *  can store with a call to the \b mvIMPACT::acquire::Property object's corresponding
     *  \b read or \b write method.
     */
    plMinValue = PROP_MIN_VAL,
    /// \brief Set/Get the step width value for this \b mvIMPACT::acquire::Property.
    /**
     *  Pass this as the index to set or get the maximum number of values this property
     *  can store with a call to the \b mvIMPACT::acquire::Property object's corresponding
     *  \b read or \b write method.
     */
    plStepWidth = PROP_STEP_WIDTH
};

//-----------------------------------------------------------------------------
/// \brief A base class for properties.
/**
 *  A property can be used to represent certain values like e.g. the input channel
 *  of a device. Depending on the way the property has been created it is either
 *  possible to read and write data to it or ( when the \b mvIMPACT::acquire::cfWriteAccess flag is \b NOT set )
 *  just to read the data. In rare cases it might also be possible that the user is
 *  is not allowed to read the data of a property. To find out what you are allowed
 *  to do with a property or any other component the function \b mvIMPACT::acquire::Component::flags()
 *  can be called.
 *
 *  A property can contain either a single value or an array of values of the same
 *  type (e.g. 4 integer values could be used to represent a property call 'Rectangle'.
 *  It can even (if the \b mvIMPACT::acquire::cfFixedSize flag is not set) contain
 *  a different number of values all the time its data is queried. E.g. for a property
 *  'searchresults' each time some function is called which writes its results to this
 *  property the property could contain a different number of integer values afterwards.
 *
 *  Every properties value can be read and written either as string or by it actual value type.
 *  So you can either assign the value of an integer property by using the standard 'write' function
 *  that accepts the value to be the type of the property or the function \b mvIMPACT::acquire::Property::writeS
 *  can be used to set the property via a string containing the new value.
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  PropertyI prop(hObj);
 *  prop.writeS("5"); // string assignment
 *  prop.write(5); // integer assignment
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  PropertyI prop = new PropertyI(hObj);
 *  prop.writeS("5"); // string assignment
 *  prop.write(5); // integer assignment
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  prop = acquire.PropertyI(hObj)
 *  prop.writeS("5") # string assignment
 *  prop.write(5) # integer assignment
 * \endcode
 * \endif
 *
 *  In addition to that \e float and \e int Properties might define a translation dictionary. This cannot be
 *  done by the user, but the user can work with the dictionary afterwards. A translation
 *  dictionary is a table which maps strings to certain values (e.g. integers).
 *
 *  The translation dictionary serves two purposes: Once it has been defined this property can only be
 *  assigned values ( which can either be passed as a string or as the actual value )
 *  which are contained in the translation table. Thus this makes it very easy to restrict
 *  a certain property to a fixed number of values, which can be assigned to it.
 *  Properties that have a translation dictionary will typically be defined by declaring
 *  a template instance with the type of the enumeration.
 *
 *  The second benefit of a translation dictionary is that certain values can be assigned
 *  a meaningful description via its translation.
 *  When a translation table has been defined either the string translation can be used to
 *  assign its value or its actual data type. A float property e.g. might define a translation
 *  table like this: 'Auto -> 0', 'auto -> 1', 'OnLowLevel -> 2'. Now to set this property
 *  to use the 'on low level' trigger mode this can be done by calling one of the 'write' functions.
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  PropertyICameraTriggerMode prop = getPropertyFromSomewhere();
 *  prop.writeS("OnLowLevel"); // set value via the translation string
 *  prop.write(ctmOnLowLevel); // set value via enum type
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  PropertyI prop = getPropertyFromSomewhere();
 *  prop.writeS("OnLowLevel"); // set value via the translation string
 *  prop.write(TCameraTriggerMode.ctmOnLowLevel); // set value via enum type
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  prop = getPropertyFromSomewhere() # assuming this function will return a 'PropertyICameraTriggerMode' instance!
 *  prop.writeS("OnLowLevel") # set value via the translation string
 *  prop.write(acquire.ctmOnLowLevel) # set value via enum type
 * \endcode
 * \endif
 *
 *  This can also be extremely useful to populate combo boxes for GUI applications.
 *
 *  Float and int properties can also define certain constants like a max. value or
 *  a min. value. If a property does define such values it can't be assigned values
 *  which do not lie within the defined range. To find out if constants are defined
 *  The user can call the functions \b mvIMPACT::acquire::Property::hasMaxValue,
 *  \b mvIMPACT::acquire::Property::hasMinValue and \b mvIMPACT::acquire::Property::hasStepWidth.
 *  To query to actual value of the max, min or step width the functions
 *  \b getMaxValue, \b getMinValue and \b getStepWidth of the classes
 *  \b mvIMPACT::acquire::EnumPropertyF, \b mvIMPACT::acquire::EnumPropertyI and
 *  \b mvIMPACT::acquire::EnumPropertyI64 can be called.
 *
 *  When reading the value of a property as a string the user can define a format string
 *  telling the property module how to format the returned string. This works pretty much
 *  like when working e.g. with the \e printf function.
 */
class Property : public Component
//-----------------------------------------------------------------------------
{
#ifdef BUILD_FOR_JAVA
public:
    // For building the Java interface this must be public but this does not do any harm as
    // only affects internal behaviour!
    Property& operator=( const Property& rhs )
    {
        Component::operator=( rhs );
        return *this;
    }
private:
#else
    // do not allow assignments! This makes sure the user can't assign e.g. the
    // gain property to the property for controlling the expose time
    Property& operator=( const Property& );
#endif // #ifdef BUILD_FOR_JAVA
    bool isConstDefinedInternal( TPropertyLimits constant ) const
    {
        unsigned int isDefined;
        const TPROPHANDLING_ERROR result = OBJ_IsConstantDefined( m_hObj, constant, &isDefined );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return isDefined != 0;
    }
protected:
    //-----------------------------------------------------------------------------
    int valuesToRead( int start, int end ) const
    //-----------------------------------------------------------------------------
    {
        if( start < 0 )
        {
            // when reading a set of values, these can't include limits or any other value associated with
            // a negative index parameter to avoid confusion cause by END_OF_LIST
            // having the same value as PROP_MAX_VAL.
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, PROPHANDLING_INVALID_INPUT_PARAMETER, m_hObj );
        }
        return ( end == END_OF_LIST ) ? ( valCount() - start ) : ( end - start + 1 );
    }
public:
    /// \brief Constructs a new unbound \b mvIMPACT::acquire::Property object.
    /**
     *  Properties constructed this way can't be used for anything unless they
     *  are bound to a internal driver property with a \b mvIMPACT::acquire::ComponentLocator object.
     */
    explicit Property( void ) {}
    /// \brief Constructs a new \b mvIMPACT::acquire::Property object.
    /**
     *  Properties successfully constructed this way can be worked with directly.
     *  If \a hObj does not reference an internal driver property a \b mvIMPACT::acquire::ENotAProperty
     *  exception will be thrown.
     */
    explicit Property(
        /// [in] A valid handle to a property
        HOBJ hProp ) : Component( hProp )
    {
        if( !isProp() )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, PROPHANDLING_NOT_A_PROPERTY, hProp );
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::Property from an existing one.
    Property(
        /// [in] A constant reference to the \b mvIMPACT::acquire::Property object, this object shall be created from
        const Property& src ) : Component( src ) {}
    /// \brief Checks if this enumerated property allows the combination of enum values.
    /**
     *  If this function returns true, the enum constants can be 'ored' together. This works
     *  for the enum constants as well as for the string representations returned in the
     *  properties translation dictionary.
     *
     *  if a property e.g. defines a dictionary (('1', "one"), ('2', "two")) the following
     *  write operations will be valid:
     *
     * \code
     *  prop = getPropFromSomewhere()
     *  prop.write( 1 | 2 )
     *  prop.write( "one | two" )
     * \endcode
     *
     *  If this function returns true code like this will be valid:
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *
     * \code
     *  enum TEnum
     *  {
     *    eA,
     *    eB
     *  };
     *
     *  typedef EnumPropertyI<TEnum> PropertyIEnum;
     *  PropertyIEnum p = getPropFromSomewhere();
     *  p.write( TEnum(eA | eB) );
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  ImageProcessing ip = new ImageProcessing( pDev );
     *  ip.getMirrorMode().write( TMirrorMode.mmTopDown | TMirrorMode.mmLeftRight );
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  prop = getPropFromSomewhere()
     *  prop.write(1 | 2)
     *  prop.write("one | two")
     * \endcode
     *  \endif
     *  \return
     *  - true if this property allows the combination of enum values.
     *  - false otherwise.
     */
    bool allowsValueCombinations( void ) const
    {
        return ( flags() & cfAllowValueCombinations ) != 0;
    }
    /// \brief Returns the size of the properties translation dictionary.
    /**
     *  If the property does define a translation dictionary this function returns
     *  the number of elements contained in this dictionary.
     *  \return
     *  - The size of the properties translation dictionary.
     *  - 0 If this property does not define a translation dictionary.
     */
    unsigned int dictSize( void ) const
    {
        unsigned int size = 0;
        const TPROPHANDLING_ERROR result = OBJ_GetDictSize( m_hObj, &size );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return size;
    }
    /// \brief Returns whether this property defines a translation dictionary or not.
    /**
     *  \return
     *  - true if this property defines a translation table
     *  - false otherwise
     */
    bool hasDict( void ) const
    {
        return ( dictSize() > 0 );
    }
#if !defined(WRAP_ANY) && !defined(BUILD_FOR_JAVA) // don't wrap deprecated stuff
    /// \brief Checks if a certain constant is defined for this property(\b deprecated).
    /**
     *  \deprecated
     *  This function has been declared <b>deprecated</b> and will be removed in future versions of this interface.
     *  Use \b mvIMPACT::acquire::Property::hasMaxValue(), \b mvIMPACT::acquire::Property::hasMinValue()
     *  and \b mvIMPACT::acquire::Property::hasStepWidth() instead and see the corresponding 'Porting existing code'
     *  section in the documentation.
     *
     *  Valid values for \a constant are defined by the enum \b mvIMPACT::acquire::TPropertyLimits.
     *
     *  \param constant [in] The constant whose existence is in question
     *
     *  \return
     *  - true if this property defines this constant
     *  - false otherwise
     */
    MVIMPACT_DEPRECATED_CPP( bool isConstDefined( TPropertyLimits constant ) const );
#endif // #if !defined(WRAP_ANY) && !defined(BUILD_FOR_JAVA) // don't wrap deprecated stuff
    /// \brief Checks if a maximum value is defined for this property.
    /**
     *  \since 1.12.63
     *
     *  \return
     *  - true if this property defines a maximum value
     *  - false otherwise
     */
    bool hasMaxValue( void ) const
    {
        return isConstDefinedInternal( plMaxValue );
    }
    /// \brief Checks if a minimum value is defined for this property.
    /**
     *  \since 1.12.63
     *
     *  \return
     *  - true if this property defines a minimum value
     *  - false otherwise
     */
    bool hasMinValue( void ) const
    {
        return isConstDefinedInternal( plMinValue );
    }
    /// \brief Checks if a step width is defined for this property.
    /**
     *  \since 1.12.63
     *
     *  \return
     *  - true if this property defines a step width
     *  - false otherwise
     */
    bool hasStepWidth( void ) const
    {
        return isConstDefinedInternal( plStepWidth );
    }
    /// \brief Reads data from this property as a string.
    /**
     *  \note If the caller does not have the needed rights this function might throw an
     *  exception of the type \b mvIMPACT::acquire::ImpactAcquireException.
     *
     *  \return A string containing the data questioned.
     */
    std::string readS(
        /// [in] The index of the desired value(only necessary for properties containing more than one value)
        int index = 0,
        /// [in] The format string telling the function how to format the result. If left empty the property uses its standard way of converting its data into a string
        const std::string& format = "" ) const
    {
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        auto_array_ptr<char> pBuf( bufSize );
        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_GetSFormattedEx( m_hObj, pBuf.get(), &bufSize, ( ( format != "" ) ? format.c_str() : 0 ), index ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            pBuf.realloc( bufSize );
        }
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return std::string( pBuf.get() );
    }
    /// \brief Reads data from this property as a string.
    /**
     *  This function can be used to query a set of values if this property stores more
     *  than a single value which might be useful for GUI applications.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  PropertyI p = getPropFromSomewhere();
     *  p.write( 1 );
     *  p.write( 2, 1 );
     *  p.write( 666, 2 );
     *  std::string s = p.readSArray( "%d", "&&:", 1 );
     *  // now s should contain '2&&:666'
     *  s = p.readSArray( "%4d", " ", 0, 1 );
     *  // now s should contain '   1,   2'
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  PropertyI p = getPropFromSomewhere();
     *  p.write( 1 );
     *  p.write( 2, 1 );
     *  p.write( 666, 2 );
     *  String s = p.readSArray( "%d", "&&:", 1 );
     *  // now s should contain '2&&:666'
     *  s = p.readSArray( "%4d", " ", 0, 1 );
     *  // now s should contain '   1,   2'
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  PropertyI p = getPropFromSomewhere()
     *  p.write(1)
     *  p.write(2, 1)
     *  p.write(666, 2)
     *  s = p.readSArray("%d", "&&:", 1)
     *  # now s should contain '2&&:666'
     *  s = p.readSArray("%4d", " ", 0, 1)
     *  # now s should contain '   1,   2'
     * \endcode
     * \endif
     *
     *  \note If the caller does not have the needed rights this function might throw an
     *  exception of the type \b mvIMPACT::acquire::ImpactAcquireException.
     *
     *  \return A string containing the data questioned.
     */
    std::string readSArray(
        /// [in] The format string telling the function how to format the result. If left empty the property uses its standard way of converting its data into a string
        const std::string& format = "",
        /// [in] This string is used to separate the individual values from one another. If left empty, a single blank will separate
        /// the data.
        const std::string& delimiter = "",
        /// [in] The index of the first of the desired values
        int startIndex = 0,
        /// [in] The index of the last of the desired values. If \b INT_MAX is passed, every
        /// from \a startIndex to the last value stored by the property will be returned.
        int endIndex = INT_MAX,
        /// [in] Specifies the mode this function operates in. Currently only the LSB affects the behaviour of this function.
        /// When the LSB is set, the translation dictionary (if defined) will be ignored for this call.
        int mode = 0 ) const
    {
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        auto_array_ptr<char> pBuf( bufSize );
        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_GetSArrayFormattedEx( m_hObj,
                          pBuf.get(),
                          &bufSize,
                          ( format != "" ) ? format.c_str() : 0,
                          ( delimiter != "" ) ? delimiter.c_str() : 0,
                          startIndex,
                          endIndex,
                          mode ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            pBuf.realloc( bufSize );
        }
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return std::string( pBuf.get() );
    }
    /// \brief Removes a certain value from the property's data.
    /**
     *  \return A const reference to the calling property.
     */
    const Property& removeValue(
        /// [in] The index of the value to be removed
        int index = 0 ) const
    {
        const TPROPHANDLING_ERROR result = OBJ_RemoveVal( m_hObj, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Resizes the property's data array.
    /**
     *  This function resizes the internal data array of this property. The size of
     *  this array represents the number of values, which can be stored within the
     *  property. This function will only succeed, if the \b mvIMPACT::acquire::cfFixedSize
     *  is \b NOT set for this property and the user has \b "write rights" for this property.
     *  Otherwise an exception will be thrown. Whenever the user successfully writes an
     *  array of values to a property and this array contains more elements than the current
     *  internal data array can accommodate at the desired offset the internal data array
     *  will be increased automatically.
     *
     *  \note If the caller does not have the needed rights this function might throw an
     *  exception of the type \b mvIMPACT::acquire::ImpactAcquireException.
     *
     *  \note In order to be allowed to modify the number of values a property
     *  can store, the \b mvIMPACT::acquire::cfFixedSize flag
     *  must \b NOT be set.
     *  \sa
     *  \b mvIMPACT::acquire::Component::isWriteable
     *
     *  \return A const reference to the calling property.
     */
    const Property& resizeValArray(
        /// [in] The new number of values this property shall be allowed to store
        unsigned int newSize ) const
    {
        const TPROPHANDLING_ERROR result = OBJ_SetValCount( m_hObj, newSize );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Returns the internal format string this property uses to convert data to strings.
    /**
     *  \return A string containing the format string internally used by the property
     *  whenever the user reads a value as a string without specifying a format string and
     *  the property is not a string type one.
     */
    std::string stringFormatString( void ) const
    {
        return compGetStringParam( sqPropFormatString );
    }
    /// \brief Returns the current number of values managed by this property.
    /**
     *  For the majority of properties this function will return '1', but as properties
     *  might manage more than a single value, this value might be interesting from time
     *  to time.
     *  \return the current number of values managed by this property.
     */
    unsigned int valCount( void ) const
    {
        unsigned int valCount;
        const TPROPHANDLING_ERROR result = OBJ_GetValCount( m_hObj, &valCount );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return valCount;
    }
    /// \brief Returns maximum number of values that can be managed by this property.
    /**
     *  For the majority of properties this function will return '1', but as properties
     *  might manage more than a single value, this value might be interesting from time
     *  to time.
     *  \return the maximum number of values that can be managed by this property.
     */
    unsigned int maxValCount( void ) const
    {
        unsigned int maxValCount;
        const TPROPHANDLING_ERROR result = OBJ_GetMaxValCount( m_hObj, &maxValCount );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return maxValCount;
    }
    /// \brief Assigns a new value to this property.
    /**
     *  The user caller have \b "write rights" for this property in order to be able to
     *  modify its value. Also if \a index is greater than the current internal data array
     *  size of this property the user must be allowed to change to size of the properties
     *  internal data array (the \b mvIMPACT::acquire::cfFixedSize flag must \b NOT be set).
     *
     *  \note If the caller does not have the needed rights this function might throw an
     *  exception of the type \b mvIMPACT::acquire::ImpactAcquireException.
     *
     *  \sa
     *  \b mvIMPACT::acquire::Component::isWriteable, \n
     *  \b mvIMPACT::acquire::Component::flags, \n
     *  \b mvIMPACT::acquire::Property::writeS
     *
     *  \return A const reference to the calling property.
     */
    const Property& writeS(
        /// [in] The new value for this property at the given \a index.
        const std::string& value,
        /// [in] The index of the value to modify
        int index = 0 ) const
    {
        const TPROPHANDLING_ERROR result = OBJ_SetS( m_hObj, value.c_str(), index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Assigns new values to this property.
    /**
     *  The user must have \b "write rights" for this property in order to be able to
     *  modify its values. Also if \a index is greater than the current internal data array
     *  size of this property the user must be allowed to change to size of the properties
     *  internal data array (the \b mvIMPACT::acquire::cfFixedSize flag must \b NOT be set). This
     *  function behaves exactly like \b mvIMPACT::acquire::Property::writeS
     *  except that is can be used to assign more than one value at the same time. The parameter
     *  \a index here serves as an offset. If for example a property holds 3 values 'one', 'two'
     *  and 'three' before this call and the function is then called with an array containing the
     *  string 'orange' and 'blue' and \a index = 2 then after a successful call to this function
     *  the property will hold the data 'one', 'two', 'orange' and 'blue'.
     *
     *  \note If the caller does not have the needed rights this function might throw an
     *  exception of the type \b mvIMPACT::acquire::ImpactAcquireException.
     *
     *  \sa
     *  \b mvIMPACT::acquire::Component::isWriteable, \n \b mvIMPACT::acquire::Component::flags, \n
     *  \b mvIMPACT::acquire::Property::writeS
     *
     *  \return A const reference to the calling property.
     */
    const Property& writeS(
        /// [in] A constant reference to an array containing the strings to be assigned to the property
        const std::vector<std::string>& sequence,
        /// [in] The offset from where to start to assign the values
        int index = 0 ) const
    {
        unsigned int vSize = static_cast<unsigned int>( sequence.size() );
        for( unsigned int i = 0; i < vSize; i++ )
        {
            writeS( sequence[i], index + i );
        }
        return *this;
    }
};

#ifndef DOXYGEN_SHOULD_SKIP_THIS
#   if !defined(WRAP_ANY) && !defined(BUILD_FOR_JAVA) // don't wrap deprecated stuff
//-----------------------------------------------------------------------------
inline bool Property::isConstDefined( TPropertyLimits constant ) const
//-----------------------------------------------------------------------------
{
    return isConstDefinedInternal( constant );
}
#   endif // #if !defined(WRAP_ANY) && !defined(BUILD_FOR_JAVA)
#endif // #ifdef DOXYGEN_SHOULD_SKIP_THIS

//-----------------------------------------------------------------------------
/// \brief A template class to represent float properties and enumerated float properties.
/**
 *  The template parameter specifies the enum to use as the value type for this
 *  enumerated property. The class itself however is restricted for float values.
 *  To use a normal float (not enumerated) properties use the \b mvIMPACT::acquire::PropertyF type.
 */
template<class ZYX>
class EnumPropertyF : public Property
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new unbound \b mvIMPACT::acquire::EnumPropertyF object.
    explicit EnumPropertyF() {}
    /// \brief Constructs a new \b mvIMPACT::acquire::EnumPropertyF object.
    explicit EnumPropertyF(
        /// [in] A valid handle to a float property
        HOBJ hProp ) : Property( hProp )
    {
        if( type() != ctPropFloat )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, PROPHANDLING_INVALID_PROP_VALUE_TYPE, hProp );
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::EnumPropertyF from an existing one.
    EnumPropertyF(
        /// [in] A constant reference to the \b mvIMPACT::acquire::EnumPropertyF object, this object shall be created from
        const EnumPropertyF& src ) : Property( src ) {}
#if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    typedef ZYX value_type;
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    /// \brief This function queries the property's translation table.
    /**
     *  If this property defines a translation table the strings and their corresponding
     *  translation values will be written into \a sequence. If the property does \b NOT
     *  define a translation table \a sequence will be empty after this function call.
     *
     *  \note
     *  This function is much more efficient than calling
     *  \b EnumPropertyF::getTranslationDictString and
     *  \b EnumPropertyF::getTranslationDictValue multiple times and
     *  therefore this function should be called whenever all entries are required.
     *  \return A const reference to the calling property.
     */
    const EnumPropertyF& getTranslationDict(
        /// [out] A reference to a container which will receive the data from the properties translation dictionary.
        std::vector<std::pair<std::string, ZYX> >& sequence ) const
    {
        const unsigned int size = dictSize();
        double* pVal = new double[size];
        char** ppBuf = new char* [size];
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        for( size_t i = 0; i < size; i++ )
        {
            ppBuf[i] = new char[bufSize];
        }

        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_GetFDictEntries( m_hObj, ppBuf, bufSize, pVal, size ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            for( size_t i = 0; i < size; i++ )
            {
                delete [] ppBuf[i];
                ppBuf[i] = new char[bufSize];
            }
        }

        if( result == PROPHANDLING_NO_ERROR )
        {
            sequence.resize( size );
            for( unsigned int i = 0; i < size; i++ )
            {
                sequence[i] = std::pair<std::string, ZYX>( ppBuf[i], static_cast<ZYX>( pVal[i] ) );
            }
        }

        for( size_t i = 0; i < size; i++ )
        {
            delete [] ppBuf[i];
        }
        delete [] ppBuf;
        delete [] pVal;

        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief This function reads a single translation table string entry from a property.
    /**
     *  If this property defines a translation table and \a index specifies a valid entry
     *  the string representation of this entry will be returned.
     *  If the property does \b NOT define a translation table or \a index specifies
     *  an invalid entry an exception will be thrown.
     */
    std::string getTranslationDictString(
        /// [in] The index of the entry to read from the property.
        int index = 0 ) const
    {
        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        auto_array_ptr<char> pTranslationString( bufSize );
        while( ( result = OBJ_GetFDictEntry( m_hObj, pTranslationString.get(), bufSize, 0, index ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            pTranslationString.realloc( bufSize );
        }
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return std::string( pTranslationString.get() );
    }
    /// \brief This function reads a single translation table value entry from a property.
    /**
     *  If this property defines a translation table and \a index specifies a valid entry
     *  the value of this entry will be returned.
     *  If the property does \b NOT define a translation table or \a index specifies
     *  an invalid entry an exception will be thrown.
     *  \sa \b mvIMPACT::acquire::EnumPropertyF::getTranslationDictValues to query all valid
     *  values efficiently in a single call.
     */
    ZYX getTranslationDictValue(
        /// [in] The index of the entry to read from the property.
        int index = 0 ) const
    {
        double value;
        const TPROPHANDLING_ERROR result = OBJ_GetFDictEntry( m_hObj, 0, 0, &value, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return static_cast<ZYX>( value );
    }
    /// \brief This function queries a list of valid strings for this property.
    /**
     *  If this property defines a translation table all valid strings will be written into \a sequence.
     *  If the property does \b NOT define a translation table \a sequence will be empty after this function call.
     *
     *  \note
     *  This function is much more efficient than calling
     *  \b mvIMPACT::acquire::EnumPropertyF::getTranslationDictString multiple times and
     *  therefore this function should be called whenever all entries are required.
     *  \since 2.5.0
     *  \return A const reference to the calling property.
     */
    const EnumPropertyF& getTranslationDictStrings(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<std::string>& sequence ) const
    {
        const unsigned int size = dictSize();
        char** ppBuf = new char* [size];
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        for( size_t i = 0; i < size; i++ )
        {
            ppBuf[i] = new char[bufSize];
        }

        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_GetFDictEntries( m_hObj, ppBuf, bufSize, 0, size ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            for( size_t i = 0; i < size; i++ )
            {
                delete [] ppBuf[i];
                ppBuf[i] = new char[bufSize];
            }
        }

        if( result == PROPHANDLING_NO_ERROR )
        {
            sequence.resize( size );
            for( unsigned int i = 0; i < size; i++ )
            {
                sequence[i] = std::string( ppBuf[i] );
            }
        }

        for( size_t i = 0; i < size; i++ )
        {
            delete [] ppBuf[i];
        }
        delete [] ppBuf;

        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }

    /// \brief This function queries a list of valid values for this property.
    /**
     *  If this property defines a translation table all valid values will be written into \a sequence.
     *  If the property does \b NOT
     *  define a translation table \a sequence will be empty after this function call.
     *
     *  \note
     *  This function is much more efficient than calling
     *  \b mvIMPACT::acquire::EnumPropertyF::getTranslationDictValue multiple times and
     *  therefore this function should be called whenever all entries are required.
     *  \since 1.12.68
     *
     *  \return A const reference to the calling property.
     */
    const EnumPropertyF& getTranslationDictValues(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<ZYX>& sequence ) const
    {
        const unsigned int size = dictSize();
        if( size == 0 )
        {
            sequence.clear();
            return *this;
        }

        double* pVal = new double[size];
        const TPROPHANDLING_ERROR result = OBJ_GetFDictEntries( m_hObj, 0, 0, pVal, size );
        if( result == PROPHANDLING_NO_ERROR )
        {
            sequence.resize( size );
            for( unsigned int i = 0; i < size; i++ )
            {
                sequence[i] = static_cast<ZYX>( pVal[i] );
            }
        }
        delete [] pVal;

        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Reads a value from a property.
    /**
     *  This function queries a single value stored under index \a index in the property.
     *  \return The value stored at \a index within the property.
     */
    ZYX read(
        /// [in] The index of the value to read from the property.
        int index = 0 ) const
    {
        double val;
        const TPROPHANDLING_ERROR result = OBJ_GetF( m_hObj, &val, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return static_cast<ZYX>( val );
    }
    /// \brief Reads the maximum value from a property.
    /**
     *  \note
     *  To find out if the property defines a maximum value \b mvIMPACT::acquire::Property::hasMaxValue
     *  should be called first.
     *
     *  \note
     *  If the property does not define a maximum value calling this function will raise
     *  an exception.
     *
     *  \since 1.12.63
     *
     */
    ZYX getMaxValue( void ) const
    {
        return read( plMaxValue );
    }
    /// \brief Reads the minimum value from a property.
    /**
     *  \note
     *  To find out if the property defines a minimum value \b mvIMPACT::acquire::Property::hasMinValue
     *  should be called first.
     *
     *  \note
     *  If the property does not define a minimum value calling this function will raise
     *  an exception.
     *
     *  \since 1.12.63
     *
     */
    ZYX getMinValue( void ) const
    {
        return read( plMinValue );
    }
    /// \brief Reads the step width from a property.
    /**
     *  \note
     *  To find out if the property defines a step width \b mvIMPACT::acquire::Property::hasStepWidth
     *  should be called first.
     *
     *  \note
     *  If the property does not define a step width calling this function will raise
     *  an exception.
     *
     *  \since 1.12.63
     *
     */
    ZYX getStepWidth( void ) const
    {
        return read( plStepWidth );
    }
    /// \brief Reads a set of values from a property.
    /**
     *  This function queries a set of values from a property and stores these values
     *  into \a sequence.
     */
    void read(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<ZYX>& sequence,
        /// [in] The index from where to start reading values from the property.
        int start = 0,
        /// [in] The index where to stop reading values from the property.
        int end = END_OF_LIST ) const
    {
        const unsigned int valCnt = valuesToRead( start, end );
        sequence.resize( valCnt );
        for( unsigned int i = 0; i < valCnt; i++ )
        {
            sequence[i] = read( i + start );
        }
    }
    /// \brief Reads a set of values from a property.
    /**
     *  This function queries a set of values from a property and stores these values
     *  into \a sequence.
     */
    void read(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<ZYX>& sequence,
        /// [in] Set this parameter to \a true to get all values at once(recommended). If set to false the function will
        /// need more time and all values in \a sequence will be read one after the other
        bool boAtomic,
        /// [in] The index from where to start reading values from the property.
        int start = 0,
        /// [in] The index where to stop reading values from the property.
        int end = END_OF_LIST ) const
    {
        if( boAtomic )
        {
            unsigned int valCnt = valuesToRead( start, end );
            sequence.resize( valCnt );
            double* pValues = new double[valCnt];
            const TPROPHANDLING_ERROR result = OBJ_GetFArray( m_hObj, pValues, valCnt, start );
            for( unsigned int i = 0; i < valCnt; i++ )
            {
                sequence[i] = static_cast<ZYX>( pValues[i] );
            }
            delete [] pValues;
            if( result != PROPHANDLING_NO_ERROR )
            {
                ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
            }
        }
        else
        {
            read( sequence, start, end );
        }
    }
    /// \brief Writes one value to the property.
    /**
     *  This function writes a single value under index \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const EnumPropertyF& write(
        /// [in] The value to write to the property.
        ZYX value,
        /// [in] The index defining at which position to write the value.
        int index = 0 ) const
    {
        const TPROPHANDLING_ERROR result = OBJ_SetF( m_hObj, static_cast<double>( value ), index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Writes a set of values to the property.
    /**
     *  This function writes a set of values starting at \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const EnumPropertyF& write(
        /// [in] An array containing the values to write to the property.
        const std::vector<ZYX>& sequence,
        /// [in] The index where to write the first value to the property.
        int index = 0 ) const
    {
        const unsigned int vSize = static_cast<unsigned int>( sequence.size() );
        for( unsigned int i = 0; i < vSize; i++ )
        {
            write( sequence[i], index + i );
        }
        return *this;
    }
    /// \brief Writes a set of values to the property.
    /**
     *  This function writes a set of values starting at \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const EnumPropertyF& write(
        /// [in] An array containing the values to write to the property.
        const std::vector<ZYX>& sequence,
        /// [in] Set this parameter to \a true to set all values at once(recommended). If set to false the function will
        /// need more time and all values in \a sequence will be set one after the other
        bool boAtomic,
        /// [in] The index where to write the first value to the property.
        int index = 0 ) const
    {
        if( boAtomic )
        {
            const unsigned int valCnt = static_cast<unsigned int>( sequence.size() );
            double* pValues = new double[valCnt];
            for( unsigned int i = 0; i < valCnt; i++ )
            {
                pValues[i] = sequence[i];
            }
            const TPROPHANDLING_ERROR result = OBJ_SetFArray( m_hObj, pValues, valCnt, index );
            delete [] pValues;
            if( result != PROPHANDLING_NO_ERROR )
            {
                ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
            }
            return *this;
        }
        else
        {
            return write( sequence, index );
        }
    }
};

/// \brief A type for floating point properties.
/**
 *  Provided for convenience only. This type represents a standard float property type.
 */
typedef EnumPropertyF<double> PropertyF;

//-----------------------------------------------------------------------------
/// \brief A template class to represent 32 bit integer properties and 32 bit enumerated integer properties.
/**
 *  The template parameter specifies the enum to use as the value type for this
 *  enumerated property. The class itself however is restricted for integer values.
 *  To use a normal int (not enumerated) properties use the \b mvIMPACT::acquire::PropertyI type.
 */
template<class ZYX>
class EnumPropertyI : public Property
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new unbound \b mvIMPACT::acquire::EnumPropertyI object.
    explicit EnumPropertyI() {}
    /// \brief Constructs a new \b mvIMPACT::acquire::EnumPropertyI object.
    explicit EnumPropertyI(
        /// [in] A valid handle to an integer property
        HOBJ hProp ) : Property( hProp )
    {
        const TComponentType compType = type();
        if( ( compType != ctPropInt ) && ( compType != ctPropInt64 ) )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, PROPHANDLING_INVALID_PROP_VALUE_TYPE, hProp );
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::EnumPropertyI from an existing one.
    EnumPropertyI(
        /// [in] A constant reference to the \b mvIMPACT::acquire::EnumPropertyI object, this object shall be created from
        const EnumPropertyI& src ) : Property( src ) {}
#if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    typedef ZYX value_type;
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    /// \brief This function queries the property's translation table.
    /**
     *  If this property defines a translation table the strings and their corresponding
     *  translation values will be written into \a sequence. If the property does \b NOT
     *  define a translation table \a sequence will be empty after this function call.
     *
     *  \note
     *  This function is much more efficient than calling
     *  \b mvIMPACT::acquire::EnumPropertyI::getTranslationDictString and
     *  \b mvIMPACT::acquire::EnumPropertyI::getTranslationDictValue multiple times and
     *  therefore this function should be called whenever all entries are required.
     *
     *  \return A const reference to the calling property.
     */
    const EnumPropertyI& getTranslationDict(
        /// [out] A reference to a container which will receive the data from the properties translation dictionary.
        std::vector<std::pair<std::string, ZYX> >& sequence ) const
    {
        const unsigned int size = dictSize();
        int* pVal = new int[size];
        char** ppBuf = new char* [size];
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        for( size_t i = 0; i < size; i++ )
        {
            ppBuf[i] = new char[bufSize];
        }

        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_GetIDictEntries( m_hObj, ppBuf, bufSize, pVal, size ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            for( size_t i = 0; i < size; i++ )
            {
                delete [] ppBuf[i];
                ppBuf[i] = new char[bufSize];
            }
        }

        if( result == PROPHANDLING_NO_ERROR )
        {
            sequence.resize( size );
            for( unsigned int i = 0; i < size; i++ )
            {
                sequence[i] = std::pair<std::string, ZYX>( ppBuf[i], static_cast<ZYX>( pVal[i] ) );
            }
        }

        for( size_t i = 0; i < size; i++ )
        {
            delete [] ppBuf[i];
        }
        delete [] ppBuf;
        delete [] pVal;

        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief This function reads a single translation table string entry from a property.
    /**
     *  If this property defines a translation table and \a index specifies a valid entry
     *  the string representation of this entry will be returned.
     *  If the property does \b NOT define a translation table or \a index specifies
     *  an invalid entry an exception will be thrown.
     */
    std::string getTranslationDictString(
        /// [in] The index of the entry to read from the property.
        int index = 0 ) const
    {
        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        auto_array_ptr<char> pTranslationString( bufSize );
        while( ( result = OBJ_GetIDictEntry( m_hObj, pTranslationString.get(), bufSize, 0, index ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            pTranslationString.realloc( bufSize );
        }
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return std::string( pTranslationString.get() );
    }
    /// \brief This function reads a single translation table value entry from a property.
    /**
     *  If this property defines a translation table and \a index specifies a valid entry
     *  the value of this entry will be returned.
     *  If the property does \b NOT define a translation table or \a index specifies
     *  an invalid entry an exception will be thrown.
     *  \sa \b mvIMPACT::acquire::EnumPropertyI::getTranslationDictValues to query all valid
     *  values efficiently in a single call.
     */
    ZYX getTranslationDictValue(
        /// [in] The index of the entry to read from the property.
        int index = 0 ) const
    {
        int value;
        const TPROPHANDLING_ERROR result = OBJ_GetIDictEntry( m_hObj, 0, 0, &value, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return static_cast<ZYX>( value );
    }
    /// \brief This function queries a list of valid strings for this property.
    /**
     *  If this property defines a translation table all valid strings will be written into \a sequence.
     *  If the property does \b NOT define a translation table \a sequence will be empty after this function call.
     *
     *  \note
     *  This function is much more efficient than calling
     *  \b mvIMPACT::acquire::EnumPropertyI::getTranslationDictString multiple times and
     *  therefore this function should be called whenever all entries are required.
     *  \since 2.5.0
     *  \return A const reference to the calling property.
     */
    const EnumPropertyI& getTranslationDictStrings(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<std::string>& sequence ) const
    {
        const unsigned int size = dictSize();
        char** ppBuf = new char* [size];
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        for( size_t i = 0; i < size; i++ )
        {
            ppBuf[i] = new char[bufSize];
        }

        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_GetIDictEntries( m_hObj, ppBuf, bufSize, 0, size ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            for( size_t i = 0; i < size; i++ )
            {
                delete [] ppBuf[i];
                ppBuf[i] = new char[bufSize];
            }
        }

        if( result == PROPHANDLING_NO_ERROR )
        {
            sequence.resize( size );
            for( unsigned int i = 0; i < size; i++ )
            {
                sequence[i] = std::string( ppBuf[i] );
            }
        }

        for( size_t i = 0; i < size; i++ )
        {
            delete [] ppBuf[i];
        }
        delete [] ppBuf;

        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }

    /// \brief This function queries a list of valid values for this property.
    /**
     *  If this property defines a translation table all valid values will be written into \a sequence.
     *  If the property does \b NOT
     *  define a translation table \a sequence will be empty after this function call.
     *
     *  \note
     *  This function is much more efficient than calling
     *  \b mvIMPACT::acquire::EnumPropertyI::getTranslationDictValue multiple times and
     *  therefore this function should be called whenever all entries are required.
     *  \since 1.12.68
     *
     *  \return A const reference to the calling property.
     */
    const EnumPropertyI& getTranslationDictValues(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<ZYX>& sequence ) const
    {
        const unsigned int size = dictSize();
        if( size == 0 )
        {
            sequence.clear();
            return *this;
        }

        int* pVal = new int[size];
        const TPROPHANDLING_ERROR result = OBJ_GetIDictEntries( m_hObj, 0, 0, pVal, size );
        if( result == PROPHANDLING_NO_ERROR )
        {
            sequence.resize( size );
            for( unsigned int i = 0; i < size; i++ )
            {
                sequence[i] = static_cast<ZYX>( pVal[i] );
            }
        }
        delete [] pVal;

        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Reads a value from a property.
    /**
     *  This function queries a single value stored under index \a index in the property.
     *  \return The value stored at \a index within the property.
     */
    ZYX read(
        /// [in] The index of the value to read from the property.
        int index = 0 ) const
    {
        int val;
        const TPROPHANDLING_ERROR result = OBJ_GetI( m_hObj, &val, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return static_cast<ZYX>( val );
    }
    /// \brief Reads the maximum value from a property.
    /**
     *  \note
     *  To find out if the property defines a maximum value \b mvIMPACT::acquire::Property::hasMaxValue
     *  should be called first.
     *
     *  \note
     *  If the property does not define a maximum value calling this function will raise
     *  an exception.
     *
     *  \since 1.12.63
     *
     */
    ZYX getMaxValue( void ) const
    {
        return read( plMaxValue );
    }
    /// \brief Reads the minimum value from a property.
    /**
     *  \note
     *  To find out if the property defines a minimum value \b mvIMPACT::acquire::Property::hasMinValue
     *  should be called first.
     *
     *  \note
     *  If the property does not define a minimum value calling this function will raise
     *  an exception.
     *
     *  \since 1.12.63
     *
     */
    ZYX getMinValue( void ) const
    {
        return read( plMinValue );
    }
    /// \brief Reads the step width from a property.
    /**
     *  \note
     *  To find out if the property defines a step width \b mvIMPACT::acquire::Property::hasStepWidth
     *  should be called first.
     *
     *  \note
     *  If the property does not define a step width calling this function will raise
     *  an exception.
     *
     *  \since 1.12.63
     *
     */
    ZYX getStepWidth( void ) const
    {
        return read( plStepWidth );
    }
    /// \brief Reads a set of values from a property.
    /**
     *  This function queries a set of values from a property and stores these values
     *  into \a sequence.
     */
    void read(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<ZYX>& sequence,
        /// [in] The index from where to start reading values from the property.
        int start = 0,
        /// [in] The index where to stop reading values from the property.
        int end = END_OF_LIST ) const
    {
        unsigned int valCnt = valuesToRead( start, end );
        sequence.resize( valCnt );
        for( unsigned int i = 0; i < valCnt; i++ )
        {
            sequence[i] = read( i + start );
        }
    }
    /// \brief Reads a set of values from a property.
    /**
     *  This function queries a set of values from a property and stores these values
     *  into \a sequence.
     */
    void read(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<ZYX>& sequence,
        /// [in] Set this parameter to \a true to get all values at once(recommended). If set to false the function will
        /// need more time and all values in \a sequence will be read one after the other
        bool boAtomic,
        /// [in] The index from where to start reading values from the property.
        int start = 0,
        /// [in] The index where to stop reading values from the property.
        int end = END_OF_LIST ) const
    {
        if( boAtomic )
        {
            unsigned int valCnt = valuesToRead( start, end );
            sequence.resize( valCnt );
            int* pValues = new int[valCnt];
            const TPROPHANDLING_ERROR result = OBJ_GetIArray( m_hObj, pValues, valCnt, start );
            for( unsigned int i = 0; i < valCnt; i++ )
            {
                sequence[i] = static_cast<ZYX>( pValues[i] );
            }
            delete [] pValues;
            if( result != PROPHANDLING_NO_ERROR )
            {
                ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
            }
        }
        else
        {
            read( sequence, start, end );
        }
    }
    /// \brief Writes one value to the property.
    /**
     *  This function writes a single value under index \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const EnumPropertyI& write(
        /// [in] The value to write to the property.
        ZYX value,
        /// [in] The index defining at which position to write the value.
        int index = 0 ) const
    {
        const TPROPHANDLING_ERROR result = OBJ_SetI( m_hObj, static_cast<int>( value ), index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Writes a set of values to the property.
    /**
     *  This function writes a set of values starting at \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const EnumPropertyI& write(
        /// [in] An array containing the values to write to the property.
        const std::vector<ZYX>& sequence,
        /// [in] The index where to write the first value to the property.
        int index = 0 ) const
    {
        int vSize = static_cast<int>( sequence.size() );
        for( int i = 0; i < vSize; i++ )
        {
            write( sequence[i], index + i );
        }
        return *this;
    }
    /// \brief Writes a set of values to the property.
    /**
     *  This function writes a set of values starting at \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const EnumPropertyI& write(
        /// [in] An array containing the values to write to the property.
        const std::vector<ZYX>& sequence,
        /// [in] Set this parameter to \a true to set all values at once(recommended). If set to false the function will
        /// need more time and all values in \a sequence will be set one after the other
        bool boAtomic,
        /// [in] The index where to write the first value to the property.
        int index = 0 ) const
    {
        if( boAtomic )
        {
            const unsigned int valCnt = static_cast<unsigned int>( sequence.size() );
            int* pValues = new int[valCnt];
            for( unsigned int i = 0; i < valCnt; i++ )
            {
                pValues[i] = sequence[i];
            }
            const TPROPHANDLING_ERROR result = OBJ_SetIArray( m_hObj, pValues, valCnt, index );
            delete [] pValues;
            if( result != PROPHANDLING_NO_ERROR )
            {
                ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
            }
            return *this;
        }
        else
        {
            return write( sequence, index );
        }
    }
};

#if defined(WRAP_JAVA) || defined(BUILD_FOR_JAVA)
typedef EnumPropertyI<int> PropertyIAcquisitionMode;
typedef EnumPropertyI<int> PropertyIAcquisitionStartStopBehaviour;
typedef EnumPropertyI<int> PropertyIAoiMode;
typedef EnumPropertyI<int> PropertyIBayerConversionMode;
typedef EnumPropertyI<int> PropertyIBayerMosaicParity;
typedef EnumPropertyI<int> PropertyIBayerWhiteBalanceResult;
typedef EnumPropertyI<int> PropertyIBoolean;
typedef EnumPropertyI<int> PropertyICameraOutput;
typedef EnumPropertyI<int> PropertyIChannelSplitMode;
typedef EnumPropertyI<int> PropertyIColorTwistInputCorrectionMatrixMode;
typedef EnumPropertyI<int> PropertyIColorTwistOutputCorrectionMatrixMode;
typedef EnumPropertyI<int> PropertyIColorProcessingMode;
typedef EnumPropertyI<int> PropertyIDarkCurrentFilterMode;
typedef EnumPropertyI<int> PropertyIDefectivePixelsFilterMode;
typedef EnumPropertyI<int> PropertyIDeviceAccessMode;
typedef EnumPropertyI<int> PropertyIDeviceAutoNegotiatePacketSizeMode;
typedef EnumPropertyI<int> PropertyIDeviceCapability;
typedef EnumPropertyI<int> PropertyIDeviceClass;
typedef EnumPropertyI<int> PropertyIDeviceInterfaceLayout;
typedef EnumPropertyI<int> PropertyIDeviceLoadSettings;
typedef EnumPropertyI<int> PropertyIDeviceState;
typedef EnumPropertyI<int> PropertyIDFirmwareUpdateResult;
typedef EnumPropertyI<int> PropertyIFlatFieldFilterCorrectionMode;
typedef EnumPropertyI<int> PropertyIFlatFieldFilterMode;
typedef EnumPropertyI<int> PropertyIHWUpdateResult;
typedef EnumPropertyI<int> PropertyIImageBufferPixelFormat;
typedef EnumPropertyI<int> PropertyIImageBufferFormatReinterpreterMode;
typedef EnumPropertyI<int> PropertyIImageDestinationPixelFormat;
typedef EnumPropertyI<int> PropertyIImageProcessingFilter;
typedef EnumPropertyI<int> PropertyIImageProcessingMode;
typedef EnumPropertyI<int> PropertyIImageProcessingOptimization;
typedef EnumPropertyI<int> PropertyIImageProcessingResult;
typedef EnumPropertyI<int> PropertyIRequestImageMemoryMode;
typedef EnumPropertyI<int> PropertyIImageRequestControlMode;
typedef EnumPropertyI<int> PropertyIInterfaceEnumerationBehaviour;
typedef EnumPropertyI<int> PropertyILUTGammaMode;
typedef EnumPropertyI<int> PropertyILUTImplementation;
typedef EnumPropertyI<int> PropertyILUTInterpolationMode;
typedef EnumPropertyI<int> PropertyILUTMapping;
typedef EnumPropertyI<int> PropertyILUTMode;
typedef EnumPropertyI<int> PropertyIMirrorMode;
typedef EnumPropertyI<int> PropertyIMirrorOperationMode;
typedef EnumPropertyI<int> PropertyIPolarizedDataExtractionMode;
typedef EnumPropertyI<int> PropertyIPolarizedDataExtractionInterpolationMode;
typedef EnumPropertyI<int> PropertyIRequestResult;
typedef EnumPropertyI<int> PropertyIRequestState;
typedef EnumPropertyI<int> PropertyIScalerMode;
typedef EnumPropertyI<int> PropertyIScalerInterpolationMode;
typedef EnumPropertyI<int> PropertyIUserDataAccessRight;
typedef EnumPropertyI<int> PropertyIUserDataReconnectBehaviour;
typedef EnumPropertyI<int> PropertyIWhiteBalanceCalibrationMode;
typedef EnumPropertyI<int> PropertyIWhiteBalanceParameter;
#else
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TAcquisitionMode.
typedef EnumPropertyI<TAcquisitionMode> PropertyIAcquisitionMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TAcquisitionStartStopBehaviour.
typedef EnumPropertyI<TAcquisitionStartStopBehaviour> PropertyIAcquisitionStartStopBehaviour;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TAoiMode.
typedef EnumPropertyI<TAoiMode> PropertyIAoiMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBayerConversionMode.
typedef EnumPropertyI<TBayerConversionMode> PropertyIBayerConversionMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBayerMosaicParity.
typedef EnumPropertyI<TBayerMosaicParity> PropertyIBayerMosaicParity;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBayerWhiteBalanceResult.
typedef EnumPropertyI<TBayerWhiteBalanceResult> PropertyIBayerWhiteBalanceResult;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBoolean.
typedef EnumPropertyI<TBoolean> PropertyIBoolean;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraOutput.
typedef EnumPropertyI<TCameraOutput> PropertyICameraOutput;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TChannelSplitMode.
typedef EnumPropertyI<TChannelSplitMode> PropertyIChannelSplitMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TColorTwistInputCorrectionMatrixMode.
typedef EnumPropertyI<TColorTwistInputCorrectionMatrixMode> PropertyIColorTwistInputCorrectionMatrixMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TColorTwistOutputCorrectionMatrixMode.
typedef EnumPropertyI<TColorTwistOutputCorrectionMatrixMode> PropertyIColorTwistOutputCorrectionMatrixMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TColorProcessingMode.
typedef EnumPropertyI<TColorProcessingMode> PropertyIColorProcessingMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDarkCurrentFilterMode.
typedef EnumPropertyI<TDarkCurrentFilterMode> PropertyIDarkCurrentFilterMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDefectivePixelsFilterMode.
typedef EnumPropertyI<TDefectivePixelsFilterMode> PropertyIDefectivePixelsFilterMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceAccessMode.
typedef EnumPropertyI<TDeviceAccessMode> PropertyIDeviceAccessMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceAutoNegotiatePacketSizeMode.
typedef EnumPropertyI<TDeviceAutoNegotiatePacketSizeMode> PropertyIDeviceAutoNegotiatePacketSizeMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceCapability.
typedef EnumPropertyI<TDeviceCapability> PropertyIDeviceCapability;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceClass.
typedef EnumPropertyI<TDeviceClass> PropertyIDeviceClass;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceInterfaceLayout.
typedef EnumPropertyI<TDeviceInterfaceLayout> PropertyIDeviceInterfaceLayout;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceLoadSettings.
typedef EnumPropertyI<TDeviceLoadSettings> PropertyIDeviceLoadSettings;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceState.
typedef EnumPropertyI<TDeviceState> PropertyIDeviceState;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TFlatFieldFilterCorrectionMode.
typedef EnumPropertyI<TFlatFieldFilterCorrectionMode> PropertyIFlatFieldFilterCorrectionMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TFlatFieldFilterMode.
typedef EnumPropertyI<TFlatFieldFilterMode> PropertyIFlatFieldFilterMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::THWUpdateResult.
typedef EnumPropertyI<THWUpdateResult> PropertyIHWUpdateResult;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TImageBufferPixelFormat.
typedef EnumPropertyI<TImageBufferPixelFormat> PropertyIImageBufferPixelFormat;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TImageBufferFormatReinterpreterMode.
typedef EnumPropertyI<TImageBufferFormatReinterpreterMode> PropertyIImageBufferFormatReinterpreterMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TImageDestinationPixelFormat.
typedef EnumPropertyI<TImageDestinationPixelFormat> PropertyIImageDestinationPixelFormat;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TImageProcessingFilter.
typedef EnumPropertyI<TImageProcessingFilter> PropertyIImageProcessingFilter;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TImageProcessingMode.
typedef EnumPropertyI<TImageProcessingMode> PropertyIImageProcessingMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TImageProcessingOptimization.
typedef EnumPropertyI<TImageProcessingOptimization> PropertyIImageProcessingOptimization;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TImageProcessingResult.
typedef EnumPropertyI<TImageProcessingResult> PropertyIImageProcessingResult;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TRequestImageMemoryMode.
typedef EnumPropertyI<TRequestImageMemoryMode> PropertyIRequestImageMemoryMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TImageRequestControlMode.
typedef EnumPropertyI<TImageRequestControlMode> PropertyIImageRequestControlMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TInterfaceEnumerationBehaviour.
typedef EnumPropertyI<TInterfaceEnumerationBehaviour> PropertyIInterfaceEnumerationBehaviour;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TLUTGammaMode.
typedef EnumPropertyI<TLUTGammaMode> PropertyILUTGammaMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TLUTImplementation.
typedef EnumPropertyI<TLUTImplementation> PropertyILUTImplementation;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TLUTInterpolationMode.
typedef EnumPropertyI<TLUTInterpolationMode> PropertyILUTInterpolationMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TLUTMapping.
typedef EnumPropertyI<TLUTMapping> PropertyILUTMapping;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TLUTMode.
typedef EnumPropertyI<TLUTMode> PropertyILUTMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TMirrorMode.
typedef EnumPropertyI<TMirrorMode> PropertyIMirrorMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TMirrorOperationMode.
typedef EnumPropertyI<TMirrorOperationMode> PropertyIMirrorOperationMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TPolarizedDataExtractionMode.
typedef EnumPropertyI<TPolarizedDataExtractionMode> PropertyIPolarizedDataExtractionMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TPolarizedDataExtractionInterpolationMode.
typedef EnumPropertyI<TPolarizedDataExtractionInterpolationMode> PropertyIPolarizedDataExtractionInterpolationMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TRequestResult.
typedef EnumPropertyI<TRequestResult> PropertyIRequestResult;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TRequestState.
typedef EnumPropertyI<TRequestState> PropertyIRequestState;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TScalerMode.
typedef EnumPropertyI<TScalerMode> PropertyIScalerMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TScalerInterpolationMode.
typedef EnumPropertyI<TScalerInterpolationMode> PropertyIScalerInterpolationMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TUserDataAccessRight.
typedef EnumPropertyI<TUserDataAccessRight> PropertyIUserDataAccessRight;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TUserDataReconnectBehaviour.
typedef EnumPropertyI<TUserDataReconnectBehaviour> PropertyIUserDataReconnectBehaviour;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TWhiteBalanceCalibrationMode.
typedef EnumPropertyI<TWhiteBalanceCalibrationMode> PropertyIWhiteBalanceCalibrationMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TWhiteBalanceParameter.
typedef EnumPropertyI<TWhiteBalanceParameter> PropertyIWhiteBalanceParameter;
#endif // #if defined(WRAP_JAVA) || defined(BUILD_FOR_JAVA)

/// \brief A type for integer properties.
/**
 *  Provided for convenience only. This type represents a standard integer property type.
 */
typedef EnumPropertyI<int> PropertyI;

//-----------------------------------------------------------------------------
/// \brief A template class to represent 64 bit integer properties and enumerated 64 bit integer properties.
/**
 *  The template parameter specifies the enum to use as the value type for this
 *  enumerated property. The class itself however is restricted for integer values.
 *  To use a normal int (not enumerated) properties use the \b mvIMPACT::acquire::PropertyI64 type.
 */
template<class ZYX>
class EnumPropertyI64 : public Property
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new unbound \b mvIMPACT::acquire::EnumPropertyI64 object.
    explicit EnumPropertyI64() {}
    /// \brief Constructs a new \b mvIMPACT::acquire::EnumPropertyI64 object.
    explicit EnumPropertyI64(
        /// [in] A valid handle to a 64-bit integer property
        HOBJ hProp ) : Property( hProp )
    {
        const TComponentType compType = type();
        if( ( compType != ctPropInt ) && ( compType != ctPropInt64 ) )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, PROPHANDLING_INVALID_PROP_VALUE_TYPE, hProp );
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::EnumPropertyI64 from an existing one.
    EnumPropertyI64(
        /// [in] A constant reference to the \b mvIMPACT::acquire::EnumPropertyI64 object, this object shall be created from
        const EnumPropertyI64& src ) : Property( src ) {}
#if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    typedef ZYX value_type;
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    /// \brief This function queries the property's translation table.
    /**
     *  If this property defines a translation table the strings and their corresponding
     *  translation values will be written into \a sequence. If the property does \b NOT
     *  define a translation table \a sequence will be empty after this function call.
     *
     *  \note
     *  This function is much more efficient than calling
     *  \b mvIMPACT::acquire::EnumPropertyI64::getTranslationDictString and
     *  \b mvIMPACT::acquire::EnumPropertyI64::getTranslationDictValue multiple times and
     *  therefore this function should be called whenever all entries are required.
     *  \return A const reference to the calling property.
     */
    const EnumPropertyI64& getTranslationDict(
        /// [out] A reference to a container which will receive the data from the properties translation dictionary.
        std::vector<std::pair<std::string, ZYX> >& sequence ) const
    {
        const unsigned int size = dictSize();
        int64_type* pVal = new int64_type[size];
        char** ppBuf = new char* [size];
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        for( size_t i = 0; i < size; i++ )
        {
            ppBuf[i] = new char[bufSize];
        }

        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_GetI64DictEntries( m_hObj, ppBuf, bufSize, pVal, size ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            for( size_t i = 0; i < size; i++ )
            {
                delete [] ppBuf[i];
                ppBuf[i] = new char[bufSize];
            }
        }

        if( result == PROPHANDLING_NO_ERROR )
        {
            sequence.resize( size );
            for( unsigned int i = 0; i < size; i++ )
            {
                sequence[i] = std::pair<std::string, ZYX>( ppBuf[i], static_cast<ZYX>( pVal[i] ) );
            }
        }

        for( size_t i = 0; i < size; i++ )
        {
            delete [] ppBuf[i];
        }
        delete [] ppBuf;
        delete [] pVal;

        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief This function reads a single translation table string entry from a property.
    /**
     *  If this property defines a translation table and \a index specifies a valid entry
     *  the string representation of this entry will be returned.
     *  If the property does \b NOT define a translation table or \a index specifies
     *  an invalid entry an exception will be thrown.
     */
    std::string getTranslationDictString(
        /// [in] The index of the entry to read from the property.
        int index = 0 ) const
    {
        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        auto_array_ptr<char> pTranslationString( bufSize );
        while( ( result = OBJ_GetI64DictEntry( m_hObj, pTranslationString.get(), bufSize, 0, index ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            pTranslationString.realloc( bufSize );
        }
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return std::string( pTranslationString.get() );
    }
    /// \brief This function reads a single translation table value entry from a property.
    /**
     *  If this property defines a translation table and \a index specifies a valid entry
     *  the value of this entry will be returned.
     *  If the property does \b NOT define a translation table or \a index specifies
     *  an invalid entry an exception will be thrown.
     *  \sa \b mvIMPACT::acquire::EnumPropertyI64::getTranslationDictValues to query all valid
     *  values efficiently in a single call.
     */
    ZYX getTranslationDictValue(
        /// [in] The index of the entry to read from the property.
        int index = 0 ) const
    {
        int64_type value;
        const TPROPHANDLING_ERROR result = OBJ_GetI64DictEntry( m_hObj, 0, 0, &value, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return static_cast<ZYX>( value );
    }
    /// \brief This function queries a list of valid strings for this property.
    /**
     *  If this property defines a translation table all valid strings will be written into \a sequence.
     *  If the property does \b NOT define a translation table \a sequence will be empty after this function call.
     *
     *  \note
     *  This function is much more efficient than calling
     *  \b mvIMPACT::acquire::EnumPropertyI64::getTranslationDictString multiple times and
     *  therefore this function should be called whenever all entries are required.
     *  \since 2.5.0
     *  \return A const reference to the calling property.
     */
    const EnumPropertyI64& getTranslationDictStrings(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<std::string>& sequence ) const
    {
        const unsigned int size = dictSize();
        char** ppBuf = new char* [size];
        size_t bufSize = DEFAULT_STRING_SIZE_LIMIT;
        for( size_t i = 0; i < size; i++ )
        {
            ppBuf[i] = new char[bufSize];
        }

        TPROPHANDLING_ERROR result = PROPHANDLING_NO_ERROR;
        while( ( result = OBJ_GetI64DictEntries( m_hObj, ppBuf, bufSize, 0, size ) ) == PROPHANDLING_INPUT_BUFFER_TOO_SMALL )
        {
            bufSize *= BUFFER_INCREMENT_FACTOR;
            for( size_t i = 0; i < size; i++ )
            {
                delete [] ppBuf[i];
                ppBuf[i] = new char[bufSize];
            }
        }

        if( result == PROPHANDLING_NO_ERROR )
        {
            sequence.resize( size );
            for( unsigned int i = 0; i < size; i++ )
            {
                sequence[i] = std::string( ppBuf[i] );
            }
        }

        for( size_t i = 0; i < size; i++ )
        {
            delete [] ppBuf[i];
        }
        delete [] ppBuf;

        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }

    /// \brief This function queries a list of valid values for this property.
    /**
     *  If this property defines a translation table all valid values will be written into \a sequence.
     *  If the property does \b NOT
     *  define a translation table \a sequence will be empty after this function call.
     *
     *  \note
     *  This function is much more efficient than calling
     *  \b mvIMPACT::acquire::EnumPropertyI64::getTranslationDictValue multiple times and
     *  therefore this function should be called whenever all entries are required.
     *  \since 1.12.68
     *
     *  \return A const reference to the calling property.
     */
    const EnumPropertyI64& getTranslationDictValues(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<ZYX>& sequence ) const
    {
        const unsigned int size = dictSize();
        if( size == 0 )
        {
            sequence.clear();
            return *this;
        }

        int64_type* pVal = new int64_type[size];
        const TPROPHANDLING_ERROR result = OBJ_GetI64DictEntries( m_hObj, 0, 0, pVal, size );
        if( result == PROPHANDLING_NO_ERROR )
        {
            sequence.resize( size );
            for( unsigned int i = 0; i < size; i++ )
            {
                sequence[i] = static_cast<ZYX>( pVal[i] );
            }
        }
        delete [] pVal;

        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Reads a value from a property.
    /**
     *  This function queries a single value stored under index \a index in the property.
     *  \return The value stored at \a index within the property.
     */
    ZYX read(
        /// [in] The index of the value to read from the property.
        int index = 0 ) const
    {
        int64_type val;
        const TPROPHANDLING_ERROR result = OBJ_GetI64( m_hObj, &val, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return static_cast<ZYX>( val );
    }
    /// \brief Reads the maximum value from a property.
    /**
     *  \note
     *  To find out if the property defines a maximum value \b mvIMPACT::acquire::Property::hasMaxValue
     *  should be called first.
     *
     *  \note
     *  If the property does not define a maximum value calling this function will raise
     *  an exception.
     *
     *  \since 1.12.63
     *
     */
    ZYX getMaxValue( void ) const
    {
        return read( plMaxValue );
    }
    /// \brief Reads the minimum value from a property.
    /**
     *  \note
     *  To find out if the property defines a minimum value \b mvIMPACT::acquire::Property::hasMinValue
     *  should be called first.
     *
     *  \note
     *  If the property does not define a minimum value calling this function will raise
     *  an exception.
     *
     *  \since 1.12.63
     *
     */
    ZYX getMinValue( void ) const
    {
        return read( plMinValue );
    }
    /// \brief Reads the step width from a property.
    /**
     *  \note
     *  To find out if the property defines a step width \b mvIMPACT::acquire::Property::hasStepWidth
     *  should be called first.
     *
     *  \note
     *  If the property does not define a step width calling this function will raise
     *  an exception.
     *
     *  \since 1.12.63
     *
     */
    ZYX getStepWidth( void ) const
    {
        return read( plStepWidth );
    }
    /// \brief Reads a set of values from a property.
    /**
     *  This function queries a set of values from a property and stores these values
     *  into \a sequence.
     */
    void read(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<ZYX>& sequence,
        /// [in] The index from where to start reading values from the property.
        int start = 0,
        /// [in] The index where to stop reading values from the property.
        int end = END_OF_LIST ) const
    {
        const unsigned int valCnt = valuesToRead( start, end );
        sequence.resize( valCnt );
        for( unsigned int i = 0; i < valCnt; i++ )
        {
            sequence[i] = read( i + start );
        }
    }
    /// \brief Reads a set of values from a property.
    /**
     *  This function queries a set of values from a property and stores these values
     *  into \a sequence.
     */
    void read(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<ZYX>& sequence,
        /// [in] Set this parameter to \a true to get all values at once(recommended). If set to false the function will
        /// need more time and all values in \a sequence will be read one after the other
        bool boAtomic,
        /// [in] The index from where to start reading values from the property.
        int start = 0,
        /// [in] The index where to stop reading values from the property.
        int end = END_OF_LIST ) const
    {
        if( boAtomic )
        {
            const unsigned int valCnt = valuesToRead( start, end );
            sequence.resize( valCnt );
            int64_type* pValues = new int64_type[valCnt];
            const TPROPHANDLING_ERROR result = OBJ_GetI64Array( m_hObj, pValues, valCnt, start );
            for( unsigned int i = 0; i < valCnt; i++ )
            {
                sequence[i] = static_cast<ZYX>( pValues[i] );
            }
            delete [] pValues;
            if( result != PROPHANDLING_NO_ERROR )
            {
                ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
            }
        }
        else
        {
            read( sequence, start, end );
        }
    }
    /// \brief Writes one value to the property.
    /**
     *  This function writes a single value under index \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const EnumPropertyI64& write(
        /// [in] The value to write to the property.
        ZYX value,
        /// [in] The index defining at which position to write the value.
        int index = 0 ) const
    {
        const TPROPHANDLING_ERROR result = OBJ_SetI64( m_hObj, static_cast<int64_type>( value ), index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Writes a set of values to the property.
    /**
     *  This function writes a set of values starting at \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const EnumPropertyI64& write(
        /// [in] An array containing the values to write to the property.
        const std::vector<ZYX>& sequence,
        /// [in] The index where to write the first value to the property.
        int index = 0 ) const
    {
        const int vSize = static_cast<int>( sequence.size() );
        for( int i = 0; i < vSize; i++ )
        {
            write( sequence[i], index + i );
        }
        return *this;
    }
    /// \brief Writes a set of values to the property.
    /**
     *  This function writes a set of values starting at \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const EnumPropertyI64& write(
        /// [in] An array containing the values to write to the property.
        const std::vector<ZYX>& sequence,
        /// [in] Set this parameter to \a true to set all values at once(recommended). If set to false the function will
        /// need more time and all values in \a sequence will be set one after the other
        bool boAtomic,
        /// [in] The index where to write the first value to the property.
        int index = 0 ) const
    {
        if( boAtomic )
        {
            const unsigned int valCnt = static_cast<unsigned int>( sequence.size() );
            int64_type* pValues = new int64_type[valCnt];
            for( unsigned int i = 0; i < valCnt; i++ )
            {
                pValues[i] = static_cast<int64_type>( sequence[i] );
            }
            const TPROPHANDLING_ERROR result = OBJ_SetI64Array( m_hObj, pValues, valCnt, index );
            delete [] pValues;
            if( result != PROPHANDLING_NO_ERROR )
            {
                ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
            }
            return *this;
        }
        else
        {
            return write( sequence, index );
        }
    }
};

/// Provided for convenience only. This type represents a standard 64 bit integer property type.
typedef EnumPropertyI64<int64_type> PropertyI64;

#if defined(WRAP_JAVA) || defined(BUILD_FOR_JAVA)
typedef EnumPropertyI64<int64_type> PropertyI64BufferPartDataType;
typedef EnumPropertyI64<int64_type> PropertyI64DeviceTriggerOverlap;
#else
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBufferPartDataType.
typedef EnumPropertyI64<TBufferPartDataType> PropertyI64BufferPartDataType;

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceTriggerOverlap.
typedef EnumPropertyI64<TDeviceTriggerOverlap> PropertyI64DeviceTriggerOverlap;
#endif // #if defined(WRAP_JAVA) || defined(BUILD_FOR_JAVA)

//-----------------------------------------------------------------------------
/// \brief A class to represent pointer properties.
class PropertyPtr : public Property
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new unbound \b mvIMPACT::acquire::PropertyPtr object.
    explicit PropertyPtr() : Property() {}
    /// \brief Constructs a new \b mvIMPACT::acquire::PropertyPtr object.
    explicit PropertyPtr(
        /// [in] A valid handle to a pointer property
        HOBJ hProp ) : Property( hProp )
    {
        if( type() != ctPropPtr )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, PROPHANDLING_INVALID_PROP_VALUE_TYPE, hProp );
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::PropertyPtr from an existing one.
    PropertyPtr(
        /// [in] A constant reference to the \b mvIMPACT::acquire::PropertyPtr object, this object shall be created from
        const PropertyPtr& src ) : Property( src ) {}
#   if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    typedef void* value_type;
#   endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    /// \brief Reads a value from a property.
    /**
     *  This function queries a single value stored under index \a index in the property.
     *  \return The value stored at \a index within the property.
     */
    void* read(
        /// [in] The index of the value to read from the property.
        int index = 0 ) const
    {
        void* val;
        const TPROPHANDLING_ERROR result = OBJ_GetP( m_hObj, &val, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return val;
    }
    /// \brief Reads a set of values from a property.
    /**
     *  This function queries a set of values from a property and stores these values
     *  into \a sequence.
     */
    void read(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<void*>& sequence,
        /// [in] The index from where to start reading values from the property.
        int start = 0,
        /// [in] The index where to stop reading values from the property.
        int end = END_OF_LIST ) const
    {
        const unsigned int valCnt = valuesToRead( start, end );
        sequence.resize( valCnt );
        for( unsigned int i = 0; i < valCnt; i++ )
        {
            sequence[i] = read( i + start );
        }
    }
    /// \brief Writes one value to the property.
    /**
     *  This function writes a single value under index \a index to the property.
     *  \return A const 'self' reference.
     */
    const PropertyPtr& write(
        /// [in] The value to write to the property.
        void* value,
        /// [in] The index defining at which position to write the value.
        int index = 0 ) const
    {
        const TPROPHANDLING_ERROR result = OBJ_SetP( m_hObj, value, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
    /// \brief Writes a set of values to the property.
    /**
     *  This function writes a set of values starting at \a index to the property.
     *  \return A const 'self' reference.
     */
    const PropertyPtr& write(
        /// [in] An array containing the values to write to the property.
        const std::vector<void*>& sequence,
        /// [in] The index where to write the first value to the property.
        int index = 0 ) const
    {
        const unsigned int vSize = static_cast<unsigned int>( sequence.size() );
        for( unsigned int i = 0; i < vSize; i++ )
        {
            write( sequence[i], static_cast<int>( index + i ) );
        }
        return *this;
    }
};

//-----------------------------------------------------------------------------
/// \brief A class to represent string properties.
class PropertyS : public Property
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new unbound \b mvIMPACT::acquire::PropertyS object.
    explicit PropertyS() : Property() {}
    /// \brief Constructs a new \b mvIMPACT::acquire::PropertyS object.
    explicit PropertyS(
        /// [in] A valid handle to the string property
        HOBJ hProp ) : Property( hProp )
    {
        if( type() != ctPropString )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, PROPHANDLING_INVALID_PROP_VALUE_TYPE, hProp );
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::PropertyS from an existing one.
    PropertyS(
        /// [in] A constant reference to the \b mvIMPACT::acquire::EnumPropertyS object, this object shall be created from
        const PropertyS& src ) : Property( src ) {}
#if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    typedef std::string value_type;
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    /// \brief Returns the size(in bytes) needed for the binary representation of the string buffer.
    /**
     *  When binary data has been stored in a string property it has been stored in [Base64](https://en.wikipedia.org/wiki/Base64) format
     *  internally. If the user wants to know the length of the binary data in decoded format,
     *  this function can be called.
     *
     *  \sa \b mvIMPACT::acquire::PropertyS::readBinary, \n
     *      \b mvIMPACT::acquire::PropertyS::writeBinary, \n
     *      \b mvIMPACT::acquire::PropertyS::binaryDataBufferMaxSize
     *
     *  \return The size(in bytes) needed for the binary representation of the string buffer.
     */
    unsigned int binaryDataBufferSize(
        /// [in] The index of the value for which to query the
        /// buffer size(if this property holds more than one value).
        int index = 0 ) const
    {
        unsigned int val;
        const TPROPHANDLING_ERROR result = OBJ_GetBinaryBufferSize( m_hObj, &val, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return val;
    }
    /// \brief Reads the max size(in bytes) of binary data this property can store.
    /**
     *  When binary data shall be stored in a string property, the user will need to allocate memory
     *  when this data shall be written to the property. To find out how much binary data can be stored
     *  by a property before calling the function \b mvIMPACT::acquire::PropertyS::writeBinary this function can be used.
     *
     *  \sa \b mvIMPACT::acquire::PropertyS::readBinary, \n
     *      \b mvIMPACT::acquire::PropertyS::writeBinary, \n
     *      \b mvIMPACT::acquire::PropertyS::binaryDataBufferMaxSize
     *
     *  \return The size(in bytes) needed for the binary representation of the string buffer.
     */
    unsigned int binaryDataBufferMaxSize( void ) const
    {
        unsigned int val;
        const TPROPHANDLING_ERROR result = OBJ_GetBinaryBufferMaxSize( m_hObj, &val );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return val;
    }
    /// \brief Reads a value from a property.
    /**
     *  This function queries a single value stored under index \a index in the property.
     *  \return The value stored at \a index within the property.
     */
    std::string read(
        /// [in] The index of the value to read from the property.
        int index = 0 ) const
    {
        return compGetStringParam( sqPropVal, 0, index );
    }
    /// \brief Reads a set of values from a property.
    /**
     *  This function queries a set of values from a property and stores these values
     *  into \a sequence.
     */
    void read(
        /// [out] A reference to a container to store the data read from the property into.
        std::vector<std::string>& sequence,
        /// [in] The index from where to start reading values from the property.
        int start = 0,
        /// [in] The index where to stop reading values from the property.
        int end = END_OF_LIST ) const
    {
        const unsigned int valCnt = valuesToRead( start, end );
        sequence.resize( valCnt );
        for( unsigned int i = 0; i < valCnt; i++ )
        {
            sequence[i] = read( i + start );
        }
    }
#if !defined(WRAP_JAVA)
    /// \brief Reads a value stored in the property as binary data.
    /**
     *  Binary data can only be stored in string properties. When writing binary data to a string
     *  property it's stored in [Base64](https://en.wikipedia.org/wiki/Base64) format internally. The Base64 algorithm converts arbitrary data
     *  into a read and printable string representation. As a result of this 3 bytes of arbitrary binary
     *  data will occupy 4 bytes of memory.
     *
     *  Reading binary data with this function obviously only makes sense if the property has been assigned
     *  the value by a previous call to \b mvIMPACT::acquire::PropertyS::writeBinary (here you find a small code example as well).
     *  However using this method any kind of data can be stored by a string property.
     *  This can e.g. be interesting when certain data shall be stored in the
     *  user accessible part of the devices non-volatile memory.
     *
     *  \sa \b mvIMPACT::acquire::PropertyS::writeBinary, \n
     *      \b mvIMPACT::acquire::PropertyS::binaryDataBufferSize, \n
     *      \b mvIMPACT::acquire::PropertyS::binaryDataBufferMaxSize
     *  \return The binary data representation of the specified property value as a new std::string object.
     */
    std::string readBinary(
        /// [in] The index of the value to get(if this property holds more than one value).
        int index = 0,
        /// [in] If set to \a true this allows applications compiled with mvIMPACT Acquire 2.32.0 or greater using this function
        /// to run on systems with mvIMPACT Acquire smaller than 2.32.0. The legacy version of this function runs slower!
        bool boLegacyMode = false ) const
    {
        unsigned int bufSize = boLegacyMode ? binaryDataBufferSize( index ) : binaryDataBufferMaxSize();
        if( bufSize == 0 )
        {
            return std::string( "" );
        }

        auto_array_ptr<char> pBuf( bufSize );
        memset( pBuf.get(), 0, bufSize );
        const TPROPHANDLING_ERROR result = boLegacyMode ? OBJ_GetBinary( m_hObj, pBuf.get(), bufSize, index ) : OBJ_GetBinaryEx( m_hObj, pBuf.get(), &bufSize, index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return std::string( pBuf.get(), bufSize );
    }
#endif // #if !defined(WRAP_JAVA)
    /// \brief Writes one value to the property.
    /**
     *  This function writes a single value under index \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const PropertyS& write(
        /// [in] The value to write to the property.
        const std::string& value,
        /// [in] The index defining at which position to write the value.
        int index = 0 ) const
    {
        writeS( value, index );
        return *this;
    }
    /// \brief Writes a set of values to the property.
    /**
     *  This function writes a set of values starting at \a index to the property.
     *
     *  \return A const 'self' reference.
     */
    const PropertyS& write(
        /// [in] An array containing the values to write to the property.
        const std::vector<std::string>& sequence,
        /// [in] The index where to write the first value to the property.
        int index = 0 ) const
    {
        writeS( sequence, index );
        return *this;
    }
#if !defined(WRAP_JAVA)
    /// \brief Writes a block of binary data to one entry of the property.
    /**
     *  Binary data can only be stored in string properties. When writing binary data to a string
     *  property it's stored in [Base64](https://en.wikipedia.org/wiki/Base64) format internally. The Base64 algorithm converts arbitrary data
     *  into a read and printable string representation. As a result of this 3 bytes of arbitrary binary
     *  data will occupy 4 bytes of memory.
     *
     *  By writing binary data with this function arbitrary data can be stored by a string property.
     *  This can e.g. be interesting when certain data shall be stored in the
     *  user accessible part of the devices non-volatile memory.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  char binData [6] = { 'A', 'B', 0x00, -128, 'E', 'F' };
     *  const string value( binData, sizeof( binData ) / sizeof( binData[0] ) );
     *  PropertyS prop( getHandleFromSomewhere() );
     *  prop.writeBinary( value );
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  final int BUF_SIZE = 6;
     *  byte[] data_bytes = new byte[BUF_SIZE];
     *  data_bytes[0] = 0x00;
     *  data_bytes[1] = -1;
     *  data_bytes[2] = -128;
     *  data_bytes[3] = 0x33;
     *  ByteBuffer data = ByteBuffer.allocateDirect( BUF_SIZE );
     *  data.put( data_bytes );
     *  binaryProp = acquire.PropertyS( getHandleFromSomewhere() )
     *  binaryProp.writeBinary( data );
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  binData = '\x00\xFF\x80\x33'
     *  binaryProp = acquire.PropertyS(getHandleFromSomewhere())
     *  binaryProp.writeBinary(binData)
     * \endcode
     * \endif
     *
     *  To find out if a property contains binary data check if \b mvIMPACT::acquire::cfContainsBinaryData is set e.g. by calling
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  PropertyS prop( getHandleFromSomewhere() );
     *  if( prop.flags() & cfContainsBinaryData )
     *  {
     *    // Yes!! Binary data
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  PropertyS prop = new PropertyS( getHandleFromSomewhere() );
     *  if( ( prop.flags() & TComponentFlag.cfContainsBinaryData ) == TComponentFlag.cfContainsBinaryData )
     *  {
     *    // Yes!! Binary data
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  binaryProp = acquire.PropertyS(getHandleFromSomewhere())
     *  if pseudoBinaryProp.flags() & acquire.cfContainsBinaryData:
     *      # Yes!! Binary data!
     * \endcode
     *  \endif
     *
     * Performance considerations:
     *
     * mvIMPACT Acquire 2.15.0 and newer:
     *
     * - Base64 encoding/decoding only is performed when read string data previously written as binary data and vice versa.
     * - encoding/decoding only is performed if the 2 internal caches are out of sync. so only on the first read access using the other format.
     * - this version is more efficient compared to previous implementations.
     *
     * <div class="interactive_dotgraph">
     * \dot
     * digraph BinaryDataHandling2_15 {
     * abb [label="Application Binary Buffer"];
     * asb [label="Application String Buffer"];
     * ibs [label="Internal Binary Storage"];
     * iss [label="Internal Base64 Storage"];
     * { rank=same; abb; asb; }
     * { rank=same; ibs; iss; }
     * abb -> ibs [label="writeBinary:\nmemcpy"];
     * ibs -> abb [label="readBinary:\nmemcpy"];
     * asb -> iss [label="write:\nmemcpy"];
     * iss -> asb [label="read:\nmemcpy"];
     * ibs -> iss [label="Base64(encode)"];
     * iss -> ibs [label="Base64(decode)"];
     * }
     * \enddot
     * </div>
     *
     * mvIMPACT Acquire versions smaller than 2.15.0
     *
     * - Base64 encoding/decoding always is performed when reading/writing data in binary format.
     *
     * <div class="interactive_dotgraph">
     * \dot
     * digraph BinaryDataHandling {
     * abb [label="Application Binary Buffer"];
     * asb [label="Application String Buffer"];
     * tb [label="Temporary Buffer"];
     * is [label="Internal Storage"];
     * { rank=same; abb; asb; }
     * abb -> tb [label="writeBinary:\nmemcpy"];
     * tb -> is [label="Base64(encode)"];
     * tb -> abb [label="readBinary:\nmemcpy"];
     * is -> tb [label="Base64(decode)"];
     * asb -> is [label="write:\nmemcpy"];
     * is -> asb [label="read:\nmemcpy"];
     * }
     * \enddot
     * </div>
     *
     * \note
     * When a property stores binary data that came from a GenICam chunk buffer additional copy operations from the GenApi runtime will take place. This can be
     * considered as an additional copy operation into the application binary buffer. So binary chunk data should be avoided if possible!
     *
     *  \sa \b mvIMPACT::acquire::PropertyS::readBinary, \n
     *      \b mvIMPACT::acquire::PropertyS::binaryDataBufferSize, \n
     *      \b mvIMPACT::acquire::PropertyS::binaryDataBufferMaxSize
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  \return A const 'self' reference.
     *  \endif
     */
    const PropertyS& writeBinary(
        /// [in] A const reference to the string holding the binary data that shall
        /// be stored by the this property.
        const std::string& value,
        /// [in] The index defining at which position to write the value.
        int index = 0 ) const
    {
        const TPROPHANDLING_ERROR result = OBJ_SetBinary( m_hObj, value.c_str(), static_cast<unsigned int>( value.size() ), index );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hObj );
        }
        return *this;
    }
#endif // #if !defined(WRAP_JAVA)
};

//-----------------------------------------------------------------------------
/// \brief A helper class that represents one entry in the devices non-volatile memory
/** (if available).
 *
 *  Each entry of user and device specific data consists of a name, data a property
 *  defining the access rights for this entry and an optional password.
 *
 *  The name can be any string, but currently is limited to 255 characters.
 *
 *  The \b mvIMPACT::acquire::UserDataEntry::data property can hold any type of user data that shall be
 *  stored in the device's non-volatile memory. This can either be a string or binary
 *  data. To store binary data the function
 *  \b mvIMPACT::acquire::PropertyS::writeBinary
 *  can be used. Internally however binary data will be stored as a [Base64](https://en.wikipedia.org/wiki/Base64) encoded string.
 *  To read binary data from the property again the function
 *  \b mvIMPACT::acquire::PropertyS::readBinary
 *  must be called. The theoretical limit for the amount of data per entry is 2^16 (64KB) bytes,
 *  however the real limit might be below this value because the device does not offer
 *  that much memory.
 *
 *  The \b mvIMPACT::acquire::UserDataEntry::access property defines the access rights the user has when
 *  working with the entry. \b AFTER creation but \b BEFORE storing the entry into the device
 *  this property can be modified. At this point the creator of the entry can choose between 2 options:
 *  \b mvIMPACT::acquire::udarFull and \b mvIMPACT::acquire::udarRW.
 *  After storing the entry into the device by calling
 *  \b mvIMPACT::acquire::UserData::writeToHardware this property will become \b read-only and
 *  will remain \b read-only until the complete entry is deleted.
 *
 *  When the user creates a new entry for the user accessible device non-volatile memory
 *  he can either create a read/write data set, which means that every user can modify
 *  the \a data and the \a name property. In that case the property \a password is ignored.
 *  Apart from that an entry that can only be modified when the correct password has been
 *  written to the \a password property. To read a value is always allowed.
 *
 *  The \a password property will hold the user input and \b NOT the actual password needed
 *  to unlock the data set. However when an entry has been created the creator afterwards can
 *  write to the password. When the creator then calls the function \b mvIMPACT::acquire::UserData::writeToHardware
 *  the value of the \a password property is used as the 'real' password from that
 *  moment onwards.
 *
 *  The maximum length for the password currently is 255 characters. This does not
 *  provide total security of cause, but the idea of the password only is to hinder
 *  the user from deleting an import entry by accident.
 *
 *  The memory consumed by a single \b mvIMPACT::acquire::UserDataEntry can vary from device
 *  to device and depends on the way the data is stored internally. In any case when an entry
 *  is created it will consume more memory than the amount of bytes written to the
 *  \b mvIMPACT::acquire::UserDataEntry::data. After data has been written to an entry
 *  it is therefore important to check the \b mvIMPACT::acquire::UserData::memoryAvailable_bytes
 *  property if there is still enough memory available.
 *
 *  \note
 *  There might be entries that can't be modified by the user. These entries contain
 *  important data that have been written to the memory during production. An attempt
 *  to delete this data will fail.
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  //-----------------------------------------------------------------------------
 *  int storeUserData( Device* pDev, char* pData, size_t dataSize, const std::string& entryName )
 *  //-----------------------------------------------------------------------------
 *  {
 *    UserData& userData = pDev->getUserData();
 *    if( !userData.isAvailable() )
 *    {
 *      cout << "This device does not support user data" << endl;
 *      return -1;
 *    }
 *
 *    cout << "Available user memory(bytes): " << userData.memoryAvailable_bytes.read() << endl;
 *    cout << "Memory consumed already(bytes): " << userData.memoryConsumed_bytes.read() << endl;
 *
 *    // create a new entry
 *    UserDataEntry entry = userData.createEntry();
 *    if( !entry.isValid() )
 *    {
 *      cout << "Failed to create new entry" << endl;
 *      return -2;
 *    }
 *
 *    string value( pData, dataSize );
 *    entry.data.writeBinary( value );
 *    entry.name.write( entryName );
 *
 *    // write to non-volatile memory (therefore the device MUST be closed)
 *    if( pDev->isOpen() )
 *    {
 *      cout << "Can't store data as the device is already in use" << endl;
 *      return -3;
 *    }
 *
 *    userData.writeToHardware();
 *    if( pDev->HWUpdateResult.read() != urSetUserDataWriteOK )
 *    {
 *      cout << "Failed to store data in device non-volatile memory" << endl;
 *      return -4;
 *    }
 *
 *    // now this data is stored in the devices permanent memory
 *    return 0;
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  //-----------------------------------------------------------------------------
 *  public static int storeUserData( Device pDev, byte[] data_bytes, final String entryName )
 *  //-----------------------------------------------------------------------------
 *  {
 *    UserData userData = pDev.getUserData();
 *    if( !userData.isAvailable() )
 *    {
 *      System.out.println( "This device does not support user data" );
 *      return -1;
 *    }
 *
 *    System.out.println( String.format( "Available user memory(bytes): %d", userData.getMemoryAvailable_bytes().read() ) );
 *    System.out.println( String.format( "Memory consumed already(bytes): %d", userData.getMemoryConsumed_bytes().read() ) );
 *
 *    // create a new entry
 *    UserDataEntry entry = userData.createEntry();
 *    if( !entry.isValid() )
 *    {
 *      System.out.println( "Failed to create new entry" );
 *      return -2;
 *    }
 *
 *    ByteBuffer data = ByteBuffer.allocateDirect( data_bytes.length );
 *    data.put( data_bytes );
 *    entry.getData().writeBinary( data );
 *    entry.getName().write( entryName );
 *
 *    // write to non-volatile memory (therefore the device MUST be closed)
 *    if( pDev.isOpen() )
 *    {
 *      System.out.println( "Can't store data as the device is already in use" );
 *      return -3;
 *    }
 *
 *    userData.writeToHardware();
 *    if( pDev.getHWUpdateResult().read() != THWUpdateResult.urSetUserDataWriteOK )
 *    {
 *      System.out.println( "Failed to store data in device non-volatile memory" );
 *      return -4;
 *    }
 *
 *    // now this data is stored in the devices permanent memory
 *    return 0;
 *  }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *
 *  def storeUserData(pDev, pData, entryName):
 *     userData = pDev.getUserData()
 *     if not userData.isAvailable:
 *       print("This device does not support user data")
 *       return -1
 *
 *     print("Available user memory(bytes): " + str(userData.memoryAvailable_bytes.read()))
 *     print("Memory consumed already(bytes): " + str(userData.memoryConsumed_bytes.read()))
 *
 *     # create a new entry
 *     entry = userData.createEntry();
 *     if not entry.isValid:
 *       print("Failed to create new entry")
 *       return -2;
 *
 *     entry.data.writeBinary(pData)
 *     entry.name.write(entryName)
 *
 *     # write to non-volatile memory (therefore the device MUST be closed)
 *     if pDev.isOpen:
 *         print("Can't store data as the device is already in use")
 *         return -3
 *
 *     userData.writeToHardware();
 *     if pDev.HWUpdateResult.read() != acquire.urSetUserDataWriteOK:
 *         print("Failed to store data in device non-volatile memory")
 *         return -4
 *
 *     # now this data is stored in the devices permanent memory
 *     return 0
 * \endcode
 * \endif
 *
 *  \note
 *  Instances of this class can only be created by the class \b UserData.
 */
class UserDataEntry
//-----------------------------------------------------------------------------
{
    friend class UserData;
    HLIST m_hList;
    explicit UserDataEntry( HLIST hList ) : m_hList( hList ), name(), data(), access(), password()
    {
        if( hList != INVALID_ID )
        {
            ComponentLocator locator( hList );
            locator.bindComponent( name, "Name" );
            locator.bindComponent( data, "Data" );
            locator.bindComponent( access, "Access" );
            locator.bindComponent( password, "Password" );
        }
    }
public:
    /// \brief Call this function to check if this object references an existing entry.
    /**
     *  \return
     *  - true if this object references an existing entry
     *  - false otherwise
     */
    bool isValid( void ) const
    {
        return ( ( m_hList != INVALID_ID ) && ( OBJ_CheckHandle( m_hList, hcmFull ) == PROPHANDLING_NO_ERROR ) );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief The name of the entry.
    /**
     *  The maximum length for the name currently is 255 characters.
     */
    PropertyS name;
    /// \brief The data stored in this entry.
    /**
     *  The theoretical limit for the amount of data per entry is 2^16 (64KB) bytes,
     *  however the real limit might be below this value because the device does not offer
     *  that much memory.
     *
     *  This property can either store string or binary data. See \b mvIMPACT::acquire::PropertyS to find
     *  out how to work with binary data.
     */
    PropertyS data;
    /// \brief The access rights for this entry.
    /**
     *  After this entry has been written to the devices non-volatile memory, this property
     *  will become \b read-only.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TUserDataAccessRight.
     */
    PropertyIUserDataAccessRight access;
    /// \brief The password needed to modify this entry.
    /**
     *  The maximum length for the password is 255 characters currently. When the
     *  \b mvIMPACT::acquire::udarPassword is not specified
     *  by the \a access property, this property will be ignored. Otherwise this
     *  property must have been assigned the correct password (case sensitive) before
     *  the \a name and \a data properties can be modified.
     */
    PropertyS password;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-OFF*
};

//-----------------------------------------------------------------------------
/// \brief A helper class to work with the device specific non-volatile memory(if available).
/**
 *  A device might have a certain amount of non-volatile memory which can be accessed and modified by
 *  the user. This data can e.g. be used to store certain parameters or custom data permanently into the
 *  device. Thus this property e.g. can be used to store configuration data in the device before shipping it
 *  to the end user.
 *
 *  In theory the number of entries that can be stored in the device is not limited. However no device
 *  will provide an unlimited amount of memory.
 *
 *  Writing data to any property of a \b mvIMPACT::acquire::UserDataEntry as well as creating a new entry by calling
 *  \b mvIMPACT::acquire::UserData::createEntry or deleting an entry with the function
 *  \b mvIMPACT::acquire::UserData::deleteEntry will \b NOT automatically result in
 *  the complete data to be updated in the device specific memory. As writing to the device memory takes
 *  a long (in terms of ms) time depending on the device architecture the modifications will only become
 *  permanent when calling \b mvIMPACT::acquire::UserData::writeToHardware.
 *
 *  If data at the end of the list of entries doesn't fit in the memory it will be discarded and therefore
 *  will not be visible the next time the device is enumerated/accessed after the running process has
 *  terminated or the device has been disconnected.
 *
 *  \note
 *  Entries that contain no data will not be stored in hardware. If e.g. 5 user data entries have been created,
 *  but only entry 0, 1, 2 and 4 contain data the write operation will pack the data in a way that when the user data
 *  is read from the device again (when the driver for that device is loaded the next time) the list of entries
 *  will contain elements at position 0, 1, 2 and 3 but \b NOT a index number 4. Deleting an entry from the middle
 *  of the list of user data however will \b NOT move all remaining entries one step towards the front of the
 *  list. Therefore during one session the entry indexes will \b NOT change. They can either become invalid (when
 *  the corresponding entry has been deleted), can get valid (newly created entries will always appear at the next
 *  free entry, thus deleting and entry and creating a new directly afterwards will create that entry at exactly the
 *  same index) or new entries can appear (when a new entry has been created and no free list position in the
 *  middle of the list of entries has been available).
 *
 *  \note
 *  The device must be closed in order to write the user data. Check the property \b mvIMPACT::acquire::Device::HWUpdateResult
 *  afterwards in order to make sure the data transfer was successful.
 *
 *  \note
 *  If a device does not offer user accessible data \b mvIMPACT::acquire::UserDataEntry objects will still be returned by certain
 *  functions. To check if this feature is available call \b mvIMPACT::acquire::UserData::isAvailable.
 *
 *  \note
 *  If the user accessible data currently can't be modified an exception of type \b mvIMPACT::acquire::ENoWriteRights
 *  will be thrown.
 *
 *  \note
 *  Instances of this class cannot be constructed directly. To get access the function \b mvIMPACT::acquire::Device::getUserData.
 *  must be used.
 */
class UserData
//-----------------------------------------------------------------------------
{
    friend class Device;
    bool             m_boAvailable;
    HDEV             m_hDev;
    ComponentLocator m_userDataEntryLocator;
    explicit UserData( HDEV hDev ) : m_boAvailable( false ), m_hDev( hDev ), m_userDataEntryLocator( hDev ),
        reconnectBehaviour(), memoryAvailable_bytes(), memoryConsumed_bytes()
    {
        init();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::UserData objects.
    UserData& operator=( const UserData& rhs )
    {
        if( this != &rhs )
        {
            m_boAvailable = false;
            m_hDev = rhs.m_hDev;
            m_userDataEntryLocator.bindSearchBase( rhs.m_hDev );
            init();
        }
        return *this;
    }
    void init( void )
    {
        // check if user data is supported
        const HOBJ hUserData = m_userDataEntryLocator.findComponent( "UserData" );
        if( hUserData != INVALID_ID )
        {
            Component userData( hUserData );
            // check if the driver supports the new enhanced user data access
            if( userData.isList() )
            {
                m_userDataEntryLocator.bindSearchBase( m_userDataEntryLocator.searchbase_id(), "UserData" );
                m_userDataEntryLocator.bindComponent( reconnectBehaviour, "ReconnectBehaviour" );
                m_userDataEntryLocator.bindComponent( memoryAvailable_bytes, "MemoryAvailable_bytes" );
                m_userDataEntryLocator.bindComponent( memoryConsumed_bytes, "MemoryConsumed_bytes" );
                m_userDataEntryLocator.bindSearchBase( m_userDataEntryLocator.searchbase_id(), "Entries" );
                m_boAvailable = true;
            }
        }
    }
public:
    /// \brief Creates and returns a new entry to store user specific data.
    /**
     *  \note
     *  The data handled by this object will not be stored permanently in the devices non-volatile
     *  memory until \b mvIMPACT::acquire::UserData::writeToHardware has been called successfully.
     *
     *  \sa
     *  \b mvIMPACT::acquire::UserData::deleteEntry, \n
     *     mvIMPACT::acquire::UserData::writeToHardware
     *  \return A new \b mvIMPACT::acquire::UserDataEntry instance that can be used to store user specific data
     *  in the devices non-volatile memory.
     */
    UserDataEntry createEntry( void )
    {
        HLIST hList;
        const TDMR_ERROR result = DMR_CreateUserDataEntry( m_hDev, &hList );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        return UserDataEntry( hList );
    }
    /// \brief Deletes an entry of user specific data.
    /**
     *  If the entry has been stored to the non-volatile memory already and has been assigned
     *  the \b mvIMPACT::acquire::udarPassword flag, this call will fail, when
     *  \b mvIMPACT::acquire::UserDataEntry::password does not contain the correct password.
     *  \note
     *  The data handled by this object will not be removed permanently from the devices non-volatile
     *  memory until \b mvIMPACT::acquire::UserData::writeToHardware( void ) const has been called successfully.
     *  \sa
     *  \b mvIMPACT::acquire::UserData::createEntry, \n
     *      mvIMPACT::acquire::UserData::writeToHardware
     */
    void deleteEntry(
        /// [in] A reference to the entry to delete
        UserDataEntry& userDataEntry )
    {
        const TDMR_ERROR result = DMR_DeleteUserDataEntry( m_hDev, userDataEntry.m_hList );
        userDataEntry.m_hList = INVALID_ID;
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
    }
    /// \brief Returns the number of bytes of user accessible, non-volatile memory that is still available.
    /**
     *
     *  \since 1.12.64
     */
    int getFreeMemory( void ) const
    {
        return memoryAvailable_bytes.read() - memoryConsumed_bytes.read();
    }
    /// \brief Returns An object to work with an existing entry of user specific data.
    /**
     *  \note
     *  If an invalid number has been passed as \a nr an object will be returned as well. Therefore
     *  always check if the entry is valid by calling \b mvIMPACT::acquire::UserDataEntry::isValid before
     *  working with the object.
     *
     *  \return An object to work with an existing entry of user specific data.
     */
    UserDataEntry getUserDataEntry(
        /// [in] The number of the entry to return
        int nr ) const
    {
        std::ostringstream oss;
        oss << "Entry" << nr;
        return UserDataEntry( m_userDataEntryLocator.findComponent( oss.str() ) );
    }
    /// \brief Fills an array with all currently valid user data entry indexes.
    /**
     *  This function can be used to obtain a list of valid parameters for calls to the function \b mvIMPACT::acquire::UserData::getUserDataEntry.
     *  Every value in the returned array will (when passed to the function \b mvIMPACT::acquire::UserData::getUserDataEntry) result in a
     *  valid \b mvIMPACT::acquire::UserDataEntry object.
     */
    void validUserDataEntryIndexes(
        /// [out] A reference to the array receiving the list of valid indexes
        std::vector<int>& sequence ) const
    {
        sequence.clear();
        Component it( m_userDataEntryLocator.searchbase_id() );
        if( !it.isValid() )
        {
            return;
        }
        it = it.firstChild();
        if( !it.isValid() )
        {
            return;
        }
        std::string::size_type indexStart = it.name().find_first_of( "0123456789" );
        while( it.isValid() )
        {
            sequence.push_back( atoi( it.name().substr( indexStart ).c_str() ) );
            ++it;
        }
    }
    /// \brief This function should be called to check if this device offers non-volatile memory that can be accessed by the user.
    /**
     *  \return
     *  - true if the device offers non-volatile memory that can be accessed by the user
     *  - false otherwise
     */
    bool isAvailable( void ) const
    {
        return m_boAvailable;
    }
    /// \brief Writes the current set of user data into the devices non-volatile memory.
    /**
     *  This function might take a while. Depending on the device architecture and the amount of
     *  memory up to some hundred ms. Therefore make sure this function is not called more often
     *  than necessary to let your application perform efficiently.
     *  \sa
     *  \b mvIMPACT::acquire::UserData::createEntry, \n
     *  \b mvIMPACT::acquire::UserData::deleteEntry
     */
    void writeToHardware( void ) const
    {
        TDMR_ERROR result = DMR_WriteUserDataToHardware( m_hDev );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property that can be used to configure how the user data should be treated in case of a device that has been unplugged is plugged back in again.
    /**
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TUserDataReconnectBehaviour.
     *
     *  If a device does not support hot-plugging, this property will be invisible (\b mvIMPACT::acquire::Component::isVisible()),
     */
    PropertyIUserDataReconnectBehaviour reconnectBehaviour;
    /// \brief An integer property \b (read-only) containing the number of bytes of user accessible, non-volatile memory this device has available.
    PropertyI memoryAvailable_bytes;
    /// \brief An integer property \b (read-only) containing the number of bytes of user accessible, non-volatile memory currently consumed by user data.
    /**
     *  This doesn't indicate that all the data has already been stored in the non-volatile memory,
     *  but is the number of bytes needed to store the current user data permanently. No check for
     *  overflows will be performed. If the user defined data exceeds the size of the available memory,
     *  this data will be lost when disconnecting or switching of the supply voltage for this device.
     *
     *  To write data permanently into the device call the function \b mvIMPACT::acquire::UserData::writeToHardware
     *  But even after calling this function data that exceeds the available memory will be lost when the
     *  device looses supply voltage and/or the process terminates.
     */
    PropertyI memoryConsumed_bytes;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief This class and its functions represent an actual device detected by this interface in the current system.
/**
 *
 *  Instances of it can only be created by instances of the \b mvIMPACT::acquire::DeviceManager class
 *  as only the \b mvIMPACT::acquire::DeviceManager has the precise knowledge to do that anyway.
 *  As a result from this fact pointers to instances of \b mvIMPACT::acquire::Device can be obtained
 *  via a \b mvIMPACT::acquire::DeviceManager object only.
 *
 * \attention
 *  \b NEVER try to explicitly delete an instance of \b mvIMPACT::acquire::Device! You did not allocate it
 *  and the result will be a crash! The \b mvIMPACT::acquire::DeviceManager will take care of all resources
 *  for you.
 *
 *  A valid pointer to a \b mvIMPACT::acquire::Device object is needed to construct most of the
 *  other objects available in this interface.
 *
 *  Almost every object requiring a valid pointer to a \b mvIMPACT::acquire::Device object will
 *  need to device in an initialized state as the properties provided e.g. by the
 *  class \b mvIMPACT::acquire::CameraSettingsBase will be constructed when the device is initialized.
 *  To initialize a device this class provides the function \b Device::open.
 *  However every object which needs an initialized device to be constructed
 *  successfully will try to open the device when it hasn't been opened before, so
 *  the user does not need to call this function explicitly.
 *
 *  \attention
 *  Whenever a device is closed via a call to \b mvIMPACT::acquire::Device::close
 *  all other objects constructed with a pointer to that device(e.g. \b mvIMPACT::acquire::CameraSettingsBase
 *  before will become invalid and need to be reconstructed afterwards, so don't close a device needlessly.
 *
 *  \attention
 *  Whenever the last instance to a \b DeviceManager object gets
 *  destroyed within the current process every remaining device that was opened in this process before will
 *  be closed automatically!
 *  Thus every instance to \b mvIMPACT::acquire::Device objects or objects created with a pointer to a
 *  \b mvIMPACT::acquire::Device object will become invalid automatically.
 *  Therefore the user has to make sure there is always at least one instance to a
 *  \b mvIMPACT::acquire::DeviceManager object within the current process unless no more
 *  device access functions shall be called!
 */
class Device
//-----------------------------------------------------------------------------
{
#ifndef DOXYGEN_SHOULD_SKIP_THIS
    // only the DeviceManager is allowed to create Device objects, as it doesn't make
    // any sense for someone else anyway.
    friend class DeviceManager;
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        HDEV m_hDev;
        HDRV m_hDrv;
        int m_refCnt;
        explicit ReferenceCountedData( HDEV hDev ) : m_hDev( hDev ), m_hDrv( INVALID_ID ), m_refCnt( 1 ) {}
    }* m_pRefData;
    UserData m_userData;
#endif // #ifdef DOXYGEN_SHOULD_SKIP_THIS

    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    //-----------------------------------------------------------------------------
    void bindPublicProperties( HDEV hDev )
    //-----------------------------------------------------------------------------
    {
        ComponentLocator locator( hDev );
        locator.bindComponent( deviceClass, "DeviceClass" );
        locator.bindComponent( family, "Family" );
        locator.bindComponent( product, "Product" );
        locator.bindComponent( capabilities, "Capabilities" );
        locator.bindComponent( serial, "Serial" );
        locator.bindComponent( state, "State" );
        locator.bindComponent( deviceID, "DeviceID" );
        locator.bindComponent( deviceVersion, "DeviceVersion" );
        locator.bindComponent( firmwareVersion, "FirmwareVersion" );
        locator.bindComponent( loadSettings, "LoadSettings" );
        locator.bindComponent( autoLoadSettingOrder, "AutoLoadSettingOrder" );
        locator.bindComponent( interfaceLayout, "InterfaceLayout" );
        locator.bindComponent( customDataDirectory, "CustomDataDirectory" );
        locator.bindComponent( defaultRequestCount, "DefaultRequestCount" );
        locator.bindComponent( resultQueueCount, "ResultQueueCount" );
        locator.bindComponent( userControlledImageProcessingEnable, "UserControlledImageProcessingEnable" );
        locator.bindComponent( allowUnrecommendedFeatures, "AllowUnrecommendedFeatures" );
        locator.bindComponent( acquisitionStartStopBehaviour, "AcquisitionStartStopBehaviour" );
        locator.bindComponent( HWUpdateResult, "HWUpdateResult" );
        locator.bindComponent( manufacturer, "Manufacturer" );
        locator.bindComponent( manufacturerSpecificInformation, "ManufacturerSpecificInformation" );
        locator.bindComponent( desiredAccess, "DesiredAccess" );
        locator.bindComponent( grantedAccess, "GrantedAccess" );
        locator.bindComponent( autoNegotiatePacketSize, "AutoNegotiatePacketSize" );
        locator.bindComponent( autoNegotiatePacketSizeMode, "AutoNegotiatePacketSizeMode" );
        locator.bindComponent( licenseValid, "LicenseValid" );
        locator.bindComponent( licenseDetails, "LicenseDetails" );
    }
    //-----------------------------------------------------------------------------
    HDRV hDrvInternal( void ) const
    //-----------------------------------------------------------------------------
    {
        DMR_GetDriverHandle( m_pRefData->m_hDev, &( m_pRefData->m_hDrv ) );
        return m_pRefData->m_hDrv;
    }
    //-----------------------------------------------------------------------------
    explicit Device( HDEV hDev ) : m_pRefData( new ReferenceCountedData( hDev ) ), m_userData( hDev ),
        deviceClass(), family(), product(), capabilities(), serial(), state(), deviceID(), deviceVersion(),
        firmwareVersion(), loadSettings(), autoLoadSettingOrder(), interfaceLayout(),
        customDataDirectory(), defaultRequestCount(), resultQueueCount(), userControlledImageProcessingEnable(), allowUnrecommendedFeatures(),
        acquisitionStartStopBehaviour(), HWUpdateResult(), manufacturer(), manufacturerSpecificInformation(), desiredAccess(), grantedAccess(),
        autoNegotiatePacketSize(), autoNegotiatePacketSizeMode(), licenseValid(), licenseDetails()
        //-----------------------------------------------------------------------------
    {
        bindPublicProperties( hDev );
    }
public:
    /// \brief Copy constructor.
    /**
     *  Creates a new object from an existing device object. Keep in mind that this new object
     *  will provide access to the very same hardware and therefore you might as well use the original
     *  reference returned from the \b mvIMPACT::acquire::DeviceManager. This constructor
     *  is only provided for internal reference counting to guarantee correct operation of the
     *  objects of this class under all platforms and languages.
     */
    explicit Device( const Device& src ) : m_pRefData( src.m_pRefData ), m_userData( src.m_pRefData->m_hDev ),
        deviceClass( src.deviceClass ), family( src.family ), product( src.product ),
        capabilities( src.capabilities ), serial( src.serial ), state( src.state ),
        deviceID( src.deviceID ), deviceVersion( src.deviceVersion ), firmwareVersion( src.firmwareVersion ), loadSettings( src.loadSettings ),
        autoLoadSettingOrder( src.autoLoadSettingOrder ), interfaceLayout( src.interfaceLayout ),
        customDataDirectory( src.customDataDirectory ), defaultRequestCount( src.defaultRequestCount ), resultQueueCount( src.resultQueueCount ),
        userControlledImageProcessingEnable( src.userControlledImageProcessingEnable ), allowUnrecommendedFeatures( src.allowUnrecommendedFeatures ),
        acquisitionStartStopBehaviour( src.acquisitionStartStopBehaviour ),
        HWUpdateResult( src.HWUpdateResult ), manufacturer( src.manufacturer ), manufacturerSpecificInformation( src.manufacturerSpecificInformation ),
        desiredAccess( src.desiredAccess ), grantedAccess( src.grantedAccess ), autoNegotiatePacketSize( src.autoNegotiatePacketSize ),
        autoNegotiatePacketSizeMode( src.autoNegotiatePacketSizeMode ), licenseValid( src.licenseValid ), licenseDetails( src.licenseDetails )
    {
        ++( m_pRefData->m_refCnt );
    }
    /// \brief Class destructor.
    /**
     *  \note
     *  This destructor must only be called for objects that have been created directly by
     *  the user on unmanaged heaps. Under most circumstances this means \b NEVER. E.g. for instances
     *  that have been obtained from a \b mvIMPACT::acquire::DeviceManager object do \b NOT call
     *  this destructor. The \b mvIMPACT::acquire::DeviceManager will take care of all the
     *  resources for you.
     */
    ~Device( void )
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::Device objects.
    Device& operator=( const Device& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            // inc. the NEW reference count
            ++( m_pRefData->m_refCnt );
            bindPublicProperties( m_pRefData->m_hDev );
            m_userData = UserData( rhs.m_pRefData->m_hDev );
        }
        return *this;
    }
    /// \brief Closes an opened device.
    /**
     *  This function closes a device previously opened again.
     *
     *  \attention
     *  Whenever a device is closed via a call to \b mvIMPACT::acquire::Device::close
     *  all other objects constructed with a pointer to that device(e.g. \b mvIMPACT::acquire::CameraSettingsBase
     *  before will become invalid and need to be reconstructed afterwards, so don't close a device needlessly.
     *
     *  \sa
     *  \b Device::open, \n \b Device::isOpen
     */
    void close( void )
    {
        HDRV h = hDrvInternal();
        if( h != INVALID_ID )
        {
            DMR_CloseDevice( h, m_pRefData->m_hDev );
            m_pRefData->m_hDrv = INVALID_ID;
        }
    }
    /// \brief Checks whether this device has a certain capability.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceCapability.
     *
     *  \return
     *  - true if the device has the capability in question
     *  - false otherwise.
     */
    bool hasCapability(
        /// [in] The capability whose presence shall be checked.
        TDeviceCapability capability ) const
    {
        return ( ( capabilities.isValid() ) ? ( ( capabilities.read() & capability ) == capability ) : false );
    }
    /// \brief Checks whether this device has a valid usage license.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \note As the name indicates, this property returns if this device has a valid license. Not all third-party vendors
     *  are allowed to run with this SDK without limitations, so this function offers a way to check in advance if this is one of them.
     *
     *  \since 2.46.0
     *  \return
     *  - true if the device has a valid license
     *  - false otherwise.
     */
    bool hasValidLicense( void ) const
    {
        return ( ( licenseValid.isValid() ) ? ( licenseValid.read() == bTrue ) : true );
    }
    /// \brief A unique identifier for this device.
    /**
     *  \note
     *  This handle is \b NOT to be confused with the id stored in the devices EEPROM
     *  The latter one represents a number stored somewhere in the physical device's EEPROM, while
     *  this handle can be assumed as a handle from a software based point of view.
     */
    HDEV hDev( void ) const
    {
        return m_pRefData->m_hDev;
    }
    /// \brief A unique identifier for the functionality offered by this device.
    /**
     *
     *  \note
     *  This identifier is only valid, if the device has been initialized
     *  before by a call to \b Device::open
     */
    HDRV hDrv( void ) const
    {
        return ( m_pRefData->m_hDrv != INVALID_ID ) ? m_pRefData->m_hDrv : hDrvInternal();
    }
    /// \brief Returns a list providing access to driver library specific features.
    /**
     *  This list does exist only once per device driver library. Changes in this list will affect all
     *  devices that are operated using this device driver library.
     *
     *  \since 2.17.0
     */
    ComponentList deviceDriverFeatureList( void ) const
    {
        HOBJ hObj = INVALID_ID;
        size_t bufSize = sizeof( hObj );
        TDMR_ERROR result = DMR_GetDeviceInfoEx( m_pRefData->m_hDev, dmdithDeviceDriver, &hObj, &bufSize );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        return ComponentList( hObj );
    }
    /// \brief Returns the current initialisation status in this process.
    /**
     *  If this function returns \a true, this only states that the current
     *  process has not opened the device in question already. A call to \b mvIMPACT::acquire::Device::open()
     *  can still fail because of some other process using this device.
     *
     *  \sa
     *  \b Device::open, \n \b Device::close
     *  \return
     *  - true if the device is initialized(opened) in the current process.
     *  - false otherwise.
     */
    bool isOpen( void ) const
    {
        return hDrvInternal() != INVALID_ID;
    }
    /// \brief Returns the current usage status of this device.
    /**
     *  If this function returns \a true, this device was not in use at the time of calling this function.
     *  A call to \b mvIMPACT::acquire::Device::open() can still fail afterwards if some other process on the system
     *  claimed the device in the time between this call and the call to \b mvIMPACT::acquire::Device::open().
     *
     *  \sa
     *  \b Device::open, \n \b Device::close
     *
     *  \since 2.0.11
     *  \return
     *  - true if the device is in use by at least one process(this includes the calling process).
     *  - false otherwise.
     */
    bool isInUse( void ) const
    {
        if( isOpen() )
        {
            return true;
        }
        unsigned int inUse = 0;
        size_t bufSize = sizeof( inUse );
        TDMR_ERROR result = DMR_GetDeviceInfoEx( m_pRefData->m_hDev, dmditDeviceIsInUse, &inUse, &bufSize );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        return inUse != 0;
    }
    /// \brief Opens a device.
    /**
     *  This function will try to open the device represented by this instance of
     *  \b mvIMPACT::acquire::Device. If this fails for any reason an exception will be thrown. The exception
     *  object will contain additional information about the reason for the error.
     *
     *  Calling this function is not really necessary, as each object for accessing
     *  other settings of the device or even the function interface need the device to
     *  be opened in order to be constructed. Therefore all the constructors for these
     *  objects check if the device is open by calling \b mvIMPACT::acquire::Device::isOpen and open
     *  the device if necessary.
     *
     *  \note
     *  Keep in mind that the first object trying to open the device might therefore
     *  throw an exception as well if opening the device fails for some reason.
     *
     *  Whenever a device is opened, the driver executes the following procedure:
     *
     *  <div align="center"><img src="./Device_Setting_Start_Procedure.png" alt="Device_Setting_Start_Procedure.png"></div>
     *  <center>Device setting start procedure</center>
     *
     *  Please have a look <a class="el" href="../GUI_page_mvPropView.html">here</a> for more information about automatic loading of
     *  settings when a device is opened.
     */
    void open( void )
    {
        TDMR_ERROR result = DMR_OpenDevice( m_pRefData->m_hDev, &( m_pRefData->m_hDrv ) );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
    }
    /// \brief Assigns a new ID to this device.
    /**
     *  To allow any application to distinguish between different devices of the same
     *  type the user can assign a unique ID to each device using this function. This ID
     *  currently is limited to values between 0 and 250 and is stored in the devices
     *  internal memory. This ID is \b NOT volatile. It will remain stored even if
     *  the device is unplugged.
     *
     *  \note
     *  \b REMARKS:
     *  \note
     *  - The device must be \b closed to assign a new ID.
     *  - This ID is not to be confused with the handle returned by the function \b mvIMPACT::acquire::Device::hDev.
     *  The latter one represents something which can be assumed as a handle from a software based point
     *  of view, while the ID represented by the property \b mvIMPACT::acquire::Device::deviceID is an ID stored in the physical
     *  devices EEPROM.
     *  - Not every device will offer this feature! When calling this function for a device that does not
     *  offer this feature, the function will return \b mvIMPACT::acquire::DMR_FEATURE_NOT_AVAILABLE.
     *
     *  \sa
     *  \b mvIMPACT::acquire::Device::open, \n \b mvIMPACT::acquire::Device::close
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int setID(
        /// [in] The new \a ID that shall be assigned to the device.
        int newID ) const
    {
        return DMR_SetDeviceID( m_pRefData->m_hDev, newID );
    }
    /// \brief Updates the firmware of the device.
    /**
     *  Calling this function will cause the driver to download a firmware version compiled
     *  into the driver library into the devices non-volatile internal memory.
     *
     *  \note
     *  - This feature currently is only available for \b mvBlueFOX devices. To update the firmware of other devices please refer to the tool \c mvDeviceConfigure(this tool also offers a command line interface)
     *  - Be sure you know what you are doing \b before calling this function. Under normal circumstances
     *  it won't be necessary to update a devices firmware.
     *  - The download will take some time (depending on the device up to 30 seconds). During this time
     *  the device and the thread calling this function will \b NOT respond.
     *  - Do \b NOT interrupt this download.
     *  - After a successful download a USB device needs to be unplugged and plugged in again.
     *  Otherwise the new firmware version will not be activated.
     *  - To download a new firmware version the device must be \b closed.
     *  - Not every device will offer this feature! When calling this function for a device that does not
     *  offer this feature, the function will return \b mvIMPACT::acquire::DMR_FEATURE_NOT_AVAILABLE.
     *
     *  \sa
     *  \b mvIMPACT::acquire::Device::open, \n \b mvIMPACT::acquire::Device::close
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int updateFirmware( void ) const
    {
        return DMR_UpdateFirmware( m_pRefData->m_hDev );
    }
    /// \brief Returns a reference to a helper class to handle user specific data stored in the devices non-volatile memory(if available).
    /**
     *  \return A reference to a helper class to handle user specific data stored in the devices
     *  non-volatile memory(if available).
     */
    UserData& getUserData( void )
    {
        return m_userData;
    }
    /// \brief A convenience function mostly used internally. Raises an exception if the current value of <b>mvIMPACT::acquire::Device::interfaceLayout</b> does not match the value passed to the function.
    /**
     *  If a driver does not support the interface layout property this function does nothing!
     */
    void validateInterfaceLayout( TDeviceInterfaceLayout requiredInterfaceLayout ) const
    {
        if( interfaceLayout.isValid() )
        {
            if( interfaceLayout.read() != requiredInterfaceLayout )
            {
                ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, DMR_INVALID_PARAMETER, "The current interface layout does not support the current operation or object instantiation. Refer to the API documentation for details about different interface layouts" );
            }
        }
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property \b (read-only) defining the device class this device belongs to.
    /**
     *  \note
     *  This property has been added to the device driver in version 1.8.3 thus might not be available when
     *  working with old device drivers. Therefore always call the function \b mvIMPACT::acquire::Component::isValid
     *  to check if this property is available or not.
     */
    PropertyIDeviceClass deviceClass;
    /// \brief A string property \b (read-only) containing the family name of this device.
    PropertyS family;
    /// \brief A string property \b (read-only) containing the product name of this device.
    PropertyS product;
    /// \brief An enumerated integer property \b (read-only) defining special device capabilities.
    /**
     *  This property stores certain device capabilities that can be read without opening the device.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceCapability.
     */
    PropertyIDeviceCapability capabilities;
    /// \brief A string property \b (read-only) containing the serial number of this device.
    PropertyS serial;
    /// \brief An enumerated integer property \b (read-only) containing the current state of this device.
    /**
     *  This property e.g. provides information about the current state of the device. For USB devices this can e.g. indicate whether
     *  a device is currently plugged into the system or not.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceState.
     *
     *  \b GenICam/GenTL \b device \b specific:
     *  In order to reduce the amount of network traffic to a minimum, this property will only be updated automatically
     *  for network devices if the property \b mvIMPACT::acquire::Device::registerErrorEvent is set to
     *  \b mvIMPACT::acquire::bTrue (which is the default behaviour). If the IP addresses stay the same the
     *  connection is automatically re-established then once the device is detected by the driver again.
     *  However if the IP address of the device and/or the network adapter of the system it is used from changes
     *  \b mvIMPACT::acquire::DeviceManager::updateDeviceList()
     *  must be called regardless of the value of \b mvIMPACT::acquire::Device::registerErrorEvent before a device
     *  that was lost can re-establish a connection to the capture driver.
     *  Apart from that \b ALL \b GenICam/GenTL will only update this property automatically if the device is
     *  currently in use \b BY \b THIS \b PROCESS, so when the device has been opened. This is also to save
     *  bandwidth and resources!
     */
    PropertyIDeviceState state;
    /// \brief An integer property \b (read-only) containing the device ID associated with this device.
    /**
     *  A device ID can be used to identify a certain device in the system. The ID is an 8 bit unsigned
     *  integer value stored in the device's EEPROM. In order to allow the
     *  distinct detection of a device via its device ID, the user has to make sure that two devices
     *  belonging to the same product family never share the same ID.
     *
     *  \note
     *  \b REMARKS:
     *  \note
     *  - To modify the device ID a separate tool will be provided. To modify the device
     *  ID without that tool the function \b mvIMPACT::acquire::Device::setID can be called.
     *  - This ID is not to be confused with the handle returned by the function \b mvIMPACT::acquire::Device::hDev.
     *  The latter one represents something which can be assumed as a handle from a software based point
     *  of view, while the ID represented by the property \a deviceID is an ID stored in the physical
     *  devices EEPROM.
     */
    PropertyI deviceID;
    /// \brief A string property \b (read-only) containing the version(e.g. the hard ware revision) of this device.
    /**
     *  \note
     *  This feature is supported by every device driver. If a device does not seem to support this feature (calling \b mvIMPACT::acquire::Component::isValid returns false)
     *  a driver update will fix this.
     */
    PropertyS deviceVersion;
    /// \brief An integer property \b (read-only) containing the firmware version of this device.
    /**
     *  A firmware is considered to be something that is stored in non volatile device memory, thus when a device
     *  is disconnected from the power supply and plugged into a different target system the same code will be executed
     *  on the device.
     *
     *  Some devices however may not support non volatile memory to accommodate a firmware. Typically the device driver then will download
     *  a firmware into the devices RAM at startup. Such devices will be considered as not supporting a firmware as in this
     *  case only the driver version present on the target system has impact on the devices behaviour.
     *
     *  When a device does not support a non volatile firmware, reading this property will always return 0.
     */
    PropertyI firmwareVersion;
    /// \brief An enumerated integer property which can be used to define which previously stored setting to load when the device is opened.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceLoadSettings.
     *
     *  \note
     *  Once the device is in use (has been initialized) this property will become \b (read-only).
     */
    PropertyIDeviceLoadSettings loadSettings;
    /// \brief A string property \b (read-only) containing the auto load order of feature settings that is executed during initialisation of the device.
    /**
     *  The first setting detected on the system will be used.
     */
    PropertyS autoLoadSettingOrder;
    /// \brief An enumerated integer property which can be used to define which interface layout shall be used when the device is opened.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceInterfaceLayout.
     *
     *  \note
     *  Once the device is in use (has been initialized) this property will become \b (read-only).
     *
     *  \note
     *  This feature is available for every device. A device not offering this feature requires a driver update. Always check
     *  for the availability of this feature by calling \b mvIMPACT::acquire::Component::isValid.
     *
     *  Not every device will offer the same options.
     *  Check for valid modes by reading the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyIDeviceInterfaceLayout::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyIDeviceInterfaceLayout::getTranslationDictValue.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyIDeviceInterfaceLayout::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     */
    PropertyIDeviceInterfaceLayout interfaceLayout;
    /// \brief A string property \b (read-only once the device is open) containing a path to a custom directory for the location of camera description files, etc.
    /**
     *  When a custom path is assigned to this property this path will be used to locate certain driver specific files
     *  and folders. Under this folder the following structure must be created:
     *
     * \code
     *  <customDataDirectory>
     *      |- CameraFiles  // this folder will be searched by frame grabbers for camera description files
     *      |- GenICam      // this folder will be searched by GenICam compliant devices that refer to a local GenICam&trade; description file
     * \endcode
     *
     *  If this property is left empty
     * \code
     *  %PUBLIC%/Documents/MATRIX VISION/mvIMPACT Acquire
     * \endcode
     *  will be used by default on Windows&trade; platforms and
     * \code
     *  /etc/matrix-vision/mvimpact-acquire
     * \endcode
     *  on Linux platforms.
     */
    PropertyS customDataDirectory;
    /// \brief An integer property that defines the number of \b mvIMPACT::acquire::Request objects to be created when the device is opened.
    /**
     *  By writing to this property an application can define the default number of \b mvIMPACT::acquire::Request
     *  objects that will be allocated when opening the device.
     *
     *  \note
     *  This property will become read-only while the device is open.
     *
     *  \sa
     *  \b mvIMPACT::acquire::SystemSettings::requestCount to change the number of request objects later and to find out why this parameter is important
     */
    PropertyI defaultRequestCount;
    /// \brief An integer property that defines the number of result queues to be created when the device is opened.
    /**
     *  By writing to this property an application can define the number of result queues that will be allocated
     *  when opening the device. When requesting buffers the user can define in which result queue a processed request shall
     *  end up by writing to the property \b mvIMPACT::acquire::ImageRequestControl::resultQueue. When waiting for a request to become ready by calling \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor
     *  the application can specify on which queue to wait.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     * Device* pDev = getDevicePointerFromSomewhere();
     * pDev->resultQueueCount.write( 2 );
     * ImageRequestControl irc( pDev );
     * FunctionInterface fi( pDev );
     * irc.resultQueue.write( 0 );
     * fi.imageRequestSingle( &irc ); // request a buffer that will be stored in queue 0 when ready
     * irc.resultQueue.write( 1 );
     * fi.imageRequestSingle( &irc ); // request a buffer that will be stored in queue 1 when ready
     * fi.imageRequestWaitFor( 500, 0 ); // wait on queue 0
     * fi.imageRequestWaitFor( 500, 1 ); // wait on queue 1
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     * Device pDev = getDevicePointerFromSomewhere();
     * pDev.getResultQueueCount().write( 2 );
     * ImageRequestControl irc = new ImageRequestControl( pDev );
     * FunctionInterface fi = new FunctionInterface( pDev );
     * irc.getResultQueue().write( 0 );
     * fi.imageRequestSingle( irc ); // request a buffer that will be stored in queue 0 when ready
     * irc.getResultQueue().write( 1 );
     * fi.imageRequestSingle( irc ); // request a buffer that will be stored in queue 1 when ready
     * fi.imageRequestWaitFor( 500, 0 ); // wait on queue 0
     * fi.imageRequestWaitFor( 500, 1 ); // wait on queue 1
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     * pDev = getDeviceFromSomewhere()
     * pDev.resultQueueCount.write(2)
     * irc = ImageRequestControl(pDev)
     * fi = FunctionInterface(pDev)
     * irc.resultQueue.write(0)
     * fi.imageRequestSingle(irc) # request a buffer that will be stored in queue 0 when ready
     * irc.resultQueue.write(1)
     * fi.imageRequestSingle(irc) # request a buffer that will be stored in queue 1 when ready
     * fi.imageRequestWaitFor(500, 0) # wait on queue 0
     * fi.imageRequestWaitFor(500, 1) # wait on queue 1
     * \endcode
     * \endif
     *
     * This can be useful e.g. when working with 2 different settings to sort all buffer capture with setting 0 into one queue
     * and all the others into another queue.
     *  \note
     *  This property will become read-only while the device is open.
     *
     * \sa
     * \b mvIMPACT::acquire::ImageRequestControl::resultQueue, \n
     * \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor
     */
    PropertyI resultQueueCount;
    /// \brief An enumerated integer property defining whether user controlled image processing related features shall be created under 'System Settings' or not.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  Setting this feature to \b mvIMPACT::acquire::bTrue will result in a separate thread being created when opening the
     *  device driver instance. The thread will decouple the host based image processing from the acquisition engine. Apart
     *  from that it will also create additional properties in the \c ImageProcessingControl list under \c SystemSettings that
     *  can be used to control the behaviour of this thread. This might be useful e.g. to make sure images can be acquired faster
     *  than they can be processed and it is not needed to processed each image.
     *
     *  \note
     *  This property will become read-only while the device is open.
     *
     * \sa
     * \b mvIMPACT::acquire::SystemSettings::imageProcessingMode \n
     * \b mvIMPACT::acquire::Request::hasProcessingBeenSkipped
     *
     *  \since 2.14.0
     */
    PropertyIBoolean userControlledImageProcessingEnable;
    /// \brief An enumerated integer property which can be used to unlock certain features, that are available but not recommended by the device manufacturer.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  This property will be invisible by default. As the name indicates its use requires special
     *  knowledge that can be provided by the device manufacturer on request.
     *
     *  \note
     *  Once the device is in use (has been initialized) this property will become \b (read-only).
     *
     *  \attention
     *  Unlocking certain unrecommended features might result in the appearance of new translation
     *  dictionary entries for certain properties. Some of these translation strings might contain
     *  an exclamation mark ('!') in its name. \b NEVER rely on that! These exclamation marks
     *  or even the complete entry might disappear with a new driver release without further notice!
     */
    PropertyIBoolean allowUnrecommendedFeatures;
    /// \brief An enumerated integer property defining the start/stop behaviour during acquisition of this driver instance.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAcquisitionStartStopBehaviour.
     *
     *  \note
     *  This property will become read-only while the device is open.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *
     *  Not every device will offer the same options.
     *  Check for valid modes by reading the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyIAcquisitionStartStopBehaviour::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyIAcquisitionStartStopBehaviour::getTranslationDictValue.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyIAcquisitionStartStopBehaviour::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     *
     * \since 1.12.11
     */
    PropertyIAcquisitionStartStopBehaviour acquisitionStartStopBehaviour;
    /// \brief An enumerated integer property \b (read-only) defining user executed hardware update results.
    /**
     *  This property e.g. might contain the result of a user executed firmware update.
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::THWUpdateResult.
     */
    PropertyIHWUpdateResult HWUpdateResult;
    /// \brief A string property \b (read-only) containing the name of the manufacturer of this device.
    /**
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *
     *  \since 2.11.3
     */
    PropertyS manufacturer;
    /// \brief A string property \b (read-only) containing manufacturer specific information of this device.
    /**
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *
     *  \since 2.18.3
     */
    PropertyS manufacturerSpecificInformation;
    /// \brief An enumerated integer property that can be used to define the desired access to the device when opening it.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceAccessMode.
     *
     *  \note
     *  This property will become read-only while the device is open.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIDeviceAccessMode desiredAccess;
    /// \brief An enumerated integer property \b (read-only) that can be used to query the granted access to the device after an attempt to open it.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceAccessMode.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIDeviceAccessMode grantedAccess;
    /// \brief An enumerated integer property which can be used to enable or disable the MTU auto negotiation of a GigE Vision device when opening it.
    /**
     * If set to true, the driver will try to determine the max. possible packet size during init, which if successful will result in optimal performance.
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \note Once the device is in use (has been initialized) this property will become \b (read-only). If this feature is disabled even before the device has been opened a
     *  firmware update is needed to use it when accessed via the \c mvGenTLProducer-lib. When using a 3rd party GenTL producer to access the GigE Vision device this
     *  feature will not be available.
     *
     *  \note This property might not be supported by every device. Therefore always call the function
     *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIBoolean autoNegotiatePacketSize;
    /// \brief An enumerated integer property \b (read-only) that can be used to define how the auto packet size negotiation for a GigE Vision device is handled.
    /**
     *  If set to \b mvIMPACT::acquire::danpsmHighToLow the MTU is automatically negotiated starting from the NICs current MTU down to a value supported by all components belonging to the network path
     *  (device, network interface card, switches, ...), if set to \b mvIMPACT::acquire::danpsmLowToHigh the negotiation starts with the small value tries larger values with each iteration until the
     *  optimal value has been found.
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceAutoNegotiatePacketSizeMode.
     *
     *  \note Once the device is in use (has been initialized) this property will become \b (read-only). When using a 3rd party GenTL producer to access the GigE Vision device this
     *  feature will not be available.
     *
     *  \note This property might not be supported by every device. Therefore always call the function
     *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIDeviceAutoNegotiatePacketSizeMode autoNegotiatePacketSizeMode;
    /// \brief A boolean property \b (read-only) that indicates if a device may be used with this SDK.
    /**
    *  All MATRIX VISION imaging and image capture devices may be used with this SDK without limitations. Third party devices might work as well but
    *  without an appropriate license that can be obtained from MATRIX VISION certain restrictions may apply.
    *
    *  \note This property will only be supported by some drivers (those allowing the usage of third party devices). Therefore always call the function
    *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
    *
    * \sa \b mvIMPACT::acquire::Device::licenseDetails
    *
    * \since 2.46.0
    */
    PropertyIBoolean licenseValid;
    /// \brief A string property \b (read-only) that indicates why a device may be used with this SDK.
    /**
    *  This property holds information on why a device may be used with mvIMPACT Acquire.
    *
    *  \note This property will only be supported by some drivers (those allowing the usage of third party devices). Therefore always call the function
    *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
    *
    * \sa \b mvIMPACT::acquire::Device::licenseValid
    *
    * \since 2.46.0
    */
    PropertyS licenseDetails;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief Grants access to devices that can be operated by this software interface.
/**
 *  This class will grant access to any device installed on/in the
 *  current system. Whenever somewhere in the code a \b mvIMPACT::acquire::DeviceManager instance is
 *  created it can be used to access any device currently
 *  supported and available. \n \n This is the only class which is allowed to
 *  create instances of the class \b mvIMPACT::acquire::Device, which are needed to access a certain
 *  device.
 *
 *  \note
 *  <b>There always has to be at least one instance of the mvIMPACT::acquire::DeviceManager when
 *  the user still works with \b mvIMPACT::acquire::Device objects!</b> When the last instance to
 *  this object is destroyed all remaining \b mvIMPACT::acquire::Device objects will be closed
 *  automatically and every device driver will be unloaded from the current process memory!
 *
 *  If a device is installed in the system but an appropriate driver has not been installed, this class
 *  will \b NOT list these devices.
 *
 *  As a result of this every program written by the use of this interface
 *  will create an instance of \b mvIMPACT::acquire::DeviceManager before performing any other
 *  operations which uses objects or functions from this interface.
 *
 *  During the construction of a \b mvIMPACT::acquire::DeviceManager object the system will be scanned
 *  for supported devices and once the instance has been created the object will
 *  provide an up to date list of devices whenever the user asks for it. Some devices when plugged into
 *  the system after the device manager has been created might require an explicit update of the device
 *  list. This can be triggered by an application by calling \b mvIMPACT::acquire::DeviceManager::updateDeviceList().
 *  When there is currently no \b mvIMPACT::acquire::DeviceManager instance within the process creating
 *  the first one will result in all supported driver stacks to be loaded dynamically. See remarks below for
 *  consequences that result from this.
 *
 *  This class also provides various functions to find a particular device in the system.
 *  Devices can e.g. be found by family or by serial number.
 *
 * \attention
 *  \b NEVER try to explicitly delete an instance of \b mvIMPACT::acquire::Device! You did not allocate it
 *  and the result will be a crash! The \b mvIMPACT::acquire::DeviceManager will take care of all resources
 *  for you.
 *
 *  \note
 *  A \b mvIMPACT::acquire::DeviceManager object will initially return pointers to \b mvIMPACT::acquire::Device objects,
 *  which all seem to be closed. However one or more of the devices might have been opened
 *  by another instance of the device manager running in a different
 *  process. In that case the attempt to open a device, which seems to be closed will raise
 *  an exception with the error code \b mvIMPACT::acquire::DMR_DRV_ALREADY_IN_USE, which MUST
 *  be handled by the user.
 *
 * \attention
 *  \b NEVER declare a global instance of this class within a dynamic library(*.dll, *.so, *.ocx, ...), as creating
 *  this instance will result in other shared libraries to be loaded dynamically by the framework. If you do, applications
 *  using your library might lock up because global objects might be constructed from (Windows) the \c DllMain context
 *  and loading other libraries from within \c DllMain is discouraged (see <tt>DllMain Best Practices</tt> in MSDN for
 *  example). Instead either attach your instance of the device manager to a singleton, declare a global pointer that gets
 *  initialised/destroyed by custom library init/close functions or use any other approach that suits your needs.
 *
 *  \b EXAMPLE CODE:
 *
 *  \if DOXYGEN_CPP_DOCUMENTATION
 *  \code
 *  //-----------------------------------------------------------------------------
 *  void obtainDevicePointers( void )
 *  //-----------------------------------------------------------------------------
 *  {
 *    // Create an instance of the device manager to get access
 *    // to supported devices.
 *    DeviceManager devMgr;
 *
 *    // show all devices
 *    for( unsigned int i=0; i<devMgr.deviceCount(); i++ )
 *    {
 *      cout << "Dev " << i << ": " << *(devMgr[i]) << endl;
 *    }
 *
 *    // try to find a device using a special criteria
 *    // ( some of these calls will fail!!! )
 *    // will fail as the string is not complete and does
 *    // NOT terminate with a wildcard.
 *    Device* pDev = devMgr.getDeviceBySerial( "SD0*0" );
 *    // might work if there are at least two devices with
 *    // a matching serial number in the system.
 *    pDev = devMgr.getDeviceByFamily( "SD0*0*", 1 );
 *    // might work if there is at least one device whose type
 *    // specifying string starts with 'SampleDevi'.
 *    pDev = devMgr.getDeviceByProduct( "SampleDevi*" );
 *    // will fail as the string is not complete and does NOT
 *    // terminate with the user defined wildcard.
 *    pDev = devMgr.getDeviceByProduct( "SampleD*", 0, '$' );
 *    // will work if there is a device whose product name
 *    // starts with 'SamplePro' and which has
 *    // been assigned the specified device ID.
 *    pDev = devMgr.getDeviceByProductAndID( "SamplePro*", 66, '*' );
 *    // will work if there is a device whose product name
 *    // starts with 'SamplePro' and which has
 *    // been assigned the specified string device ID.
 *    pDev = devMgr.getDeviceByProductAndID( "SamplePro*","sampleID", '*' );
 *    // will work if there is at least one device with a serial
 *    // number starting with 'SD00' in the system.
 *    pDev = devMgr.getDeviceBySerial( "SD00*" );
 *    // will return a pointer to the first device detected thus
 *    // this call will work if there is at least one device in the
 *    // current system that is supported by this interface
 *    pDev = devMgr.getDeviceBySerial( "*" );
 *    if( !pDev )
 *    {
 *      cout << "Error! No valid device found" << endl;
 *      return 0;
 *    }
 *
 *    // from here it will be save to work with the pointer returned
 *    // by device manager.
 *    // THE NEXT LINE WILL TRY TO OPEN THE DEVICE! This can fail if the device
 *    // is already running in a different process!
 *    try
 *    {
 *      FunctionInterface func(pDev);
 *      // do some work
 *    }
 *    catch( const ImpactAcquireException& e )
 *    {
 *      // failed to open the device...
 *    }
 *  }
 *
 *  //-----------------------------------------------------------------------------
 *  void showDeviceManagerOperation( void )
 *  //-----------------------------------------------------------------------------
 *  {
 *    Device* pDev = 0;
 *    {
 *      DeviceManager devMgr1;
 *      // will return a pointer to the first device detected thus
 *      // this call will work if there is at least one device in the
 *      // current system that is supported by this interface
 *      pDev = devMgr.getDeviceBySerial( "*" );
 *      if( !pDev )
 *      {
 *        cout << "Error! No valid device found" << endl;
 *        return;
 *      }
 *      // from here it will be save to work with the pointer returned
 *      // by device manager.
 *      // THE NEXT LINE WILL TRY TO OPEN THE DEVICE! This can fail if the device
 *      // is already running in a different process!
 *      try
 *      {
 *        FunctionInterface func( pDev );
 *        // do some work
 *      }
 *      catch( const ImpactAcquireException& e )
 *      {
 *        // failed to open the device...
 *      }
 *      {
 *        DeviceManager devMgr2;
 *        // This will return the same device as pDev
 *        Device* pDev2 = devMgr2.getDeviceBySerial( "*" );
 *      } // here the device manager devMgr2 will be destroyed, but it will NOT close pDev2, as devMgr1 holds a reference to it
 *      Statistics s( pDev ); // this will still work
 *    } // here the last device manager will be destroyed, thus from here onwards pDev will be invalid!
 *    Info i( pDev ); // this will crash
 *    DeviceManager devMgr3;
 *    Info i2( devMgr3.getDevice( 0 ) ); // this will work again
 *  }
 *  \endcode
 *  \elseif DOXYGEN_JAVA_DOCUMENTATION
 *  \code
 *  //-----------------------------------------------------------------------------
 *  public static void showDeviceManagerOperation()
 *  //-----------------------------------------------------------------------------
 *  {
 *    Device pDev = null;
 *    {
 *      DeviceManager devMgr = new DeviceManager();
 *      // will return a pointer to the first device detected thus
 *      // this call will work if there is at least one device in the
 *      // current system that is supported by this interface
 *      pDev = devMgr.getDeviceBySerial( "*" );
 *      if( pDev == null )
 *      {
 *        System.out.print( "No valid device found!" );
 *        mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *        System.exit( 1 );
 *      }
 *
 *      // from here it will be save to work with the pointer returned
 *      // by device manager.
 *      // THE NEXT LINE WILL TRY TO OPEN THE DEVICE! This can fail if the device
 *      // is already running in a different process!
 *      try
 *      {
 *        FunctionInterface fi = new FunctionInterface( pDev );
 *        // do some work
 *      }
 *      catch( ImpactAcquireException e )
 *      {
 *        // this e.g. might happen if the same device is already opened in another process...
 *        System.out.println( "An error occurred while opening device " + pDev.getSerial().read() +
 *                            "(error code: " + e.getMessage() + ")." );
 *        System.exit( 1 );
 *      }
 *      {
 *        DeviceManager devMgr2 = new DeviceManager();
 *        // This will return the same device as pDev
 *        Device pDev2 = devMgr.getDeviceBySerial( "*" );
 *      }
 *      // after the next line the device manager devMgr2 will be destroyed, but it will NOT close pDev2, as devMgr holds a reference to it
 *      System.gc();
 *      Statistics s = new Statistics( pDev ); // this will still work
 *    }
 *  }
 *  \endcode
 *  \elseif DOXYGEN_PYTHON_DOCUMENTATION
 *  \code
 *  def obtainDeviceReferences():
 *      # Create an instance of the device manager to get access
 *      # to supported devices.
 *      devMgr = acquire.DeviceManager()
 *
 *      # show all devices
 *      for i in range(devMgr.deviceCount()):
 *          print("Dev " + str(i) + ": " + str(devMgr[i]))
 *
 *      # try to find a device using a special criteria
 *      # ( some of these calls will fail!!! )
 *      # will fail as the string is not complete and does
 *      # NOT terminate with a wildcard.
 *      pDev = devMgr.getDeviceBySerial("SD0*0")
 *      # might work if there are at least two devices with
 *      # a matching serial number in the system.
 *      pDev = devMgr.getDeviceByFamily("SD0*0*", 1)
 *      # might work if there is at least one device whose type
 *      # specifying string starts with 'SampleDevi'.
 *      pDev = devMgr.getDeviceByProduct("SampleDevi*")
 *      # will fail as the string is not complete and does NOT
 *      # terminate with the user defined wildcard.
 *      pDev = devMgr.getDeviceByProduct("SampleD*", 0, '$')
 *      # will work if there is a device whose product name
 *      # starts with 'SamplePro' and which has
 *      # been assigned the specified device ID.
 *      pDev = devMgr.getDeviceByProductAndID("SamplePro*", 66, '*')
 *      # will work if there is a device whose product name
 *      # starts with 'SamplePro' and which has
 *      # been assigned the specified string device ID.
 *      pDev = devMgr.getDeviceByProductAndID("SamplePro*","sampleID", '*')
 *      # will work if there is at least one device with a serial
 *      # number starting with 'SD00' in the system.
 *      pDev = devMgr.getDeviceBySerial("SD00*")
 *      # will return a pointer to the first device detected thus
 *      # this call will work if there is at least one device in the
 *      # current system that is supported by this interface
 *      pDev = devMgr.getDeviceBySerial("*")
 *      if not pDev:
 *          print("Error! No valid device found")
 *
 *      # from here it will be save to work with the pointer returned
 *      # by device manager.
 *      # THE NEXT LINE WILL TRY TO OPEN THE DEVICE! This can fail if the device
 *      # is already running in a different process!
 *      try:
 *          func = acquire.FunctionInterface(pDev);
 *          # do some work
 *      except Exception as e:
 *          # failed to open the device...
 *          print("failed to open the device...")
 *  \endcode
 *  \endif
 */
class DeviceManager
//-----------------------------------------------------------------------------
{
    typedef std::vector<Device*> DevVector;
    HDMR                    m_deviceBaseList;
    mutable DevVector       m_devVector;
    mutable unsigned int    m_lastChangedCounter;
    int*                    m_pRefCnt;
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        if( m_pRefCnt )
        {
            --( *m_pRefCnt );
            for( unsigned int i = 0; i < m_devVector.size(); i++ )
            {
                delete m_devVector[i];
            }
            m_devVector.clear();
            // free reference count memory if no one uses it anymore
            if( *m_pRefCnt == 0 )
            {
                delete m_pRefCnt;
                m_pRefCnt = 0;
            }
        }
    }
    //-----------------------------------------------------------------------------
    Device* getDevice( TDMR_DeviceSearchMode mode, const std::string& search_string, unsigned int devNr, char wildcard ) const
    //-----------------------------------------------------------------------------
    {
        updateInfoVector();
        Device* pResult = 0;
        HDEV device;
        if( DMR_GetDevice( &device, mode, search_string.c_str(), devNr, wildcard ) == DMR_NO_ERROR )
        {
            DevVector::size_type vSize = m_devVector.size();
            for( DevVector::size_type i = 0; i < vSize; i++ )
            {
                if( m_devVector[i]->hDev() == device )
                {
                    pResult = m_devVector[i];
                    break;
                }
            }
        }
        return pResult;
    }
    //-----------------------------------------------------------------------------
    Device* getDevice( TDMR_DeviceSearchMode mode, const std::string& search_string, const std::string& deviceID, char wildcard ) const
    //-----------------------------------------------------------------------------
    {
        updateInfoVector();
        Device* pResult = 0;
        HDEV device;
        if( DMR_GetDeviceWithStringID( &device, mode, search_string.c_str(), deviceID.c_str(), wildcard ) == DMR_NO_ERROR )
        {
            DevVector::size_type vSize = m_devVector.size();
            for( DevVector::size_type i = 0; i < vSize; i++ )
            {
                if( m_devVector[i]->hDev() == device )
                {
                    pResult = m_devVector[i];
                    break;
                }
            }
        }
        return pResult;
    }
    //-----------------------------------------------------------------------------
    bool updateInfoVector( void ) const
    //-----------------------------------------------------------------------------
    {
        Component iter( m_deviceBaseList );
        unsigned int changedCount = iter.changedCounter();
        if( m_lastChangedCounter == changedCount )
        {
            return false;
        }

        m_lastChangedCounter = changedCount;

        unsigned int curDevCnt = 0;
        DevVector::size_type vSize = m_devVector.size();
        DMR_GetDeviceCount( &curDevCnt );
        if( curDevCnt <= static_cast<unsigned int>( vSize ) )
        {
            return false;
        }

        HDEV hDev = INVALID_ID;
        for( DevVector::size_type i = vSize; i < curDevCnt; i++ )
        {
            DMR_GetDevice( &hDev, dmdsmSerial, "*", static_cast<unsigned int>( i ), '*' );
            if( hDev != INVALID_ID )
            {
                m_devVector.push_back( new Device( hDev ) );
            }
        }
        return true;
    }
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::DeviceManager object.
    /**
     *  If the construction of this object fails for some reason this constructor
     *  might throw an exception of type \b mvIMPACT::acquire::ImpactAcquireException or a type
     *  derived from this class.
     */
    explicit DeviceManager( void ) : m_deviceBaseList( INVALID_ID ), m_devVector(), m_lastChangedCounter( 0 ), m_pRefCnt( 0 )
    {
        TDMR_ERROR result;
        if( ( result = DMR_Init( &m_deviceBaseList ) ) != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        m_pRefCnt = new int();
        *m_pRefCnt = 1;
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::DeviceManager object from an existing one.
    /**
     *  If the construction of this object fails for some reason this constructor
     *  might throw an exception of type \b mvIMPACT::acquire::ImpactAcquireException or a type
     *  derived from this class.
     */
    DeviceManager( const DeviceManager& src ) : m_deviceBaseList( INVALID_ID ), m_devVector(), m_lastChangedCounter( 0 ), m_pRefCnt( src.m_pRefCnt )
    {
        // we don't need to copy data as the necessary updates are done anyway.
        // But we have to call the underlying C-API to achieve correct reference counting.
        TDMR_ERROR result;
        if( ( result = DMR_Init( &m_deviceBaseList ) ) != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        ++( *m_pRefCnt );
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::DeviceManager objects.
    DeviceManager& operator=( const DeviceManager& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefCnt = rhs.m_pRefCnt;
            // inc. the NEW reference count
            ++( *m_pRefCnt );
            // this will fill the device vector with up to date data the next time someone asks
            // for a device.
            m_lastChangedCounter = 0;
            m_devVector.clear();
        }
        return *this;
    }
    /// \brief Class destructor.
    /**
     *  There always has to be at least one instance of the \b DeviceManager when
     *  the user still works with \b mvIMPACT::acquire::Device objects, as when the last instance to
     *  this object is destroyed all remaining \b mvIMPACT::acquire::Device objects will be closed
     *  automatically!
     */
    virtual ~DeviceManager( void )
    {
        dealloc();
        DMR_Close();
    }
    /// \brief Returns a string containing the version number of the specified library.
    /**
     *  This function returns a string containing the version number of the specified library.
     *
     *  The format of the string will be MAJOR.MINOR.RELEASE.BUILD.
     *  \since 2.1.2
     *  \return A pointer to an internal version string.
     */
    static std::string getVersionAsString(
        /// [in] Specifies the library to query information from.
        TLibraryQuery libraryQuery )
    {
        return DMR_GetVersion( libraryQuery );
    }
#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
    /// \brief Returns the internal handle to the device manager created via \b DMR_Init().
    HDMR getInternalHandle( void ) const
    {
        return m_deviceBaseList;
    }
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS)
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::Device object.
    /**
     *  Returns a pointer to a \b mvIMPACT::acquire::Device object specifying the device found at the given
     *  index in the device managers internal list.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If the index is either equal or higher than the number of devices detected \n
     *  an STL out_of_range exception is thrown.
     *  \endif
     *
     *  \sa
     *  \b mvIMPACT::acquire::DeviceManager::deviceCount, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceBySerial, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByFamily, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByProduct
     *  \return
     *  - A pointer to the device if found.
     *  - an invalid pointer or reference otherwise.
     */
    Device* operator[](
        /// [in] The index of the device to be returned.
        unsigned int index ) const
    {
        return getDevice( index );
    }
    /// \brief Returns the current changed counter for the device list.
    /**
     *  This is a useful function to find out if the device list has been changed in any
     *  way. Such a change might be the appearance of a new USB device or a state change
     *  of any other device (e.g. when a USB device has been unplugged). Thus this function
     *  can be called periodically in order to maintain lists in GUI application for example.
     *  To find out the actual number of devices call \b mvIMPACT::acquire::DeviceManager::deviceCount.
     *  \return The current changed counter for the device list.
     */
    unsigned int changedCount( void ) const
    {
        return Component( m_deviceBaseList ).changedCounter();
    }
    /// \brief Returns the number of devices currently present in the system.
    /**
     *  This function returns the number of devices currently detected in the system. A
     *  device once connected to the system while the device manager was running will remain
     *  in its list even if it's unplugged (then only its state will change). To detect
     *  changes in the \b mvIMPACT::acquire::DeviceManager objects list call the function
     *  \b mvIMPACT::acquire::DeviceManager::changedCount.
     *  \return The number of devices detected in the current system.
     */
    unsigned int deviceCount( void ) const
    {
        updateInfoVector();
        return static_cast<unsigned int>( m_devVector.size() );
    }
    /// \brief Updates the internal device list.
    /**
     *  Most devices can't appear out of nowhere. For example a PCI device is
     *  either connected to the current system when the device manager is initialized
     *  or not but it will never appear at runtime after this instance of \b mvIMPACT::acquire::DeviceManager
     *  has been created.
     *
     *  However certain device classes (e.g. network devices) might be connected to
     *  the system \b AFTER the device manager has been initialized. Some will announce themselves
     *  like e.g. USB devices, which will send a message to every application interested while others
     *  like e.g. network devices wont. In order not to
     *  pollute the network or bus with constant rescan messages no polling is done inside the driver.
     *  the user should call this function instead when looking for new devices. This can either be done in reasonable intervals or after
     *  it is known that a new device has been connected to the system.
     *
     *  If new devices have been detected a subsequent call to \b mvIMPACT::acquire::DeviceManager::deviceCount
     *  will result in a higher value when compared to a previous call and \b mvIMPACT::acquire::DeviceManager::changedCount
     *  will contain a different value as well then (however this could also happen because a certain device related property did change
     *  its state).
     *
     *  \note
     *  As long as a certain instance of a device manager is active, the devices once detected will \b NOT
     *  disappear from the list of devices even if they have been unplugged from the system. So the list
     *  of devices can only grow, but never gets shorter again until either the process terminates or the
     *  last instance of this class went out of scope. If a device has been unplugged, its \b mvIMPACT::acquire::Device::state
     *  property will change. If the application is interested in getting an instant notification when a
     *  device has been disconnected a callback can be registered on this property.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  How to do this is explained here: \ref Callback.cpp
     *  \endif
     */
    void updateDeviceList( void ) const
    {
        TDMR_ERROR result = DMR_NO_ERROR;
        if( ( result = DMR_UpdateDeviceList( 0, 0 ) ) != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::Device object.
    /**
     *  Returns a pointer to a \b mvIMPACT::acquire::Device object specifying the device found at the given
     *  index in the device managers internal list.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If the index is either equal or higher than the number of devices detected
     *  an STL out_of_range exception will be thrown.
     *  \endif
     *
     *  \sa
     *  \b mvIMPACT::acquire::DeviceManager::deviceCount, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceBySerial, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByFamily, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByProduct
     *  \return
     *  - A pointer to the device if \a index specifies a valid value. \n
     *  - an exception will be raised otherwise.
     */
    Device* getDevice(
        /// [in] The index of the device to be returned.
        unsigned int index ) const
    {
        updateInfoVector();
        return m_devVector.at( index );
    }
    /// \brief Tries to locate a device via the serial number.
    /**
     *  This function tries to find a device by its serial number (or parts of this number).
     *  The user can specify only parts of the serial number and a wildcard. The \b mvIMPACT::acquire::DeviceManager
     *  object will then try to find that matches these parameters in its current list.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  DeviceManager devMgr;
     *  // this will return a pointer to the second device with
     *  // a serial number starting with 'SD' device found or 0
     *  // if there are no 2 sample devices in the system
     *  devMgr.getDeviceBySerial( "SD*******", 1, '*' );
     *  // will return a pointer to the device with the serial
     *  // number SD000001 if present or 0
     *  devMgr.getDeviceBySerial( "SD0000001" );
     *  // will return a pointer to the first device in the system
     *  devMgr.getDeviceBySerial( "*", 0, '*' );
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  DeviceManager devMgr = new DeviceManager();
     *  // this will return a pointer to the second device with
     *  // a serial number starting with 'SD' device found or 0
     *  // if there are no 2 sample devices in the system
     *  devMgr.getDeviceBySerial( "SD*******", 1, '*' );
     *  // will return a pointer to the device with the serial
     *  // number SD000001 if present or 0
     *  devMgr.getDeviceBySerial( "SD0000001" );
     *  // will return a pointer to the first device in the system
     *  devMgr.getDeviceBySerial( "*", 0, '*' );
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  devMgr = acquire.DeviceManager()
     *  # this will return a reference to the second device with
     *  # a serial number starting with 'SD' device found or 0
     *  # if there are no 2 sample devices in the system
     *  devMgr.getDeviceBySerial("SD*******", 1, '*')
     *  # will return a reference to the device with the serial
     *  # number SD000001 if present or 0
     *  devMgr.getDeviceBySerial("SD0000001")
     *  # will return a reference to the first device in the system
     *  devMgr.getDeviceBySerial("*", 0, '*')
     * \endcode
     * \endif
     *
     *  \sa
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByFamily, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByProduct, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByProductAndID
     *  \return
     *  - A pointer to the device if found. \n
     *  - an invalid pointer or reference otherwise.
     */
    Device* getDeviceBySerial(
        /// [in] The full serial number or the known parts of the serial number and wildcard characters.
        const std::string& serial = "",
        /// [in] The number of the device to return (if there is more than one candidate).
        unsigned int devNr = 0,
        /// [in] The character to ignore in \a serial.
        char wildcard = '*' ) const
    {
        return getDevice( dmdsmSerial, serial, devNr, wildcard );
    }
    /// \brief Tries to locate a device via the family name.
    /**
     *  This function tries to find a device by its family (or parts of this family name).
     *  The user can specify only parts of the family name and a wildcard. The \b mvIMPACT::acquire::DeviceManager
     *  object will then try to find the device that matches these parameters in its current list.
     *  The family is the most general method of searching for a device apart from 'any device'.
     *  E.g. for a device the family name might be 'SampleDevice'
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  DeviceManager devMgr;
     *  // this will return a pointer to the second 'SampleDevice'
     *  // device found or 0 if there are no 2 'SampleDevice'
     *  // devices in the system
     *  devMgr.getDeviceByFamily( "SampleD*", 1, '*' );
     *  // will return a pointer to the first device belonging
     *  // to the 'SampleDevice' family if present or 0.
     *  devMgr.getDeviceByFamily( "SampleDevice" );
     *  // will return the first recognized device in the system
     *  devMgr.getDeviceByFamily( "*", 0, '*' );
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  DeviceManager devMgr = new DeviceManager();
     *  // this will return a pointer to the second 'SampleDevice'
     *  // device found or 0 if there are no 2 'SampleDevice'
     *  // devices in the system
     *  devMgr.getDeviceByFamily( "SampleD*", 1, '*' );
     *  // will return a pointer to the first device belonging
     *  // to the 'SampleDevice' family if present or 0.
     *  devMgr.getDeviceByFamily( "SampleDevice" );
     *  // will return the first recognized device in the system
     *  devMgr.getDeviceByFamily( "*", 0, '*' );
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  devMgr = acquire.DeviceManager()
     *  # this will return a reference to the second 'SampleDevice'
     *  # device found or 0 if there are no 2 'SampleDevice'
     *  # devices in the system
     *  devMgr.getDeviceByFamily("SampleD*", 1, '*')
     *  # will return a reference to the first device belonging
     *  # to the 'SampleDevice' family if present or 0.
     *  devMgr.getDeviceByFamily("SampleDevice")
     *  # will return the first recognized device in the system
     *  devMgr.getDeviceByFamily("*", 0, '*')
     * \endcode
     * \endif
     *
     *  \sa
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceBySerial, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByProduct, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByProductAndID
     *  \return
     *  - A pointer to the device if found. \n
     *  - an invalid pointer or reference otherwise.
     */
    Device* getDeviceByFamily(
        /// [in] The full family name of the requested device or known parts of it and wildcard characters.
        const std::string& family = "",
        /// [in] The number of the device to return (if there is more than one candidate).
        unsigned int devNr = 0,
        /// [in] The character to ignore in \a family.
        char wildcard = '*' ) const
    {
        return getDevice( dmdsmFamily, family, devNr, wildcard );
    }
    /// \brief Tries to locate a device via the product name.
    /**
     *  This function tries to find a device by its product name (or parts of it).
     *  The user can specify only parts of the name and a wildcard. The \b mvIMPACT::acquire::DeviceManager
     *  object will then try to find the device that matches these parameters in its current list.
     *  The product name is a bit more specific than the family name, but less specific than
     *  the serial. For the 'SampleDevice' for example there might be different product names for different
     *  device types. This might e.g. be 'SampleDevice-G' for a grey version of the sample device and
     *  'SampleDevice-C' for the color version of the sample device.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  DeviceManager devMgr;
     *  // this will return a pointer to the second sample
     *  // device of type 'G' found or 0 if there aren't
     *  // two devices of this type in the system
     *  devMgr.getDeviceByProduct( "SampleDevice-G", 1 );
     *  // will return a pointer to the first device whose
     *  // product string starts with 'SampleDev' or 0 if
     *  // no such device can be found.
     *  devMgr.getDeviceByProduct( "SampleDev*", 0, '*' );
     *  // will return the first recognized device in the system
     *  devMgr.getDeviceByProduct( "*", 0, '*' );
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     *  DeviceManager devMgr = new DeviceManager();
     *  // this will return a pointer to the second sample
     *  // device of type 'G' found or 0 if there aren't
     *  // two devices of this type in the system
     *  devMgr.getDeviceByProduct( "SampleDevice-G", 1 );
     *  // will return a pointer to the first device whose
     *  // product string starts with 'SampleDev' or 0 if
     *  // no such device can be found.
     *  devMgr.getDeviceByProduct( "SampleDev*", 0, '*' );
     *  // will return the first recognized device in the system
     *  devMgr.getDeviceByProduct( "*", 0, '*' );
     * \code
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  devMgr = acquire.DeviceManager()
     *  # this will return a reference to the second sample
     *  # device of type 'G' found or 0 if there aren't
     *  # two devices of this type in the system
     *  devMgr.getDeviceByProduct("SampleDevice-G", 1)
     *  # will return a reference to the first device whose
     *  # product string starts with 'SampleDev' or 0 if
     *  # no such device can be found.
     *  devMgr.getDeviceByProduct("SampleDev*", 0, '*')
     *  # will return the first recognized device in the system
     *  devMgr.getDeviceByProduct("*", 0, '*')
     * \endcode
     * \endif
     *
     *  \sa
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceBySerial, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByFamily, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByProductAndID
     *  \return
     *  - A pointer to the device if found. \n
     *  - an invalid pointer or reference otherwise.
     */
    Device* getDeviceByProduct(
        /// [in] The full product name of the requested device or known parts of it and wildcard characters.
        const std::string& product = "",
        /// [in] The number of the device to return (if there is more than one candidate).
        unsigned int devNr = 0,
        /// [in] The character to ignore in \a product.
        char wildcard = '*' ) const
    {
        return getDevice( dmdsmProduct, product, devNr, wildcard );
    }
    /// \brief Tries to locate a device via the product name and the device ID.
    /**
     *  This function behaves like
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByProduct
     *  except that the second parameter now is interpreted as the device ID.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  DeviceManager devMgr;
     *  // this will return a pointer to the sample device of
     *  // type 'G' which has been assigned a device ID of '1'
     *  // or 0 if there is no sample device with this ID in the system.
     *  devMgr.getDeviceByProductAndID( "SampleDevice-G", 1 );
     *  // will return a pointer to the device whose product string
     *  // starts with 'SampleDev' and whose device ID has been set
     *  // to '0' or 0 if no such device can be found.
     *  devMgr.getDeviceByProductAndID( "SampleDev*", 0, '*' );
     *  // will return the first recognized device with an assigned
     *  // device ID of '0' in the system.
     *  devMgr.getDeviceByProductAndID( "*", 0 );
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  DeviceManager devMgr = new DeviceManager();
     *  // this will return a pointer to the sample device of
     *  // type 'G' which has been assigned a device ID of '1'
     *  // or 0 if there is no sample device with this ID in the system.
     *  devMgr.getDeviceByProductAndID( "SampleDevice-G", 1 );
     *  // will return a pointer to the device whose product string
     *  // starts with 'SampleDev' and whose device ID has been set
     *  // to '0' or 0 if no such device can be found.
     *  devMgr.getDeviceByProductAndID( "SampleDev*", 0, '*' );
     *  // will return the first recognized device with an assigned
     *  // device ID of '0' in the system.
     *  devMgr.getDeviceByProductAndID( "*", 0 );
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  devMgr = acquire.DeviceManager()
     *  # this will return a reference to the sample device of
     *  # type 'G' which has been assigned a device ID of '1'
     *  # or 0 if there is no sample device with this ID in the system.
     *  devMgr.getDeviceByProductAndID("SampleDevice-G", 1)
     *  # will return a reference to the device whose product string
     *  # starts with 'SampleDev' and whose device ID has been set
     *  # to '0' or 0 if no such device can be found.
     *  devMgr.getDeviceByProductAndID("SampleDev*", 0, '*')
     *  # will return the first recognized device with an assigned
     *  # device ID of '0' in the system.
     *  devMgr.getDeviceByProductAndID("*", 0)
     * \endcode
     * \endif
     *
     *  \sa
     *  \b mvIMPACT::acquire::Device::deviceID, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByFamily, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceByProduct, \n
     *  \b mvIMPACT::acquire::DeviceManager::getDeviceBySerial, \n
     *  \b mvIMPACT::acquire::Device::setID
     *  \return
     *  - A pointer to the device if found. \n
     *  - an invalid pointer or reference otherwise.
     */
    Device* getDeviceByProductAndID(
        /// [in] The full product name of the requested device or known parts of it and wildcard characters.
        const std::string& product = "",
        /// [in] The ID associated with this device.
        unsigned int devID = 0,
        /// [in] The character to ignore in \a product.
        char wildcard = '*' ) const
    {
        return getDevice( static_cast<TDMR_DeviceSearchMode>( dmdsmProduct | dmdsmUseDevID ), product, devID, wildcard );
    }
    /// \brief Tries to locate a device via the product name and the device ID.
    /**
    *  This function can be used to locate devices with a certain string identifier that has previously been written into a devices non-volatile
    *  memory. E.g. GenICam devices may support the \c DeviceUserID feature to assign a certain user defined name. A user defined
    *  name might be useful e.g. to access a device with a certain function without the need to worry about which device is it. You could
    *  e.g. have a \c barcodeReadingDevice and a \c monitorCamera.
    *  This function behaves like \b mvIMPACT::acquire::DeviceManager::getDeviceByProduct
    *  except that the second parameter now is interpreted as the device ID.
    *
    * \if DOXYGEN_CPP_DOCUMENTATION
    * \code
    *  DeviceManager devMgr;
    *  // this will return a pointer to the sample device of
    *  // type 'G' which has been assigned a device ID of 'abc'
    *  // or 0 if there is no sample device with this ID in the system.
    *  devMgr.getDeviceByProductAndID( "SampleDevice-G", "abc" );
    *  // will return a pointer to the device whose product string
    *  // starts with 'SampleDev' and whose device ID has been set
    *  // to 'def' or 0 if no such device can be found.
    *  devMgr.getDeviceByProductAndID( "SampleDev*", "def", '*' );
    *  // will return the first recognized device with an assigned
    *  // device ID of 'anyString' in the system.
    *  devMgr.getDeviceByProductAndID( "*", "anyString" );
    * \endcode
    * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
    *  DeviceManager devMgr = new DeviceManager();
    *  // this will return a pointer to the sample device of
    *  // type 'G' which has been assigned a device ID of 'abc'
    *  // or 0 if there is no sample device with this ID in the system.
    *  devMgr.getDeviceByProductAndID( "SampleDevice-G", "abc" );
    *  // will return a pointer to the device whose product string
    *  // starts with 'SampleDev' and whose device ID has been set
    *  // to 'def' or 0 if no such device can be found.
    *  devMgr.getDeviceByProductAndID( "SampleDev*", "def", '*' );
    *  // will return the first recognized device with an assigned
    *  // device ID of 'anyString' in the system.
    *  devMgr.getDeviceByProductAndID( "*", "anyString" );
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
    * \code
    *  devMgr = acquire.DeviceManager()
    *  # this will return a reference to the sample device of
    *  # type 'G' which has been assigned a device ID of 'abc'
    *  # or 0 if there is no sample device with this ID in the system.
    *  devMgr.getDeviceByProductAndID("SampleDevice-G", "abc")
    *  # will return a reference to the device whose product string
    *  # starts with 'SampleDev' and whose device ID has been set
    *  # to 'def' or 0 if no such device can be found.
    *  devMgr.getDeviceByProductAndID("SampleDev*", "def", '*')
    *  # will return the first recognized device with an assigned
    *  # device ID of 'anyString' in the system.
    *  devMgr.getDeviceByProductAndID("*", "anyString")
    * \endcode
    * \endif
    *
    *  \sa
    *  \b mvIMPACT::acquire::Device::deviceID, \n
    *  \b mvIMPACT::acquire::DeviceManager::getDeviceByFamily, \n
    *  \b mvIMPACT::acquire::DeviceManager::getDeviceByProduct, \n
    *  \b mvIMPACT::acquire::DeviceManager::getDeviceBySerial, \n
    *  \b mvIMPACT::acquire::Device::setID
    *  \return
    *  - A pointer to the device if found. \n
    *  - an invalid pointer or reference otherwise.
    */
    Device* getDeviceByProductAndID(
        /// [in] The full product name of the requested device or known parts of it and wildcard characters.
        const std::string& product,
        /// [in] The device ID associated with this device.
        const std::string& devID,
        /// [in] The character to ignore in \a product.
        char wildcard = '*' ) const
    {
        return getDevice( static_cast<TDMR_DeviceSearchMode>( dmdsmProduct | dmdsmUseDevID ), product, devID, wildcard );
    }
};

//-----------------------------------------------------------------------------
/// \brief Defines valid interface list types, which can be located using an instance of \b mvIMPACT::acquire::DeviceComponentLocator.
enum TDeviceListType
//-----------------------------------------------------------------------------
{
    /// \brief A placeholder for an undefined list type.
    dltUndefined = dmltUndefined,
    /// \brief Specifies a certain setting.
    /**
     *  An additional string defines the name of the setting to look for.
     */
    dltSetting = dmltSetting,
    /// \brief Specifies the list of driver owned image request objects.
    dltRequest = dmltRequest,
    /// \brief Specifies a certain image request control.
    /**
     *  An additional string defines the name of the setting to look for.
     */
    dltRequestCtrl = dmltRequestCtrl,
    /// \brief Specifies the driver interfaces list containing general information.
    /**
     *  This e.g. can be properties containing the driver version, the current state
     *  of the device and stuff like that.
     */
    dltInfo = dmltInfo,
    /// \brief Specifies the driver interface list containing statistical information.
    /**
     *  This list e.g. might contain the current frame rate, the total number of images
     *  captured, etc.
     */
    dltStatistics = dmltStatistics,
    /// \brief Specifies the driver interface list containing properties, which influence the overall operation of the device.
    /**
     *  This list e.g. might contain the priority of the drivers internal worker thread,
     *  the number of request objects the driver shall work with, etc.
     */
    dltSystemSettings = dmltSystemSettings,
    /// \brief Specifies the driver interface list containing properties to work with any kind of I/O pin belonging to that device.
    /**
     *  Here properties addressing the digital inputs and outputs and other I/O related
     *  properties can be found.
     */
    dltIOSubSystem = dmltIOSubSystem,
    ///  \brief Specifies the driver interface list providing access to the drivers <b>H</b>ardware <b>R</b>eal-<b>T</b>ime <b>C</b>ontroller (HRTC).
    /**
     *  Here properties to control the behaviour of the HRTCs can be found.
     *  \note
     *  This feature might not be available for every device.
     */
    dltRTCtr = dmltRTCtr,
    /// \brief Specifies the driver interface list providing access to the recognized camera description lists.
    /**
     *  Within this list all recognized camera descriptions can be found, each forming a sub list
     *  containing the properties describing the camera.
     *
     *  \note This feature is only available for frame grabber devices currently.
     */
    dltCameraDescriptions = dmltCameraDescriptions,
    /// \brief Specifies the driver interface list providing access to the device specific settings lists.
    /**
     *  \note This feature currently is only available for frame grabber devices.
     */
    dltDeviceSpecificData = dmltDeviceSpecificData,
    /// \brief Specifies the driver interface list providing access to the devices memory manager list.
    /**
     *  \note This feature currently is only available for frame grabber devices.
     *
     *  This list will contain properties and lists providing access to settings related to the memory
     *  handling used by the device. E.g. the buffer size for individual DMA blocks can be configured
     *  here.
     *
     *  \note
     *  Properties in this list should only be modified by advanced users.
     */
    dltImageMemoryManager = dmltImageMemoryManager,
#ifndef DOXYGEN_SHOULD_SKIP_THIS
    dltPseudoLast,
#endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
    /// \brief Defines the last entry in this enumeration.
    /**
     *  This is always equal to the last 'real' enum value.
     */
    dltLast = dltPseudoLast - 1
};

//-----------------------------------------------------------------------------
/// \brief A class to locate components within the driver.
/**
 *  Every driver will offer a set of properties, methods and component lists.
 *  \b mvIMPACT::acquire::Property objects contain data such as the current gain in dB, the state of a
 *  digital input, etc.. \b mvIMPACT::acquire::Method objects can be executed like a normal function and
 *  \b mvIMPACT::acquire::ComponentList objects are used to group certain
 *  objects together to form a logical unit.
 *
 *  When it's necessary to locate one or more of these objects without knowing
 *  exactly where to look for them this locator class can be used to look for the component.
 *
 *  In general the properties interesting for the user can be found in one of the
 *  classes offered by this interface, but when a special property is needed or a
 *  new property that hasn't been embedded into the C++ interface, this class offers
 *  a way to get hold of its handle.
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  // assuming a new property 'MyProp' has been added to the setting of a
 *  // device driver whose product string is 'MyDevice' and it has not been
 *  // added to the corresponding class or the property shall be accessed
 *  // without rebuilding the application.
 *  // The latter situation will require some kind of interpreter that
 *  // can pass the required information to the device driver
 *  //-----------------------------------------------------------------------------
 *  enum TMyEnumType
 *  //-----------------------------------------------------------------------------
 *  {
 *    metOne = 0,
 *    metTwo,
 *    metThree
 *  };
 *
 *  //-----------------------------------------------------------------------------
 *  void fn( void )
 *  //-----------------------------------------------------------------------------
 *  {
 *    DeviceManager devMgr;
 *    Device* pDev = devMgr.getDeviceByProduct( "MyDev*" );
 *    if( pDev )
 *    {
 *      // get access to the base setting
 *      DeviceComponentLocator locator( pDev, dltSetting, "Base" );
 *      Property prop;
 *      locator.bindComponent( prop, "MyProp" );
 *      // set the value by string
 *      prop.writeS( "MyVal" );
 *      if( prop.type() == ctPropInt )
 *      {
 *        PropertyI iProp( prop.hObj() );
 *        int myVal = 666;
 *        iProp.write( myVal );
 *      }
 *      // if the type is known this test can be omitted:
 *      PropertyF fProp;
 *      locator.bindComponent( fProp, "MyFloatProperty" );
 *      fProp.write( 3.14 );
 *
 *      // When it's an enumerated property this is legal as well:
 *      PropertyIMyEnumType eProp;
 *      locator.bindComponent( eProp, "MyEnumeratedProperty" );
 *      eProp.write( metOne );
 *    }
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  //-----------------------------------------------------------------------------
 *  public static void fn( void )
 *  //-----------------------------------------------------------------------------
 *  {
 *    DeviceManager devMgr = new DeviceManager();
 *    Device pDev = devMgr.getDeviceByProduct( "MyDev*" );
 *    if( pDev != null )
 *    {
 *      DeviceComponentLocator locator = new DeviceComponentLocator( pDev, TDeviceListType.dltSetting, "Base" );
 *      Property prop = new Property();
 *      locator.bindComponent( prop, "MyProp" );
 *      // set the value by string
 *      prop.writeS( "MyVal" );
 *      if( prop.type() == TComponentType.ctPropInt )
 *      {
 *        PropertyI iProp = new PropertyI( prop.hObj() );
 *        int myVal = 666;
 *        iProp.write( myVal );
 *      }
 *      // if the type is known this test can be omitted:
 *      PropertyF fProp = new PropertyF();
 *      locator.bindComponent( fProp, "MyFloatProperty" );
 *      fProp.write( 3.14 );
 *
 *      // When it's an enumerated property this is legal as well:
 *      PropertyI eProp = new PropertyI();
 *      locator.bindComponent( eProp, "MyBooleanProperty" );
 *      eProp.write( TBoolean.bTrue );
 *    }
 *  }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  devMgr = acquire.DeviceManager()
 *  pDev = devMgr.getDeviceByProduct("MyDev*")
 *  if pDev:
 *    # get access to the base setting
 *    locator = acquire.DeviceComponentLocator(pDev, dltSetting, "Base")
 *    prop = None
 *    locator.bindComponent(prop, "MyProp")
 *    # set the value by string
 *    prop.writeS("MyVal")
 *    if prop.type == ctPropInt:
 *      iProp = PropertyI(prop.hObj())
 *      myVal = 666
 *      iProp.write(myVal)
 *
 *    # if the type is known this test can be omitted:
 *    fProp = None
 *    locator.bindComponent(fProp, "MyFloatProperty")
 *    fProp.write(3.14)
 *
 *    # When it's an enumerated property this is legal as well:
 *    eProp = acquire.EnumPropertyI()
 *    locator.bindComponent(eProp, "MyEnumeratedProperty")
 *    # e.g. writing the devices interfaceLayout property using the TDeviceInterfaceLayout enum value
 *    eProp.write(acquire.dilGenICam)
 * \endcode
 * \endif
 *
 */
class DeviceComponentLocator : public ComponentLocatorBase
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new unbound locator.
    explicit DeviceComponentLocator() : ComponentLocatorBase() {}
    /// \brief Constructs a new bound to the specified base list locator.
    explicit DeviceComponentLocator(
        /// [in] A unique identifier to the base list from where to start to search for
        /// the search base.
        HLIST baselist ) : ComponentLocatorBase( baselist ) {}
    /// \brief Constructs a new locator and searches the search base list.
    explicit DeviceComponentLocator(
        /// [in] A unique identifier to the base list from where to start to search for
        /// the search base.
        HLIST baselist,
        /// [in] The name or path ('/' separated) to the search base.
        const std::string& pathToSearchBase ) : ComponentLocatorBase( baselist, pathToSearchBase ) {}
    /// \brief Constructs a new locator and bind the search base to the specified list type of the device.
    explicit DeviceComponentLocator(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from
        /// a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The type list to locate
        TDeviceListType deviceListType,
        /// [in] A string that can contain the name of the list if there
        /// is more than one candidate (e.g. when looking for settings)
        const std::string& sublistName = "" ) : ComponentLocatorBase()
    {
        bindSearchBaseList( pDev, deviceListType, sublistName );
    }
    /// \brief Assign a new search base to the locator.
    /**
     *  This new search base will be search starting from the base list specified.
     *  \return The unique identifier of the new search base.
     */
    HLIST bindSearchBaseList(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from
        /// a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The type list to locate
        TDeviceListType deviceListType,
        /// [in] The name or path to the search base.
        const std::string& sublistName = "" )
    {
        if( !pDev->isOpen() )
        {
            pDev->open();
        }

        HLIST hList;
        const TDMR_ERROR result = DMR_FindList( pDev->hDrv(), ( sublistName.length() == 0 ) ? 0 : sublistName.c_str(), static_cast<TDMR_ListType>( deviceListType ), 0, &hList );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        bindSearchBase( hList );
        return searchbase_id();
    }
};

//-----------------------------------------------------------------------------
/// \brief A wrapper class to handle \b mvIMPACT::acquire::ImageBuffer structures.
/**
 *  This class acts as a simple wrapper to handle \b mvIMPACT::acquire::ImageBuffer structures.
 *  When using this class the user is no longer responsible for the memory management
 *  of \b mvIMPACT::acquire::ImageBuffer structures.
 *
 *  Instances of this class are reference counted. Memory is freed once the last instance
 *  to it is destroyed. For details read the corresponding sections in the documentation
 *  of the various constructors and function belonging to this class.
 */
class ImageBufferDesc
//-----------------------------------------------------------------------------
{
#if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    friend class Request;
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        int             m_refCnt;
        bool            m_boBufferAllocated;
        ImageBuffer*    m_pBuffer;
        explicit ReferenceCountedData( bool boAllocated = false, ImageBuffer* pBuffer = 0 )
            : m_refCnt( 1 ), m_boBufferAllocated( boAllocated ), m_pBuffer( pBuffer ) {}
        ~ReferenceCountedData()
        {
            if( m_pBuffer )
            {
                if( m_boBufferAllocated )
                {
                    DMR_ReleaseImageBuffer( &m_pBuffer );
                }
                else
                {
                    DMR_ReleaseImageRequestBufferDesc( &m_pBuffer );
                }
            }
        }
        // make sure there are NO assignments or copy constructions by accident!
        ReferenceCountedData& operator=( const ReferenceCountedData& rhs );
        ReferenceCountedData( const ReferenceCountedData& src );
    }* m_pRefData;
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    explicit ImageBufferDesc( bool boAllocated, ImageBuffer* pBuf ) : m_pRefData( new ImageBufferDesc::ReferenceCountedData( boAllocated, pBuf ) ) {}
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::ImageBufferDesc from an existing one.
    /**
     *  The image buffer associated with this descriptor will not be copied! The internal
     *  data will be reference counted and changing this new object will also affect the
     *  original one. The internal data is freed when the last descriptor referencing the
     *  image is destroyed.
     */
    ImageBufferDesc(
        /// [in] The source buffer descriptor.
        const ImageBufferDesc& source ) : m_pRefData( source.m_pRefData )
    {
        ++( m_pRefData->m_refCnt );
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::ImageBufferDesc object with \a channelCount channel specific data elements.
    /**
     *  This constructor does \b NOT allocate memory for the actual pixel data but only for the
     *  a structure describing an image.
     *
     *  When passing invalid values to this constructor (e.g. a negative value for \c channelCount) an
     *  exception will be thrown.
     */
    explicit ImageBufferDesc(
        /// [in] The number of channel specific data elements to allocate
        /// memory for.
        int channelCount ) : m_pRefData( new ImageBufferDesc::ReferenceCountedData() )
    {
        const TDMR_ERROR result = DMR_AllocImageRequestBufferDesc( &( m_pRefData->m_pBuffer ), channelCount );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::ImageBufferDesc object and allocates all memory needed.
    /**
     *  This constructor will allocate and handle a new and complete \b ImageBuffer object including
     *  memory for the pixel data for the given pixel format.
     *
     *  The size(in bytes) of allocated pixel memory will depend on the \a pixelFormat as well as on the
     *  parameters \a width and \a height. \b mvIMPACT::acquire::ImageBuffer::iSize will return the
     *  amount of memory allocated for the buffer.
     *
     *  When passing invalid values to this constructor (e.g. a negative value for \c height) an
     *  exception will be thrown.
     */
    explicit ImageBufferDesc(
        /// [in] The desired pixel format for the new \b mvIMPACT::acquire::ImageBuffer
        /// object handled by this descriptor.
        TImageBufferPixelFormat pixelFormat,
        /// [in] The width of the new \b mvIMPACT::acquire::ImageBuffer object handled
        /// by this descriptor.
        int width,
        /// [in] The height of the new \b mvIMPACT::acquire::ImageBuffer object handled
        /// by this descriptor.
        int height ) : m_pRefData( new ImageBufferDesc::ReferenceCountedData( true ) )
    {
        const TDMR_ERROR result = DMR_AllocImageBuffer( &( m_pRefData->m_pBuffer ), pixelFormat, width, height );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::ImageBufferDesc object from a file and allocates all memory needed.
    /**
     *  This constructor will allocate and handle a new and complete \b ImageBuffer object including
     *  memory for the pixel data for the given pixel format. The buffer will be filled with the
     *  data from the file referenced by \c fileName.
     *
     *  \note
     *  Internally The FreeImage library (see 'legal notice' section) is used for this operation. If the library
     *  cannot be located in version 3.16.0 on the host system calling this constructor will fail and an
     *  exception will be thrown.
     *
     * \since 2.23.0
     */
    explicit ImageBufferDesc(
        /// [in] The name of the file to load.
        const std::string& fileName,
        /// [in] The format of the file to load.
        TImageFileFormat fileFormat = iffAuto ) : m_pRefData( new ImageBufferDesc::ReferenceCountedData( true ) )
    {
        const TDMR_ERROR result = DMR_LoadImageBuffer( &( m_pRefData->m_pBuffer ), fileName.c_str(), fileFormat );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
    }
    /// \brief De-allocates all managed memory again when this is the last object referencing the image.
    ~ImageBufferDesc()
    {
        dealloc();
    }
    /// \brief Allows assignments of two different \b mvIMPACT::acquire::ImageBufferDesc.
    /**
     *  The image buffer associated with this descriptor will not be copied! The internal
     *  data will be reference counted and changing this new object will also affect the
     *  original one. The internal data is freed when the last descriptor referencing the
     *  image is destroyed.
     */
    ImageBufferDesc& operator=( const ImageBufferDesc& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            ++( m_pRefData->m_refCnt );
        }
        return *this;
    }
    /// \brief Returns a deep copy of the \b mvIMPACT::acquire::ImageBuffer object referenced by this descriptor.
    /**
     *  This function will create a deep copy of the \b mvIMPACT::acquire::ImageBuffer object referenced by this
     *  descriptor. Afterwards modifying one of the images will \b NOT influence the other one.
     *
     *  \return A deep copy of the \b mvIMPACT::acquire::ImageBuffer object referenced by this descriptor.
     */
    ImageBufferDesc clone( void ) const
    {
        ImageBuffer* pDst = 0;
        DMR_CopyImageBuffer( m_pRefData->m_pBuffer, &pDst, 0 );
        return ImageBufferDesc( true, pDst );
    }
#ifdef PYTHON_OR_JAVA_ONLY // This function is only needed e.g. to copy into managed Java memory
    /// \brief Returns a deep copy of the data buffer of the underlying \b mvIMPACT::acquire::ImageBuffer object referenced by this descriptor.
    /**
     *  This function will create a deep copy of the data buffer of the \b mvIMPACT::acquire::ImageBuffer object referenced by this
     *  descriptor. Afterwards modifying one of the buffers will \b NOT influence the other one.
     *
     * \since 2.36.0
     *  \return The buffer size needed for \c pDst if \c dstSize was too small or the size used if the operation was successful.
     */
    int copy(
        /// A pointer to the buffer to copy the data into. Can be 0 if just the size needed shall be queried.
        char* pDst,
        /// The size of the buffer pointed to by \c pDst. Is 'don't care' if just the size needed shall be queried.
        const int dstSize ) const
    {
        const int sizeNeeded = getBuffer()->iSize;
        if( dstSize < sizeNeeded )
        {
            return sizeNeeded;
        }
        if( pDst )
        {
            memcpy( pDst, static_cast<char*>( getBuffer()->vpData ), sizeNeeded );
        }
        return sizeNeeded;
    }
#endif // #ifdef PYTHON_OR_JAVA_ONLY
    /// \brief Grants access to the underlying \b mvIMPACT::acquire::ImageBuffer structure managed by this object.
    /**
     *  \return A pointer to the \b mvIMPACT::acquire::ImageBuffer object referenced by this descriptor.
     */
    ImageBuffer* getBuffer( void ) const
    {
        return m_pRefData ? m_pRefData->m_pBuffer : 0;
    }
    /// \brief Stores the complete data of one <b>ImageBuffer</b> structure into a file.
    /**
     *  This function stores the image described by a <b>mvIMPACT::acquire::ImageBuffer</b> structure pointed to by the \c pBuffer variable
     *  into a file.
     *
     *  \note
     *  Internally The FreeImage library (see 'legal notice' section) is used for this operation. If the library
     *  cannot be located in version 3.16.0 on the host system calling this function will fail.
     *
     * \since 2.23.0
     *  \return
     *  - <b>mvIMPACT::acquire::DMR_NO_ERROR</b> if successful.
     *  - <b>mvIMPACT::acquire::DMR_LIBRARY_NOT_FOUND</b> if the required version of the FreeImage library could not be located on the host system.
     *  - <b>mvIMPACT::acquire::DEV_UNSUPPORTED_PARAMETER</b> if a pixel format has been passed to the function that is not supported by the internal algorithms.
     *  - <b>mvIMPACT::acquire::DEV_INPUT_PARAM_INVALID</b> if a pixel format has been passed to the function that is not supported by the FreeImage library.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int save(
        /// [in] The full path of the file to create.
        const std::string& fileName,
        /// [in] The format of the file to be created. If this parameter is set to <b>mvIMPACT::acquire::iffAuto</b> make sure to specify a proper file extension.
        TImageFileFormat format = iffAuto ) const
    {
        return DMR_SaveImageBuffer( m_pRefData->m_pBuffer, fileName.c_str(), format );
    }
};

//-----------------------------------------------------------------------------
/// \brief A base class for sets of properties that can be modified by the user.
class ComponentCollection
//-----------------------------------------------------------------------------
{
protected:
    HOBJ m_hRoot;
    explicit ComponentCollection() : m_hRoot( INVALID_ID ) {}
    explicit ComponentCollection( HOBJ hRoot ) : m_hRoot( hRoot ) {}
    explicit ComponentCollection( Device* pDev ) : m_hRoot( INVALID_ID )
    {
        if( !pDev->isOpen() )
        {
            pDev->open();
        }
    }
public:
    virtual ~ComponentCollection() {}
    /// \brief Returns a unique identifier for the component collection referenced by this object.
    /**
     *  This handle will always reference an object of type \b mvIMPACT::acquire::ComponentList.
     *  \return A unique identifier for the component referenced by this object.
     */
    HOBJ hObj( void ) const
    {
        return m_hRoot;
    }
    /// \brief Restores the default for every component of this collection.
    /**
     *  Calling this function will restore the default value for every component
     *  belonging to this collection.
     *
     *  \note The caller must have the right to modify the component. Otherwise
     *  an exception will be thrown.
     *
     *  \return A const reference to the component.
     */
    const ComponentCollection& restoreDefault( void ) const
    {
        const TPROPHANDLING_ERROR result = OBJ_RestoreDefault( m_hRoot );
        if( result != PROPHANDLING_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, m_hRoot );
        }
        return *this;
    }
};

//-----------------------------------------------------------------------------
/// \brief Contains information about a specific part of a captured buffer.
/**
 *  This class provides access to all sorts of information about a specific part of a captured buffer.
 *  Only Instances of \b mvIMPACT::acquire::Request are allowed to create objects of \b mvIMPACT::acquire::BufferPart.
 *  Consequently the only way to get access to a \b mvIMPACT::acquire::BufferPart object is via a call to
 *  \b mvIMPACT::acquire::Request::getBufferPart.
 *
 * \sa
 * \ref ImageAcquisition_MultiPart
 * \since 2.20.0
 */
class BufferPart : public ComponentCollection
//-----------------------------------------------------------------------------
{
    // only Request objects can create these objects, as these objects are
    // fixed parts of that class.
    friend class Request;
    mutable ImageBufferDesc m_imageBufferDesc;
    Component m_firstSibling;
    explicit BufferPart( HOBJ hObj ): ComponentCollection( hObj ), m_imageBufferDesc( 1 ), m_firstSibling(), address(), dataSize(), dataType(),
        pixelFormat(), width(), height(), offsetX(), offsetY(), paddingX(), bytesPerPixel(), bayerMosaicParity(),
        channelCount(), channelDesc(), pixelPitch(), linePitch(), channelBitDepth(), channelOffset(), sourceID(), regionID(), groupID()
    {
        bindPublicProperties( hObj );
    }
    void bindPublicProperties( HOBJ hObj )
    {
        ComponentLocator locator( hObj );
        locator.bindComponent( address, "Address" );
        if( address.isValid() )
        {
            m_firstSibling = address.firstSibling();
        }
        locator.bindComponent( dataSize, "DataSize" );
        locator.bindComponent( dataType, "DataType" );
        locator.bindComponent( pixelFormat, "PixelFormat" );
        locator.bindComponent( width, "Width" );
        locator.bindComponent( height, "Height" );
        locator.bindComponent( offsetX, "OffsetX" );
        locator.bindComponent( offsetY, "OffsetY" );
        locator.bindComponent( paddingX, "PaddingX" );
        locator.bindComponent( bytesPerPixel, "BytesPerPixel" );
        locator.bindComponent( bayerMosaicParity, "BayerMosaicParity" );
        locator.bindComponent( channelCount, "ChannelCount" );
        locator.bindComponent( channelDesc, "ChannelDesc" );
        locator.bindComponent( pixelPitch, "PixelPitch" );
        locator.bindComponent( linePitch, "LinePitch" );
        locator.bindComponent( channelBitDepth, "ChannelBitDepth" );
        locator.bindComponent( channelOffset, "ChannelOffset" );
        locator.bindComponent( sourceID, "SourceID" );
        locator.bindComponent( regionID, "RegionID" );
        locator.bindComponent( groupID, "GroupID" );
    }
public:
    /// \brief Returns a const reference to the image buffer descriptor of this buffer part.
    /**
     *  This function returns a const reference to the \b mvIMPACT::acquire::ImageBufferDesc associated
     *  with this \b mvIMPACT::acquire::BufferPart.
     *
     *  \attention
     *  Please do \b NEVER work with old references to this structure. So do \b NOT store this reference in
     *  some variable to use it for the evaluation of the next \b mvIMPACT::acquire::BufferPart object as well,
     *  as this will not work. Whenever \b mvIMPACT::acquire::BufferPart::getImageBufferDesc is called the function
     *  will make sure that the data in the returned structure is up to date while when working with
     *  an old reference to the \b mvIMPACT::acquire::ImageBufferDesc structure the containing data might refer
     *  to a previous result or even worse invalid memory locations. This reference will remain valid until an
     *  application calls \b mvIMPACT::acquire::Request::unlock for the corresponding request.
     */
    const ImageBufferDesc& getImageBufferDesc( void ) const
    {
        ImageBufferDesc tmp( static_cast<int>( channelCount.read() ) );
        ImageBuffer* p = tmp.getBuffer();
        p->iBytesPerPixel = static_cast<int>( bytesPerPixel.read() );
        p->iHeight = static_cast<int>( height.read() );
        p->iSize = static_cast<int>( dataSize.read() );
        p->iWidth = static_cast<int>( width.read() );
        p->pixelFormat = static_cast<TImageBufferPixelFormat>( pixelFormat.read() );
        p->vpData = address.read();
        std::vector<int64_type> channelOffsets;
        channelOffset.read( channelOffsets );
        std::vector<int64_type> linePitches;
        linePitch.read( linePitches );
        std::vector<int64_type> pixelPitches;
        pixelPitch.read( pixelPitches );
        std::vector<std::string> channelDescriptors;
        channelDesc.read( channelDescriptors );
        for( int i = 0; i < p->iChannelCount; i++ )
        {
            p->pChannels[i].iChannelOffset = static_cast<int>( channelOffsets[i] );
            p->pChannels[i].iLinePitch = static_cast<int>( linePitches[i] );
            p->pChannels[i].iPixelPitch = static_cast<int>( pixelPitches[i] );
            mv_strncpy_s( p->pChannels[i].szChannelDesc, channelDescriptors[i].c_str(), DEFAULT_STRING_SIZE_LIMIT - 1 );
            p->pChannels[i].szChannelDesc[DEFAULT_STRING_SIZE_LIMIT - 1] = '\0';
        }
        m_imageBufferDesc = tmp;
        return m_imageBufferDesc;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief A pointer property \b (read-only) containing the start address of this buffer part.
    /**
     * See remarks under <b>mvIMPACT::acquire::Request::imageData</b>. Most of the information provided there
     * will be valid for this property as well.
     */
    PropertyPtr address;
    /// \brief A 64-bit integer property \b (read-only) containing the size (in bytes) of this buffer part.
    /**
     * See remarks under <b>mvIMPACT::acquire::Request::imageData</b>. Most of the information provided there
     * will be valid for this property as well.
     */
    PropertyI64 dataSize;
    /// \brief An enumerated 64-bit integer property \b (read-only) containing the data type of this buffer part.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBufferPartDataType.
     */
    PropertyI64BufferPartDataType dataType;
    /// \brief An enumerated integer property defining the pixel format of this buffer part.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TImageBufferPixelFormat.
     */
    PropertyIImageBufferPixelFormat pixelFormat;
    /// \brief A 64-bit integer property \b (read-only) containing the width of the buffer part in pixels.
    PropertyI64 width;
    /// \brief A 64-bit integer property \b (read-only) containing the height of the buffer part in pixels.
    PropertyI64 height;
    /// \brief A 64-bit integer property \b (read-only) containing the X-offset of the buffer part in pixels.
    PropertyI64 offsetX;
    /// \brief A 64-bit integer property \b (read-only) containing the Y-offset of the buffer part in pixels.
    PropertyI64 offsetY;
    /// \brief A 64-bit integer property \b (read-only) containing the number of padding bytes in X direction of the buffer part.
    PropertyI64 paddingX;
    /// \brief A 64-bit integer property \b (read-only) containing the number of bytes per pixel in this buffer part.
    PropertyI64 bytesPerPixel;
    /// \brief An enumerated 64-bit integer property \b (read-only) containing the Bayer parity of this buffer part.
    /**
     *  If the current buffer part does not contain Bayer data, this value will be \b mvIMPACT::acquire::bmpUndefined.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBayerMosaicParity.
     */
    PropertyIBayerMosaicParity bayerMosaicParity;
    /// \brief A 64-bit integer property \b (read-only) containing the number of channels this buffer part consists of.
    /**
     *  For an RGB image this value e.g. would be 3. This value also defines how many parameters are stored by the properties
     *  \b mvIMPACT::acquire::BufferPart::pixelPitch, \n
     *  \b mvIMPACT::acquire::BufferPart::linePitch, \n
     *  \b mvIMPACT::acquire::BufferPart::channelBitDepth, \n
     *  \b mvIMPACT::acquire::BufferPart::channelDesc and \n
     *  \b mvIMPACT::acquire::BufferPart::channelOffset.
     *
     *  If e.g. the channel count is 3 a call like bufferPart.channelOffset.read( 2 ) would return the channel offset of
     *  channel 3 (as calls to the read functions of properties are '0' based).
     */
    PropertyI64 channelCount;
    /// \brief A string property \b (read-only) containing the string descriptors of each channel belonging to the current buffer part.
    /**
     * See remarks under <b>mvIMPACT::acquire::Request::imageChannelDesc</b>. Most of the information provided there
     * will be valid for this property as well.
     */
    PropertyS channelDesc;
    /// \brief A 64-bit integer property \b (read-only) containing the offset (in bytes) to the next pixel of the specified channel of this buffer part.
    /**
     *  \note
     *  This property will store \a channelCount values. These can be queried one by one using the \a index parameter of the function
     *  \b mvIMPACT::acquire::PropertyI64::read() or in a single call by using the overloaded \a read function accepting a reference to a
     *  vector.
     */
    PropertyI64 pixelPitch;
    /// \brief A 64-bit integer property \b (read-only) containing the offset (in bytes) to the next line of each channel belonging to the current buffer part.
    /**
     *  \note
     *  This property will store \a channelCount values. These can be queried one by one using the \a index parameter of the function
     *  \b mvIMPACT::acquire::PropertyI64::read() or in a single call by using the overloaded \a read function accepting a reference to a
     *  vector.
     */
    PropertyI64 linePitch;
    /// \brief A 64-bit integer property \b (read-only) containing the number of effective bits stored in each channel belonging to the current buffer part.
    /**
     *  \note
     *  This property will store \a channelCount values. These can be queried one by one using the \a index parameter of the function
     *  \b mvIMPACT::acquire::PropertyI64::read() or in a single call by using the overloaded \a read function accepting a reference to a
     *  vector.
     */
    PropertyI64 channelBitDepth;
    /// \brief A 64-bit integer property \b (read-only) containing the offset (in bytes) to each channel belonging to the current buffer part relative to the address contained in \b mvIMPACT::acquire::BufferPart::address.
    /**
     * \note
     * This property will store \a channelCount values. These can be queried one by one using the \a index parameter of the function
     * \b mvIMPACT::acquire::PropertyI64::read() or in a single call by using the overloaded \a read function accepting a reference to a
     * vector.
     */
    PropertyI64 channelOffset;
    /// \brief Identifier allowing to group data parts belonging to the same source (usually corresponding with the SourceSelector/ChunkSourceID features from SFNC).
    /**
     * Parts marked with the same source_id can be pixel mapped together. Parts carrying data from different ROI's of the same source would typically be marked with the
     * same source_id. It is not mandatory that source_id's within a given buffer make a contiguous sequence of numbers starting with zero.
     * \note
     * For example with a dual-source 3D camera, the buffer can contain data parts carrying the 3D data and Confidence data corresponding to both
     * of the two different sources. In this case the source ID helps to match the 3D and Confidence parts belonging together.
     */
    PropertyI64 sourceID;
    /// \brief Identifier allowing to group data parts belonging to the same region (usually corresponding with the RegionSelector/ChunkRegionID features from SFNC).
    /**
     * Parts marked with the same region_id can be pixel mapped together. Parts carrying data from different ROI's of the same source would typically be marked with the
     * same source_id but with different region_ids.
     *
     * \since 2.50.0
     */
    PropertyI64 regionID;
    /// \brief Identifier allowing to group data parts having the same purpose (usually corresponding with the ComponentSelector feature from SFNC).
    /**
     * \since 2.50.0
     */
    PropertyI64 groupID;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief Contains information about a captured buffer.
/**
 *  This class provides access to all sorts of information about the captured buffer.
 *  Only Instances of \b mvIMPACT::acquire::FunctionInterface are allowed to create objects of \b mvIMPACT::acquire::Request.
 *  Consequently the only way to get access to a \b mvIMPACT::acquire::Request object is via a call to
 *  \b mvIMPACT::acquire::FunctionInterface::getRequest.
 *
 *  A \b mvIMPACT::acquire::Request represents an object used by the driver to fill its internal job
 *  queues. Whenever a buffer shall be captured a \b mvIMPACT::acquire::Request is sent to the driver
 *  and the hardware then tries to capture the desired buffer as fast as possible.
 *
 *  Requests are managed by the driver. The only thing the user needs to configure is the
 *  maximum number of requests he wants the driver to work with. To make sure a
 *  certain number of requests are available, the property
 *  \b mvIMPACT::acquire::SystemSettings::requestCount can be used.
 *  This can be useful for time critical applications where the hardware can capture
 *  images in the background while the PC performs other tasks. In that case it's
 *  necessary to make sure that the request queue never runs low to ensure lossless
 *  data acquisition.
 */
class Request
//-----------------------------------------------------------------------------
{
    // only the function interface object is allowed to create new requests as
    // it maintains an internal reference to each request created.
    friend class FunctionInterface;
    typedef std::vector<BufferPart*> BufferPartContainer;
protected:
#if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        std::string                 m_requestName;
        int                         m_requestNr;
        mutable ImageBufferDesc     m_imageBufferDesc;
        Device*                     m_pDev;
        DeviceComponentLocator      m_locator;
        Component                   m_bufferPartIterator;
        Component                   m_infoIterator;
        Component                   m_info_imageProcessingResultsIterator;
        mutable BufferPartContainer m_bufferParts;
        std::vector<PropertyI64*>   m_chunkCounterValues;
        std::vector<PropertyF*>     m_chunkTimerValues;
        std::vector<PropertyF*>     m_chunkGains;
        std::map<std::string, unsigned int> m_chunkGainString2IndexMap;
        unsigned int                m_refCnt;
#ifdef COMPILE_PYTHON
        Py_buffer                   m_pythonUserBuffer;
#endif // #ifdef COMPILE_PYTHON
        explicit ReferenceCountedData( Device* pDev, int requestNr ) : m_requestName(), m_requestNr( requestNr ), m_imageBufferDesc( 1 ), m_pDev( pDev ),
            m_locator(), m_bufferPartIterator(), m_infoIterator(), m_info_imageProcessingResultsIterator(), m_bufferParts(), m_chunkCounterValues(), m_chunkTimerValues(), m_chunkGains(), m_chunkGainString2IndexMap(), m_refCnt( 1 )
#ifdef COMPILE_PYTHON
            , m_pythonUserBuffer()
#endif // #ifdef COMPILE_PYTHON
        {
#ifdef COMPILE_PYTHON
            m_pythonUserBuffer.buf = NULL;
#endif // #ifdef COMPILE_PYTHON
            if( m_requestNr >= 0 )
            {
                std::ostringstream oss;
                oss << "Entry " << m_requestNr;
                m_requestName = oss.str();
                m_locator = DeviceComponentLocator( m_pDev, dltRequest, m_requestName );
            }
            else
            {
                m_locator = DeviceComponentLocator( m_pDev, dltInfo, "CurrentRequestLayout" );
            }
            HLIST hList = m_locator.findComponent( "BufferParts" );
            if( hList != INVALID_ID )
            {
                // this driver offers multi-part buffer support
                m_bufferPartIterator = Component( hList );
            }
        }
        ~ReferenceCountedData()
        {
            const BufferPartContainer::size_type bufferPartsCnt = m_bufferParts.size();
            for( BufferPartContainer::size_type h = 0; h < bufferPartsCnt; h++ )
            {
                delete m_bufferParts[h];
            }
            const std::vector<PropertyI64*>::size_type cntcc = m_chunkCounterValues.size();
            for( std::vector<PropertyI64*>::size_type i = 0; i < cntcc; i++ )
            {
                delete m_chunkCounterValues[i];
            }
            const std::vector<PropertyF*>::size_type cntct = m_chunkTimerValues.size();
            for( std::vector<PropertyF*>::size_type j = 0; j < cntct; j++ )
            {
                delete m_chunkTimerValues[j];
            }
            const std::vector<PropertyF*>::size_type cntcg = m_chunkGains.size();
            for( std::vector<PropertyF*>::size_type k = 0; k < cntcg; k++ )
            {
                delete m_chunkGains[k];
            }
#ifdef COMPILE_PYTHON
            releasePythonBufferIfNeeded();
#endif // #ifdef COMPILE_PYTHON
        }
        // make sure there are NO assignments or copy constructions by accident!
        ReferenceCountedData( const ReferenceCountedData& src );
        ReferenceCountedData& operator=( const ReferenceCountedData& rhs );
        void collectChunkFeatures( Component it )
        {
            while( it.isValid() )
            {
                switch( it.type() )
                {
                case ctList:
                    collectChunkFeatures( it.firstChild() );
                    break;
                case ctPropInt64:
                    {
                        const std::string name( it.name() );
                        if( ( name == "ChunkCounterValue" ) || ( name == "ChunkCounter" ) ) // the latter name is the one that became deprecated with GenICam SFNC 1.5
                        {
                            m_chunkCounterValues.push_back( new PropertyI64( it.hObj() ) );
                        }
                    }
                    break;
                case ctPropFloat:
                    {
                        const std::string name( it.name() );
                        if( ( name == "ChunkTimerValue" ) || ( name == "ChunkTimer" ) ) // the latter name is the one that became deprecated with GenICam SFNC 1.5
                        {
                            m_chunkTimerValues.push_back( new PropertyF( it.hObj() ) );
                        }
                        else if( name == "ChunkGain" )
                        {
                            m_chunkGains.push_back( new PropertyF( it.hObj() ) );
                            std::string parentName( it.parent().name() );
                            if( parentName.find( "Gain" ) == 0 )
                            {
                                // remove the 'Gain' to get the original string from the selector the user would expect!
                                parentName = parentName.substr( 4 );
                            }
                            m_chunkGainString2IndexMap.insert( std::make_pair( parentName, static_cast<unsigned int>( m_chunkGains.size() - 1 ) ) );
                        }
                    }
                    break;
                default:
                    break;
                }
                ++it;
            }
        }
        void collectSelectedChunkFeatures( Component it )
        {
            if( m_chunkCounterValues.empty() && m_chunkTimerValues.empty() && m_chunkGains.empty() )
            {
                collectChunkFeatures( it );
            }
        }
#ifdef COMPILE_PYTHON
        void releasePythonBufferIfNeeded( void )
        {
            if( m_pythonUserBuffer.buf != NULL )
            {
                PyBuffer_Release( &m_pythonUserBuffer );
                m_pythonUserBuffer.buf = NULL;
            }
        }
#endif // #ifdef COMPILE_PYTHON
    }* m_pRefData;
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
private:
    //-----------------------------------------------------------------------------
    void bindPublicProperties( void )
    //-----------------------------------------------------------------------------
    {
        DeviceComponentLocator locator( getComponentLocator() );
        locator.bindComponent( requestResult, "Result" );
        locator.bindComponent( requestState, "State" );
        locator.bindSearchBase( locator.searchbase_id(), "Info" );
        m_pRefData->m_infoIterator = Component( locator.searchbase_id() );
        m_pRefData->m_infoIterator = m_pRefData->m_infoIterator.firstChild();
        locator.bindComponent( infoFrameID, "FrameID" );
        locator.bindComponent( infoFrameNr, "FrameNr" );
        locator.bindComponent( infoExposeStart_us, "ExposeStart_us" );
        locator.bindComponent( infoExposeTime_us, "ExposeTime_us" );
        locator.bindComponent( infoTransferDelay_us, "TransferDelay_us" );
        locator.bindComponent( infoGain_dB, "Gain_dB" );
        locator.bindComponent( infoTimeStamp_us, "TimeStamp_us" );
        locator.bindComponent( infoSettingUsed, "SettingUsed" );
        locator.bindComponent( infoImageAverage, "ImageAverage" );
        locator.bindComponent( infoVideoChannel, "VideoChannel" );
        locator.bindComponent( infoCameraOutputUsed, "CameraOutputUsed" );
        locator.bindComponent( infoLineCounter, "LineCounter" );
        locator.bindComponent( infoMissingData_pc, "MissingData_pc" );
        locator.bindComponent( infoIOStatesAtExposureStart, "IOStatesAtExposureStart" );
        locator.bindComponent( infoIOStatesAtExposureEnd, "IOStatesAtExposureEnd" );
        HLIST hList = locator.findComponent( "ChunkData" );
        if( hList != INVALID_ID )
        {
            ComponentLocator chunkFeatureLocator( hList );
            chunkFeatureLocator.bindComponent( chunkOffsetX, "ChunkOffsetX" );
            chunkFeatureLocator.bindComponent( chunkOffsetY, "ChunkOffsetY" );
            chunkFeatureLocator.bindComponent( chunkWidth, "ChunkWidth" );
            chunkFeatureLocator.bindComponent( chunkHeight, "ChunkHeight" );
            chunkFeatureLocator.bindComponent( chunkPixelFormat, "ChunkPixelFormat" );
            chunkFeatureLocator.bindComponent( chunkDynamicRangeMin, "ChunkDynamicRangeMin" );
            chunkFeatureLocator.bindComponent( chunkDynamicRangeMax, "ChunkDynamicRangeMax" );
            chunkFeatureLocator.bindComponent( chunkExposureTime, "ChunkExposureTime" );
            chunkFeatureLocator.bindComponent( chunkTimestamp, "ChunkTimestamp" );
            chunkFeatureLocator.bindComponent( chunkLineStatusAll, "ChunkLineStatusAll" );
            chunkFeatureLocator.bindComponent( chunkSequencerSetActive, "ChunkSequencerSetActive" );
            chunkFeatureLocator.bindComponent( chunkmvCustomIdentifier, "ChunkmvCustomIdentifier" );
            m_pRefData->collectSelectedChunkFeatures( Component( hList ).firstChild() );
        }
        hList = locator.findComponent( "ImageProcessingResults" );
        if( hList != INVALID_ID )
        {
            m_pRefData->m_info_imageProcessingResultsIterator = Component( hList ).firstChild();
        }
        locator.bindSearchBase( locator.hObj(), "Image" );
        locator.bindComponent( imageMemoryMode, "MemoryMode" );
        locator.bindComponent( imagePixelFormat, "PixelFormat" );
        locator.bindComponent( imageData, "Data" );
        locator.bindComponent( imageSize, "Size" );
        locator.bindComponent( imageFooter, "Footer" );
        locator.bindComponent( imageFooterSize, "FooterSize" );
        locator.bindComponent( imagePixelPitch, "PixelPitch" );
        locator.bindComponent( imageChannelCount, "ChannelCount" );
        locator.bindComponent( imageChannelOffset, "ChannelOffset" );
        locator.bindComponent( imageChannelBitDepth, "ChannelBitDepth" );
        locator.bindComponent( imageLinePitch, "LinePitch" );
        locator.bindComponent( imageChannelDesc, "ChannelDesc" );
        locator.bindComponent( imageBytesPerPixel, "BytesPerPixel" );
        locator.bindComponent( imageOffsetX, "OffsetX" );
        locator.bindComponent( imageOffsetY, "OffsetY" );
        locator.bindComponent( imageWidth, "Width" );
        locator.bindComponent( imageWidthTotal, "WidthTotal" );
        locator.bindComponent( imageHeight, "Height" );
        locator.bindComponent( imageHeightTotal, "HeightTotal" );
        locator.bindComponent( imageBayerMosaicParity, "BayerMosaicParity" );
    }
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    //-----------------------------------------------------------------------------
    void updateBufferParts( void ) const
    //-----------------------------------------------------------------------------
    {
        if( m_pRefData->m_bufferPartIterator.isValid() )
        {
            unsigned int bufferPartCount = 0;
            Component it( m_pRefData->m_bufferPartIterator.firstChild() );
            while( it.isValid() )
            {
                if( bufferPartCount >= m_pRefData->m_bufferParts.size() )
                {
                    // add new buffer parts
                    m_pRefData->m_bufferParts.push_back( new BufferPart( it.hObj() ) );
                }
                else
                {
                    BufferPart* pBufferPart = m_pRefData->m_bufferParts[bufferPartCount];
                    bool boMustUpdate = pBufferPart->hObj() != it.hObj();
                    if( !boMustUpdate )
                    {
                        // even if the list handle remained the same, the handles of the features inside it might have different handles now!
                        boMustUpdate = ( pBufferPart->m_firstSibling.hObj() != it.firstChild().hObj() ) || !pBufferPart->m_firstSibling.isValid();
                    }
                    if( boMustUpdate )
                    {
                        // update existing ones if necessary
                        pBufferPart->bindPublicProperties( it.hObj() );
                    }
                }
                ++bufferPartCount;
                ++it;
            }
            const BufferPartContainer::size_type bufferPartObjectCount = m_pRefData->m_bufferParts.size();
            if( bufferPartCount < bufferPartObjectCount )
            {
                // delete all buffer parts that are no longer part of the buffer
                for( size_t i = bufferPartCount; i < bufferPartObjectCount; i++ )
                {
                    delete m_pRefData->m_bufferParts[i];
                }
                m_pRefData->m_bufferParts.resize( bufferPartCount );
            }
        }
    }
protected:
    explicit Request( Device* pDev, int requestNr ) : m_pRefData( new ReferenceCountedData( pDev, requestNr ) ),
        requestResult(), requestState(),
        infoFrameID(), infoFrameNr(), infoExposeStart_us(),
        infoExposeTime_us(), infoTransferDelay_us(), infoGain_dB(),
        infoTimeStamp_us(), infoSettingUsed(), infoImageAverage(),
        infoVideoChannel(), infoCameraOutputUsed(), infoLineCounter(),
        infoMissingData_pc(), infoIOStatesAtExposureStart(), infoIOStatesAtExposureEnd(),
        chunkOffsetX(), chunkOffsetY(), chunkWidth(), chunkHeight(), chunkPixelFormat(), chunkDynamicRangeMin(),
        chunkDynamicRangeMax(), chunkExposureTime(), chunkTimestamp(), chunkLineStatusAll(), chunkSequencerSetActive(), chunkmvCustomIdentifier(),
        imageMemoryMode(), imagePixelFormat(), imageData(), imageSize(), imageFooter(), imageFooterSize(),
        imagePixelPitch(), imageChannelCount(), imageChannelOffset(), imageChannelBitDepth(), imageLinePitch(),
        imageChannelDesc(), imageBytesPerPixel(), imageOffsetX(), imageOffsetY(), imageWidth(),
        imageWidthTotal(), imageHeight(), imageHeightTotal(), imageBayerMosaicParity()
    {
        bindPublicProperties();
    }
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::Request from an existing one.
    Request(
        /// [in] A constant reference to the \b mvIMPACT::acquire::Request object, this object shall be created from
        const Request& src ) : m_pRefData( src.m_pRefData ),
        requestResult( src.requestResult ), requestState( src.requestState ),
        infoFrameID( src.infoFrameID ), infoFrameNr( src.infoFrameNr ), infoExposeStart_us( src.infoExposeStart_us ),
        infoExposeTime_us( src.infoExposeTime_us ), infoTransferDelay_us( src.infoTransferDelay_us ), infoGain_dB( src.infoGain_dB ),
        infoTimeStamp_us( src.infoTimeStamp_us ), infoSettingUsed( src.infoSettingUsed ), infoImageAverage( src.infoImageAverage ),
        infoVideoChannel( src.infoVideoChannel ), infoCameraOutputUsed( src.infoCameraOutputUsed ), infoLineCounter( src.infoLineCounter ),
        infoMissingData_pc( src.infoMissingData_pc ), infoIOStatesAtExposureStart( src.infoIOStatesAtExposureStart ),
        infoIOStatesAtExposureEnd( src.infoIOStatesAtExposureEnd ),
        chunkOffsetX( src.chunkOffsetX ), chunkOffsetY( src.chunkOffsetY ), chunkWidth( src.chunkWidth ), chunkHeight( src.chunkHeight ),
        chunkPixelFormat( src.chunkPixelFormat ), chunkDynamicRangeMin( src.chunkDynamicRangeMin ), chunkDynamicRangeMax( src.chunkDynamicRangeMax ),
        chunkExposureTime( src.chunkExposureTime ), chunkTimestamp( src.chunkTimestamp ), chunkLineStatusAll( src.chunkLineStatusAll ),
        chunkSequencerSetActive( src.chunkSequencerSetActive ), chunkmvCustomIdentifier( src.chunkmvCustomIdentifier ),
        imageMemoryMode( src.imageMemoryMode ), imagePixelFormat( src.imagePixelFormat ),
        imageData( src.imageData ), imageSize( src.imageSize ), imageFooter( src.imageFooter ), imageFooterSize( src.imageFooterSize ),
        imagePixelPitch( src.imagePixelPitch ), imageChannelCount( src.imageChannelCount ), imageChannelOffset( src.imageChannelOffset ),
        imageChannelBitDepth( src.imageChannelBitDepth ), imageLinePitch( src.imageLinePitch ), imageChannelDesc( src.imageChannelDesc ),
        imageBytesPerPixel( src.imageBytesPerPixel ), imageOffsetX( src.imageOffsetX ), imageOffsetY( src.imageOffsetY ), imageWidth( src.imageWidth ),
        imageWidthTotal( src.imageWidthTotal ), imageHeight( src.imageHeight ), imageHeightTotal( src.imageHeightTotal ), imageBayerMosaicParity( src.imageBayerMosaicParity )
    {
        ++( m_pRefData->m_refCnt );
    }
    virtual ~Request()
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::Request objects.
    Request& operator=( const Request& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            // inc. the NEW reference count
            ++m_pRefData->m_refCnt;
            bindPublicProperties();
        }
        return *this;
    }
    /// \brief Returns a component locator for this request.
    /**
     * This will allow to write custom feature bind operations.
     *
     *  \since 1.12.68
     * \return A component locator for this request.
     */
    DeviceComponentLocator getComponentLocator( void ) const
    {
        return m_pRefData->m_locator;
    }
    /// \brief Returns the number of buffer parts currently associated with this request.
    /**
     * Certain device drivers are able to deliver multiple buffer part within a single request object.
     * \sa
     * \ref ImageAcquisition_MultiPart
     * \since 2.20.0
     * \return The number of buffer parts currently associated with this request. This might be zero in case the device
     * driver delivers a \c standard data stream. It might also be 1 for special data formats such as JPEG, which must be handled
     * differently from an image describing properties perspective.
     */
    unsigned int getBufferPartCount( void ) const
    {
        updateBufferParts();
        return static_cast<unsigned int>( m_pRefData->m_bufferParts.size() );
    }
    /// \brief Returns a reference to a buffer part descriptor of this request.
    /**
     *  This function returns a reference to a \b mvIMPACT::acquire::BufferPart at index \c index associated
     *  with this \b mvIMPACT::acquire::Request.
     *
     *  \attention
     *  Please do \b NEVER work with old references to this class. So do \b NOT store this reference in
     *  some variable to use it for the evaluation of the next \b mvIMPACT::acquire::Request object as well,
     *  as this might not work because the buffer layout might have changed. Whenever \b mvIMPACT::acquire::Request::getBufferPart
     *  is called the function will make sure that the data in the returned structure is up to date while when working with
     *  an old reference to the \b mvIMPACT::acquire::BufferPart structure the containing data might refer
     *  to a previous result or worse an invalid memory location. This reference will remain valid until an
     *  application calls \b mvIMPACT::acquire::Request::unlock for the corresponding request.
     *
     * \sa
     * \b mvIMPACT::acquire::Request::getBufferPartCount \n
     * \ref ImageAcquisition_MultiPart
     *
     * \since 2.20.0
     * \return A reference to the buffer part defined by \c index
     */
    BufferPart& getBufferPart(
        /// [in] The index of the buffer part to return
        unsigned int index ) const
    {
        updateBufferParts();
        return *( m_pRefData->m_bufferParts.at( index ) );
    }
#ifdef COMPILE_PYTHON
    /// \brief Returns the Python user memory buffer associated with this request.
    /**
     * \attention
     * This buffer is managed automatically. Manual modification \b will lead to undefined behavior,
     * including Python interpreter crashes.
     */
    Py_buffer* getPythonUserBuffer( void )
    {
        return &m_pRefData->m_pythonUserBuffer;
    }
    /// \brief Releases the Python user memory buffer associated with this request.
    /**
     * \attention
     * Releasing the buffer while the request is capturing to user memory \b will lead to undefined behavior.
     */
    void releasePythonUserBufferIfNeeded( void )
    {
        m_pRefData->releasePythonBufferIfNeeded();
    }
#endif // #ifdef COMPILE_PYTHON
    /// \brief Returns the name associated with this request.
    /**
     * \since 2.32.0
     */
    const std::string& getName( void ) const
    {
        return m_pRefData->m_requestName;
    }
    /// \brief Returns the number associated with this request.
    int getNumber( void ) const
    {
        return m_pRefData->m_requestNr;
    }
    /// \brief Returns a const reference to the image buffer descriptor of this request.
    /**
     *  This function returns a const reference to the \b mvIMPACT::acquire::ImageBufferDesc associated
     *  with this \b mvIMPACT::acquire::Request.
     *
     *  \attention
     *  Please do \b NEVER work with old references to this structure. So do \b NOT store this reference in
     *  some variable to use it for the evaluation of the next \b mvIMPACT::acquire::Request object as well,
     *  as this will not work. Whenever \b mvIMPACT::acquire::Request::getImageBufferDesc is called the function
     *  will make sure that the data in the returned structure is up to date while when working with
     *  an old reference to the \b mvIMPACT::acquire::ImageBufferDesc structure the containing data might refer
     *  to a previous result.
     */
    const ImageBufferDesc& getImageBufferDesc( void ) const
    {
        const TDMR_ERROR result = DMR_GetImageRequestBuffer( m_pRefData->m_pDev->hDrv(), m_pRefData->m_requestNr, &( m_pRefData->m_imageBufferDesc.m_pRefData->m_pBuffer ) );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        return m_pRefData->m_imageBufferDesc;
    }
#if defined(MVIMPACT_H_) || defined(DOXYGEN_CPP_DOCUMENTATION)
    /// \brief Returns an mvIMPACT image buffer representation of the image associated with this request.
    /**
     *  \attention
     *  This function is slow, as it performs a copy of the
     *  image data. So using this function will not affect the actual image data from the
     *  device when modifying the image object.
     *
     *  \note
     *  This function is provided for backward compatibility only. New applications should use
     *  the overloaded function accepting a parameter of type \b mvIMPACT::acquire::TImpactBufferFlag.
     *  This function might be faster and provides the user with more control over the way the image
     *  is constructed. However if the \a new function is used also a new driver has to be deployed
     *  on every target system running software compiled with this interface. At least version
     *  1.3.5 of the mvDeviceManager-lib.
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  \attention
     *  This function will only be available if \a mvIMPACT.h has been included before including this interface!
     *  \endif
     */
    mvIMPACT::Image getIMPACTImage( void ) const
    {
        mvIMPACT_C::IPL_BUFHANDLE hBuf = IPL_DONT_CARE;
        const TDMR_ERROR result = DMR_GetImpactRequestBufferEx( m_pRefData->m_pDev->hDrv(), m_pRefData->m_requestNr, &hBuf, TImpactBufferFlag( 0 ), 0 );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        return mvIMPACT::Image::imageFactory( hBuf );
    }
    /// \brief Returns an mvIMPACT image buffer representation of the image associated with this request.
    /**
     *  \note
     *  This function might be fast depending on the \a flags parameter or might behave like
     *  \b mvIMPACT::acquire::Request::getIMPACTImage.
     *
     *  Valid values for \a flags are defined by the enumeration \b mvIMPACT::acquire::TImpactBufferFlag.
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  \attention
     *  This function will only be available if \a mvIMPACT.h has been included before including this interface!
     *  \endif
     */
    mvIMPACT::Image getIMPACTImage(
        /// [in] Flags defining how the buffer is created and behaves.
        TImpactBufferFlag flags ) const
    {
        mvIMPACT_C::IPL_BUFHANDLE hBuf = IPL_DONT_CARE;
        const TDMR_ERROR result = DMR_GetImpactRequestBufferEx( m_pRefData->m_pDev->hDrv(), m_pRefData->m_requestNr, &hBuf, flags, 0 );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, INVALID_ID );
        }
        return mvIMPACT::Image::imageFactory( hBuf );
    }
#endif // #if defined(MVIMPACT_H_) || defined(DOXYGEN_CPP_DOCUMENTATION)
    /// \brief Returns an iterator for iterating inside the info list of the request.
    /**
     *  This can be useful when custom or device specific information has been attached to the request
     *  object that wasn't known at compile time.
     *
     * It allows to write code like this:
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT::acquire::FunctionInterface,
     *  // 'nr' is assumed to be a valid request number returned from a previous call to
     *  // mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor()
     *  const Request* pRequest = fi.getRequest( nr );
     *  if( pRequest )
     *  {
     *    Component it(pRequest->getInfoIterator());
     *    std::map<std::string, std::string> m;
     *    while( it.isValid() )
     *    {
     *      // collect all entries that are properties and store their current name and value in a map
     *      if( it.isProp() && it.isVisible() )
     *      {
     *        Property prop( it );
     *        m.insert( std::make_pair( prop.name(), prop.readS() ) );
     *      }
     *      ++it;
     *    }
     *    // Here you can work with the information you just obtained
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  import java.util.Hashtable;
     *
     *  // ...
     *
     *  Component it = pRequest.getInfoIterator();
     *  Hashtable<String, String> m = new Hashtable<String, String>();
     *  while( it.isValid() )
     *  {
     *    // collect all entries that are properties and store their current name and value in a hash table
     *    if( it.isProp() && it.isVisible() )
     *    {
     *      Property prop = new Property( it.hObj() );
     *      m.put( prop.name(), prop.readS() );
     *    }
     *    it = it.nextSibling();
     *  }
     *  // Here you can work with the information you just obtained
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  # 'fi' is assumed to be a valid instance of acquire.FunctionInterface,
     *  # 'nr' is assumed to be a valid request number returned from a previous call to
     *  # acquire.FunctionInterface.imageRequestWaitFor()
     *  pRequest = fi.getRequest(requestNr)
     *  if pRequest:
     *      it = pRequest.getInfoIterator()
     *      props = {None:None}
     *      while it.isValid:
     *          if it.isProp and it.isVisible:
     *              prop = acquire.Property(it.hObj())
     *              props[prop.name()] = prop.readS()
     *          it = it.nextSibling()
     *      # Here you can work with the information you just obtained
     * \endcode
     * \endif
     * \return
     * An iterator for iterating inside the info list of the request.
     */
    Component getInfoIterator( void ) const
    {
        return m_pRefData->m_infoIterator;
    }
    /// \brief Returns an iterator for iterating inside the info/imageProcessingResults list of the request.
    /**
     *  This can be useful when custom or device specific algorithms have been applied to the request
     *  object that weren't known at compile time.
     *
     *  For a code example please refer to the documentation of \b mvIMPACT::acquire::Request::getInfoIterator
     *  \sa
     *  \b mvIMPACT::acquire::Request::getInfoIterator \n
     *
     * \since 2.14.0
     *
     * \return
     * An iterator for iterating inside the info/imageProcessingResults list of the request.
     */
    Component getImageProcessingResultsIterator( void ) const
    {
        return m_pRefData->m_info_imageProcessingResultsIterator;
    }
    /// \brief Checks if image processing that was set up for this request has been skipped for performance reasons.
    /**
     *  If \b mvIMPACT::acquire::Device::userControlledImageProcessingEnable is set to \b mvIMPACT::acquire::bTrue and
     *  \b mvIMPACT::acquire::SystemSettings::imageProcessingMode is set to  \b mvIMPACT::acquire::ipmProcessLatestOnly
     *  this function can be used to check if at least one algorithm has been skipped because of a lack of processing time.
     *  \sa
     *  \b mvIMPACT::acquire::Device::userControlledImageProcessingEnable, \n
     *  \b mvIMPACT::acquire::SystemSettings::imageProcessingMode \n
     *
     *  \since 2.14.0
     *
     *  \return
     *  - true if at least one internal algorithm has been skipped.
     *  - false otherwise.
     */
    bool hasProcessingBeenSkipped( void ) const
    {
        if( !m_pRefData->m_info_imageProcessingResultsIterator.isValid() )
        {
            return false;
        }

        Component it( m_pRefData->m_info_imageProcessingResultsIterator );
        while( it.isValid() )
        {
            if( PropertyIImageProcessingResult( it.hObj() ).read() == iprSkipped )
            {
                return true;
            }
            ++it;
        }

        return false;
    }
    /// \brief Returns the number of counter values that can be returned as part of the additional data of the buffer containing the request data.
    /**
     *  A device may support a large number of counters even though just a few of them or none is configured
     *  for counting. In such a case situation when switching on the transmission of the counter values
     *  at the time of the internal frame start event will allow to access the number of counters returned
     *  by this function but then the data in these counters of course will be meaningless.
     *
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     *
     *  \since 2.0.15
     *  \return
     *  The number of counter values that can be returned as part of the additional data of the buffer containing the request data.
     */
    unsigned int getChunkCounterCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_chunkCounterValues.size() );
    }
    /// \brief Returns a 64 bit integer property \b (read-only) defining the selected counter value at the time of the internal frame start event for this request.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a index is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     *
     *  \since 2.0.15
     */
    PropertyI64 getChunkCounterValue(
        /// [in] The index of the counter to return
        unsigned int index ) const
    {
        return PropertyI64( m_pRefData->m_chunkCounterValues.at( index )->hObj() );
    }
    /// \brief Returns the number of timer values that can be returned as part of the additional data of the buffer containing the request data.
    /**
     *  A device may support a large number of timers even though just a few of them or none is configured
     *  to run. In such a case situation when switching on the transmission of the timer values
     *  at the time of the internal frame start event will allow to access the number of timers returned
     *  by this function but then the data in these timers of course will be meaningless.
     *
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     *
     *  \since 2.0.15
     */
    unsigned int getChunkTimerCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_chunkTimerValues.size() );
    }
    /// \brief Returns a floating point property \b (read-only) defining the selected timer value at the time of the internal frame start event for this request.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a index is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     *
     *  \since 2.0.15
     */
    PropertyF getChunkTimerValue(
        /// [in] The index of the timer to return
        unsigned int index ) const
    {
        return PropertyF( m_pRefData->m_chunkTimerValues.at( index )->hObj() );
    }
    /// \brief Returns the number of gain values that can be returned as part of the additional data of the buffer containing the request data.
    /**
     *  A device may support a large number of gains even though just a few of them or none is configured
     *  to run. In such a case situation when switching on the transmission of the gain values
     *  at the time of the internal frame start event will allow to access the number of gains returned
     *  by this function but then the data in these gains of course will be meaningless.
     *
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     *
     *  \since 2.17.3
     */
    unsigned int getChunkGainCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_chunkGains.size() );
    }
    /// \brief Returns a floating point property \b (read-only) defining the selected gain value at the time of the internal frame start event for this request.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a index is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     *
     *  \since 2.17.3
     */
    PropertyF getChunkGain(
        /// [in] The index of the gain to return
        unsigned int index ) const
    {
        return PropertyF( m_pRefData->m_chunkGains.at( index )->hObj() );
    }
    /// \brief Returns a floating point property \b (read-only) defining the selected gain value at the time of the internal frame start event for this request.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a name is invalid(not a valid gain to select) a <b>mvIMPACT::acquire::EInvalidInputParameter</b> exception
     *  will be thrown.
     *  \endif
     *
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     *
     *  \since 2.17.3
     */
    PropertyF getChunkGain(
        /// [in] The name of the gain to return (as selected by <b>mvIMPACT::acquire::GenICam::AnalogControl::gainSelector</b>)
        const std::string& name ) const
    {
        std::map<std::string, unsigned int>::const_iterator it = m_pRefData->m_chunkGainString2IndexMap.find( name );
        if( it == m_pRefData->m_chunkGainString2IndexMap.end() )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, PROPHANDLING_INVALID_INPUT_PARAMETER, INVALID_ID );
        }
        return getChunkGain( it->second );
    }
    /// \brief Convenience function to check if a request has been processed successfully.
    /**
     * This is just a nicer way of checking the value of the \a requestResult property.
     * It allows to write code like this:
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT::acquire::FunctionInterface,
     *  // 'nr' is assumed to be a valid request number returned from a previous call to
     *  // mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor()
     *  const Request* pRequest = fi.getRequest( nr );
     *  if( pRequest->isOK() )
     *  {
     *    // do something
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT::acquire::FunctionInterface,
     *  // 'nr' is assumed to be a valid request number returned from a previous call to
     *  // mvIMPACT.acquire.FunctionInterface.imageRequestWaitFor()
     *  Request pRequest = fi.getRequest( nr );
     *  if( pRequest.isOK() )
     *  {
     *    // do something
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  # 'fi' is assumed to be a valid instance of acquire.FunctionInterface,
     *  # 'nr' is assumed to be a valid request number returned from a previous call to
     *  # acquire.FunctionInterface.imageRequestWaitFor()
     *  pRequest = fi.getRequest(nr)
     *  if pRequest.isOK:
     *    # do something
     * \endcode
     * \endif
     *
     * Instead if this:
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT::acquire::FunctionInterface,
     *  // 'nr' is assumed to be a valid request number returned from a previous call to
     *  // mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor()
     *  const Request* pRequest = fi.getRequest( nr );
     *  if( pRequest->requestResult.read() == rrOK )
     *  {
     *    // do something
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT::acquire::FunctionInterface,
     *  // 'nr' is assumed to be a valid request number returned from a previous call to
     *  // mvIMPACT.acquire.FunctionInterface.imageRequestWaitFor()
     *  Request pRequest = fi.getRequest( nr );
     *  if( pRequest.getRequestResult().read() == TRequestResult.rrOK )
     *  {
     *    // do something
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  # 'fi' is assumed to be a valid instance of acquire.FunctionInterface,
     *  # 'nr' is assumed to be a valid request number returned from a previous call to
     *  # acquire.FunctionInterface.imageRequestWaitFor()
     *  pRequest = fi.getRequest(nr)
     *  if(pRequest.requestResult.read() == acquire.rrOK):
     *    # do something
     * \endcode
     * \endif
     *
     *  \since 1.12.63
     *
     *  \return
     *  - true if the request has been processed successfully.
     *  - false otherwise.
     */
    bool isOK( void ) const
    {
        return ( requestResult.read() == rrOK );
    }
    /// \brief Sets a request into configuration mode.
    /**
     *  In configuration mode certain properties like \b mvIMPACT::acquire::Request::imageData,
     *  \b mvIMPACT::acquire::Request::imageSize, \b mvIMPACT::acquire::Request::imageMemoryMode
     *  of a request object can be modified. This can be used to configure one or more requests
     *  to use a user supplied memory. To use only a subset of the \b mvIMPACT::acquire::Request
     *  objects available the \b mvIMPACT::acquire::ImageRequestControl::requestToUse feature
     *  can be used.
     *
     *  Only requests that are currently not used by the driver and are not locked
     *  because they contain image data that hasn't been processed can be set into
     *  configuration mode.
     *
     *  \note
     *  Instead of calling this function directly for most cases it is much more convenient to use
     *  the functions \b mvIMPACT::acquire::Request::attachUserBuffer and \b mvIMPACT::acquire::Request::detachUserBuffer
     *  instead.
     *
     *  User supplied buffers must follow the alignment and size requirements reported by versions of the
     *  function \b mvIMPACT::acquire::FunctionInterface::getCurrentCaptureBufferLayout. Calling
     *  a version of this function will return all the information required to allocate buffers that
     *  can be used to capture data for the specified settings.
     *
     *  When allocating memory on the heap, the complete buffer size is needed which is calculated like
     *  this:
     *
     *  <b>size + alignment</b>
     *
     *  \note
     *  The address passed to the request object must be aligned already!
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  Device* pDev = getDevicePointerFromSomewhere()
     *  FunctionInterface fi(pDev);
     *  Request* pRequest = fi.getRequest( 0 );
     *  // the buffer assigned to the request object must be aligned accordingly
     *  // the size of the user supplied buffer MUST NOT include the additional size
     *  // caused by the alignment
     *  if( pRequest->attachUserBuffer( getAlignedMemoryPtr(), getAlignedMemorySize() ) ) == DMR_NO_ERROR )
     *  {
     *    ImageRequestControl irc(pDev);
     *    irc.requestToUse.write( 0 ); // use the buffer just configured for the next image request
     *    // now the next image will be captured into the user supplied memory
     *    fi.imageRequestSingle( &irc ); // this will send request '0' to the driver
     *    // wait for the buffer. Once it has been returned by the driver AND the user buffer shall no
     *    // longer be used call
     *    if( pRequest->detachUserBuffer() != DMR_NO_ERROR )
     *    {
     *      // handle error
     *    }
     *    // now this request will use internal memory again.
     *  }
     *  else
     *  {
     *     // handle error
     *  }
     * \endcode
     *  \endif
     *  \note
     *  A request that is in configuration mode can't be sent to the driver for acquisition until
     *  \b mvIMPACT::acquire::Request::unlock or \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock has been called again.
     *  By using \b mvIMPACT::acquire::Request::attachUserBuffer and \b mvIMPACT::acquire::Request::detachUserBuffer this locking
     *  and unlocking is done internally thus the application does not need to worry about this.
     *
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle, \n
     *  \b mvIMPACT::acquire::Request::attachUserBuffer, \n
     *  \b mvIMPACT::acquire::Request::detachUserBuffer, \n
     *  \b mvIMPACT::acquire::Request::unlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestReset
     *
     *  \since 1.12.68
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int configure( void )
    {
        return DMR_ImageRequestConfigure( m_pRefData->m_pDev->hDrv(), m_pRefData->m_requestNr, 0, 0 );
    }
    /// \brief Stores the image described by this request into a file.
    /**
     *  This function stores the image described by this request into a file.
     *
     *  \note
     *  Internally The FreeImage library (see 'legal notice' section) is used for this operation. If the library
     *  cannot be located in version 3.16.0 on the host system calling this function will fail.
     *
     * \since 2.23.0
     *  \return
     *  - <b>mvIMPACT::acquire::DMR_NO_ERROR</b> if successful.
     *  - <b>mvIMPACT::acquire::DMR_LIBRARY_NOT_FOUND</b> if the required version of the FreeImage library could not be located on the host system.
     *  - <b>mvIMPACT::acquire::DEV_UNSUPPORTED_PARAMETER</b> if a pixel format has been passed to the function that is not supported by the internal algorithms.
     *  - <b>mvIMPACT::acquire::DEV_INPUT_PARAM_INVALID</b> if a pixel format has been passed to the function that is not supported by the FreeImage library.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int save(
        /// [in] The full path of the file to create.
        const std::string& fileName,
        /// [in] The format of the file to be created. If this parameter is set to <b>mvIMPACT::acquire::iffAuto</b> make sure to specify a proper file extension.
        TImageFileFormat format = iffAuto ) const
    {
        return DMR_ImageRequestSave( m_pRefData->m_pDev->hDrv(), m_pRefData->m_requestNr, fileName.c_str(), format );
    }
    /// \brief Unlocks the request for the driver again.
    /**
     *
     *  To ensure that no image data is overwritten by another image request while the user still
     *  deals with the image from a previous acquisition each image buffer will be locked by the driver when
     *  it is returned to the user by a call to \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor.
     *  No new image will be captured into the same buffer until the user unlocks the buffer again
     *  by calling \b mvIMPACT::acquire::Request::unlock or \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock.
     *
     *  \note
     *  After unlocking a request it is no longer guaranteed that the memory once referenced by the
     *  request and the image buffer belonging to it stays valid, so do \b NEVER try to access
     *  memory belonging to an unlocked request object. If you need to copy the image buffer or
     *  modify it in any other way, do everything you have to do \b BEFORE calling this function!
     *
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestReset, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure, \n
     *  \b mvIMPACT::acquire::Request::configure
     *
     *  \since 1.12.68
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int unlock( void )
    {
        return DMR_ImageRequestUnlock( m_pRefData->m_pDev->hDrv(), m_pRefData->m_requestNr );
    }
    /// \brief Convenience function to attach a user supplied buffer to a \b mvIMPACT::acquire::Request object.
    /**
     *  This function just provides a nicer way to attach a user supplied buffer to a \b mvIMPACT::acquire::Request.
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  It e.g. makes it possible to write code like this:
     *
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT::acquire::FunctionInterface,
     *  const Request* pRequest = fi.getRequest( 0 ); // get access to request 0
     *  pRequest->attachUserBuffer( getBufferFromSomewhere(), getBufferSizeFromSomewhere() );
     * \endcode
     *
     *  Instead if this:
     *
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT::acquire::FunctionInterface,
     *  const Request* pRequest = fi.getRequest( 0 ); // get access to request 0
     *  if( pRequest->configure() == DMR_NO_ERROR )
     *  {
     *    pRequest->imageMemoryMode.write( rimmUser );
     *    pRequest->imageData.write( getBufferFromSomewhere() );
     *    pRequest->imageSize.write( getBufferSizeFromSomewhere() );
     *    pRequest->unlock();
     *  }
     * \endcode
     *  \endif
     *
     *  To find out more about capturing to user supplied buffers please
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  refer to the example \ref CaptureToUserMemory.cpp and
     *  \endif
     *  have a look at the documentation of the function \b mvIMPACT::acquire::Request::configure.
     *
     *  \sa
     *  \b mvIMPACT::acquire::Request::detachUserBuffer, \n
     *     mvIMPACT::acquire::FunctionInterface::imageRequestUnlock, \n
     *     mvIMPACT::acquire::Request::unlock, \n
     *     mvIMPACT::acquire::FunctionInterface::imageRequestConfigure, \n
     *     mvIMPACT::acquire::Request::configure
     *
     *  \since 1.12.68
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int attachUserBuffer(
        /// [in] A pointer to a user supplied buffer
        void* pBuf,
        /// [in] The size of the user supplied buffer
        int bufSize )
    {
        int result = configure();
        if( result == DMR_NO_ERROR )
        {
            imageMemoryMode.write( rimmUser );
            imageData.write( pBuf );
            imageSize.write( bufSize );
            result = unlock();
        }
        return result;
    }
    /// \brief Convenience function to detach a user supplied buffer from a \b mvIMPACT::acquire::Request object.
    /**
     *  This function just provides a nicer way to detach a user supplied buffer from a \b mvIMPACT::acquire::Request.
     *  It e.g. allows to write code like this:
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT::acquire::FunctionInterface
     *  const Request* pRequest = fi.getRequest( 0 ); // get access to request 0
     *  pRequest->detachUserBuffer();
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT.acquire.FunctionInterface
     *  Request pRequest = fi.getRequest( 0 ); // get access to request 0
     *  pRequest.detachUserBuffer();
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  # 'fi' is assumed to be a valid instance of acquire.FunctionInterface
     *  pRequest = fi.getRequest(0) # get access to request 0
     *  pRequest.detachUserBuffer()
     * \endcode
     * \endif
     *
     *  Instead if this:
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT::acquire::FunctionInterface
     *  const Request* pRequest = fi.getRequest( 0 ); // get access to request 0
     *  if( pRequest->configure() == DMR_NO_ERROR )
     *  {
     *    pRequest->imageMemoryMode.write( rimmAuto );
     *    pRequest->unlock();
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  // 'fi' is assumed to be a valid instance of mvIMPACT.acquire.FunctionInterface
     *  Request pRequest = fi.getRequest( 0 ); // get access to request 0
     *  if( pRequest.configure() == TDMR_ERROR.DMR_NO_ERROR )
     *  {
     *    pRequest.getImageMemoryMode().write( TRequestImageMemoryMode.rimmAuto );
     *    pRequest.unlock();
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  # 'fi' is assumed to be a valid instance of acquire.FunctionInterface
     *  pRequest = fi.getRequest(0) # get access to request 0
     *  if pRequest.configure() == acquire.DMR_NO_ERROR:
     *    pRequest.imageMemoryMode.write(acquire.rimmAuto)
     *    pRequest.unlock()
     * \endcode
     * \endif
     *
     *  To find out more about capturing to user supplied buffers please
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  refer to the example \ref CaptureToUserMemory.cpp and
     *  \endif
     *  have a look at the documentation of the function \b mvIMPACT::acquire::Request::configure.
     *
     *  \sa
     *  \b mvIMPACT::acquire::Request::attachUserBuffer, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock, \n
     *  \b mvIMPACT::acquire::Request::unlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure, \n
     *  \b mvIMPACT::acquire::Request::configure
     *
     *  \since 1.12.68
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int detachUserBuffer( void )
    {
        int result = configure();
        if( result == DMR_NO_ERROR )
        {
            imageMemoryMode.write( rimmAuto );
            result = unlock();
#ifdef COMPILE_PYTHON
            m_pRefData->releasePythonBufferIfNeeded();
#endif // #ifdef COMPILE_PYTHON
        }
        return result;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property \b (read-only) defining the result of this request.
    /**
     *  This parameter indicates whether a previous image acquisition has been
     *  successful or not.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TRequestResult.
     */
    PropertyIRequestResult requestResult;
    /// \brief An enumerated integer property \b (read-only) defining the current state of this request.
    /**
     *  This parameter indicates the current state of this request. A \b mvIMPACT::acquire::Request e.g.
     *  can currently be idle. This would mean that it is currently not used for
     *  image acquisition. Also a \b mvIMPACT::acquire::Request can be in 'Capturing' state, which means
     *  it is currently processed by the driver.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TRequestState.
     */
    PropertyIRequestState requestState;
    /// \brief A 64 bit integer property \b (read-only) containing a frame identifier.
    /**
     *  This parameter is returned as part of the \b mvIMPACT::acquire::Request. It is
     *  used to associate a certain image with a unique identifier.
     *
     *  When an \b mvIMPACT::acquire::RTCtrProgramStep instruction of the type \b mvIMPACT::acquire::rtctrlProgTriggerSet
     *  is executed, the \a frameID is set to the value of the property \a FrameID of a corresponding \b mvIMPACT::acquire::RTCtrProgramStep if the
     *  HRTC is used and any program step executes the setting of the ID.
     *
     *  If a device (e.g. a digital camera) supports the transmission of a unique identifier for an image, this property will reflect
     *  the identifier as transmitted by the device.
     *
     *  \note \b mvBlueFOX and \b mvHYPERION specific:
     *  This property will only contain meaningful data if the device supports at least one \b HRTC and a program is running and writing data to
     *  the property OR if a device supports the transmission of a unique identifier for an image. Currently HRTC programs are supported by \b mvBlueFOX and \b mvHYPERION devices.
     *
     *  \note \b GigE \b Vision and \b USB3 \b Vision specific:
     *  This is the property where the so called block ID will be stored which is a unique identifier for each frame that will be transferred by the device as part of each frame as defined by the standard.
     *  - For \b GigE \b Vision 1.x compliant devices, this will be a 16 bit counter that will be incremented with every data block(e.g. an image or chunk data) transmitted
     *  by the device where '0' is a reserved value, which will never be used, thus values like this will be transmitted in a round robin scheme:
     *  1, 2, 3, ..., 65535, 1, 2, ...
     *  - For devices complying with version 2.0 and greater of the \b GigE \b Vision specification, this will be a 64 bit counter that will be incremented with every data block(e.g. an image or chunk data) transmitted
     *  by the device where '0' is a reserved value, which will never be used, thus values like this will be transmitted in a round robin scheme:
     *  1, 2, 3, ..., ((2^64)-1), 1, 2, ...
     *  - For \b USB3 \b Vision compliant devices, this will be a 64 bit counter that will be incremented with every data block(e.g. an image or chunk data) transmitted
     *  by the device, thus values like this will be transmitted in a round robin scheme:
     *  0, 1, 2, ..., ((2^64)-1), 0, 1, ...
     *
     *  Please note that due to the nature of \b mvIMPACT::acquire::amContinuous there might be gaps between the
     *  last image of a continuous stream and the first image of the next continuous stream if the device is stopped or re-programmed in between.
     */
    PropertyI64 infoFrameID;
    /// \brief A 64 bit integer property \b (read-only, zero-based) containing the number of image requests processed since this driver instance has been opened.
    /**
     *  This counter is incremented regardless of the result this request is returned with thus also e.g. if a request did time out, was aborted(e.g. due to a call to \b mvIMPACT::acquire::FunctionInterface::imageRequestReset or \b mvIMPACT::acquire::FunctionInterface::acquisitionStop) or the data was not completely captured.
     *  So if a \b mvIMPACT::acquire::Request object contains the value \a 6 here, 6 requests have been processed before this one(the first request would contain the value \a 0)
     *  This value is reset to 0 only if the current driver instance is closed.
     */
    PropertyI64 infoFrameNr;
    /// \brief An integer property \b (read-only) containing a timestamp (in us) defining the time the device started the exposure of the image associated with this \b mvIMPACT::acquire::Request object.
    /**
     *  This value will stay 0 if nothing is known about the time the exposure did start.
     *  In such a case the \b mvIMPACT::acquire::Request::infoTimeStamp_us property should be used instead.
     */
    PropertyI infoExposeStart_us;
    /// \brief An integer property \b (read-only) containing the 'real' expose time (in us) used to generate this image.
    /**
     *  This might differ slightly from the value selected by the user via
     *  the corresponding exposure property depending on the precision
     *  available for the device or the connected camera.
     *
     * \note When working with the <b>mvIMPACT::acquire::dilGenICam</b> this value will reflect the last value of the corresponding device
     * property when it was written thus is a cached copy of the value that has been set by the application. For various operation modes
     * this might \b NOT be the value actually used by the device for taking the image described by this request object. For example when
     * AEC (exposureAuto) is active or the device is operated in a special sequencer mode the value of this property might be incorrect. When
     * precise information about this value is needed it is recommended to work in chunk mode and use the exposure provided as chunk information instead.
     *
     * \sa
     * \b mvIMPACT::acquire::Device::interfaceLayout, \n
     * \b mvIMPACT::acquire::GenICam::ChunkDataControl, \n
     * \b mvIMPACT::acquire::GenICam::AcquisitionControl::exposureAuto, \n
     * \b mvIMPACT::acquire::Request::getChunkExposureTime
     */
    PropertyI infoExposeTime_us;
    /// \brief An integer property \b (read-only) containing the time the transaction of this image has been delayed (in us) because either the bus was blocked or the CPU was busy.
    /**
     *  Normally this value will be 0. A value larger than 0 indicates that the system
     *  can't manage the current load.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyI infoTransferDelay_us;
    /// \brief A float property \b (read-only) containing the gain(in dB) this image has been taken with.
    /**
     * \note When working with the <b>mvIMPACT::acquire::dilGenICam</b> this value will reflect the last value of the corresponding device
     * property when it was written thus is a cached copy of the value that has been set by the application. For various operation modes
     * this might \b NOT be the value actually used by the device for taking the image described by this request object. For example when
     * AGC (gainAuto) is active or the device is operated in a special sequencer mode the value of this property might be incorrect. When
     * precise information about this value is needed it is recommended to work in chunk mode and use the gain provided as chunk information instead.
     *
     * \sa
     * \b mvIMPACT::acquire::Device::interfaceLayout, \n
     * \b mvIMPACT::acquire::GenICam::ChunkDataControl, \n
     * \b mvIMPACT::acquire::GenICam::AnalogControl::gainAuto, \n
     * \b mvIMPACT::acquire::Request::getChunkGainCount, \n
     * \b mvIMPACT::acquire::Request::getChunkGain
     */
    PropertyF infoGain_dB;
    /// \brief A 64 bit integer property \b (read-only) containing a timestamp to define the exact time this image has been captured
    /// (usually either at exposure start or exposure end, depending on the device).
    /**
     * \b mvBlueFOX specific:
     * The counter of the timestamp starts when the camera gets initialized. It is measured in us.
     */
    PropertyI64 infoTimeStamp_us;
    /// \brief A enumerated integer property \b (read-only) containing the setting that was used for processing this request.
    /**
     *  The string representation will be a valid setting name, the integer representation can be casted into a \b mvIMPACT::acquire::HOBJ type.
     */
    PropertyI infoSettingUsed;
    /// \brief Currently unsupported.
    PropertyF infoImageAverage;
    /// \brief An integer property \b (read-only) containing the video input channel of the device this image has been acquired from.
    /**
     *  \note
     *  This property is not supported by every device and will only be available if the device has more than one input channel.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyI infoVideoChannel;
    /// \brief An enumerated integer property \b (read-only) containing the camera output used to transmit the image to the capture device.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraOutput.
     *
     *  \note This property is not supported by every device. Therefore always call the function \b mvIMPACT::acquire::Component::isValid
     *  to check if this property is available or not.
     */
    PropertyICameraOutput infoCameraOutputUsed;
    /// \brief An integer property \b (read-only) containing the number of lines since the last trigger event.
    /**
     *  Will contain
     *  - the number of lines since last trigger event of the first line of the snap if line counting is enabled
     *  - -1 otherwise
     *
     *  \note This property is not supported by every device. Therefore always call the function \b mvIMPACT::acquire::Component::isValid
     *  to check if this property is available or not.
     */
    PropertyI infoLineCounter;
    /// \brief A float property \b (read-only) containing the amount of data missing in the current image.
    /**
     *  The value of this property will be 0 almost always. However if a device
     *  can detect blocks of missing data and an image request has returned with \b mvIMPACT::acquire::rrFrameIncomplete
     *  to indicate that not all the data has been captured, this property will contain the amount of data missing in percent.
     */
    PropertyF infoMissingData_pc;
    /// \brief An integer property \b (read-only) containing the state of all the IO lines at the beginning of the frame exposure as a device specific bit field.
    /**
     *  The following table documents which bit in this property represents the state of which digital I/O for \b mvBlueFOX devices:
     *
     *  <table>
     *  <tr><td class="header">bit</td><td class="header">IO</td></tr>
     *  <tr><td class="indexvalue">0</td><td class="indexvalue">in 0</td></tr>
     *  <tr><td class="indexvalue">1</td><td class="indexvalue">in 1</td></tr>
     *  <tr><td class="indexvalue">2</td><td class="indexvalue">in 2(if available)</td></tr>
     *  <tr><td class="indexvalue">3</td><td class="indexvalue">in 3(if available)</td></tr>
     *  <tr><td class="indexvalue">4</td><td class="indexvalue">out 0</td></tr>
     *  <tr><td class="indexvalue">5</td><td class="indexvalue">out 1</td></tr>
     *  <tr><td class="indexvalue">6</td><td class="indexvalue">out 2(if available)</td></tr>
     *  <tr><td class="indexvalue">7</td><td class="indexvalue">out 3(if available)</td></tr>
     *  </table>
     *
     * \attention This feature is currently only available for \b mvBlueFOX-MLC devices!
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  #include <sstream>
     *  #include <mvIMPACT/mvIMPACT_acquire.h>
     *
     *  using namespace std;
     *  using namespace mvIMPACT::acquire;
     *
     *  //-----------------------------------------------------------------------------
     *  template<typename _Ty>
     *  string decToBinString( _Ty value )
     *  //-----------------------------------------------------------------------------
     *  {
     *    const size_t bitCount = sizeof(_Ty)*8;
     *    ostringstream oss;
     *    for( size_t i=0; i<bitCount; i++ )
     *    {
     *      oss << ( ( value & ( 1 << ( bitCount - 1 - i ) ) ) ? "1" : "0" );
     *    }
     *    return oss.str();
     *  }
     *
     *  //-----------------------------------------------------------------------------
     *  void printIOStateOfAValidRequest( const Request* pRequest )
     *  //-----------------------------------------------------------------------------
     *  {
     *    if( pRequest->infoIOStatesAtExposureStart.isValid() )
     *    {
     *       cout << pRequest->infoIOStatesAtExposureStart.name() << ": " << decToBinString( pRequest->infoIOStatesAtExposureStart.read() ) << endl;
     *    }
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  //-----------------------------------------------------------------------------
     *  public static void printIOStateOfAValidRequest( Request pRequest )
     *  //-----------------------------------------------------------------------------
     *  {
     *    if( pRequest.getInfoIOStatesAtExposureStart().isValid() )
     *    {
     *       System.out.println( pRequest.getInfoIOStatesAtExposureStart().name() + ": " + Integer.toBinaryString( pRequest.getInfoIOStatesAtExposureStart().read() ) );
     *    }
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  def printIOStateOfAValidRequest(pRequest):
     *    if pRequest.infoIOStatesAtExposureStart.isValid:
     *      print(pRequest.infoIOStatesAtExposureStart.name() + ": " + format(pRequest.infoIOStatesAtExposureStart.read(), '32b'))
     * \endcode
     * \endif
     *  \note This property is not supported by every device. Therefore always call the function \b mvIMPACT::acquire::Component::isValid
     *  to check if this property is available or not.
     */
    PropertyI infoIOStatesAtExposureStart;
    /// \brief An integer property \b (read-only) containing the state of all the IO lines at the end of the frame exposure as a device specific bit field.
    /**
     *  See \b mvIMPACT::acquire::Request::infoIOStatesAtExposureStart for details on how to interpret the data.
     *
     *  \note This property is not supported by every device. Therefore always call the function \b mvIMPACT::acquire::Component::isValid
     *  to check if this property is available or not.
     */
    PropertyI infoIOStatesAtExposureEnd;
    /// \brief A 64 bit integer property \b (read-only) containing the X-offset of the image in pixels as returned in the chunk data attached to the image.
    /**
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     */
    PropertyI64 chunkOffsetX;
    /// \brief A 64 bit integer property \b (read-only) containing the Y-offset of the image in pixels as returned in the chunk data attached to the image.
    /**
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     */
    PropertyI64 chunkOffsetY;
    /// \brief A 64 bit integer property \b (read-only) containing the width of the image in pixels as returned in the chunk data attached to the image.
    /**
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     */
    PropertyI64 chunkWidth;
    /// \brief A 64 bit integer property \b (read-only) containing the height of the image in pixels as returned in the chunk data attached to the image.
    /**
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     */
    PropertyI64 chunkHeight;
    /// \brief A 64 bit integer property \b (read-only) containing the pixel format of the image as returned in the chunk data attached to the image.
    /**
     *  This will \b NOT be a valid mvIMPACT Acquire pixel format but e.g. a GigE Vision, USB3 Vision of PFNC compliant pixel format or something else.
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     */
    PropertyI64 chunkPixelFormat;
    /// \brief A 64 bit integer property \b (read-only) containing the minimum value of dynamic range of the image as returned in the chunk data attached to the image.
    /**
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     */
    PropertyI64 chunkDynamicRangeMin;
    /// \brief A 64 bit integer property \b (read-only) containing the maximum value of dynamic range of the image as returned in the chunk data attached to the image.
    /**
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     */
    PropertyI64 chunkDynamicRangeMax;
    /// \brief A floating point property \b (read-only) containing the exposure time used to capture the image as returned in the chunk data attached to the image.
    /**
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     *
     * \since 2.5.16
     */
    PropertyF chunkExposureTime;
    /// \brief A 64 bit integer property \b (read-only) containing the timestamp value of the internal frame start signal of the image as returned in the chunk data attached to the image.
    /**
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     */
    PropertyI64 chunkTimestamp;
    /// \brief A 64 bit integer property \b (read-only) containing the status of all I/O lines at the time of the internal frame start signal of the image as returned in the chunk data attached to the image.
    /**
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     */
    PropertyI64 chunkLineStatusAll;
    /// \brief A 64-bit integer property \b (read-only) containing the index of the active set of the running sequencer use during the creation of this block of data.
    /**
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     *
     *  \since 2.12.3
     */
    PropertyI64 chunkSequencerSetActive;
    /// \brief A 64 bit integer property \b (read-only) containing the previously configured user defined identifier attached to the image.
    /**
     *  This identifier can be specified by some other functions belonging to this SDK. If not specified this value will be 0.
     *
     *  \note
     *  For additional information about the chunk data format please refer to \ref ImageAcquisition_chunk.
     *
     *  \since 2.17.3
     */
    PropertyI64 chunkmvCustomIdentifier;
    /// \brief An enumerated integer property \b (read-only) containing the memory mode used for this request.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TRequestImageMemoryMode.
     *
     *  \note This property will become writeable if this request is in configuration mode.
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure, \n
     *  \b mvIMPACT::acquire::Request::configure
     */
    PropertyIRequestImageMemoryMode imageMemoryMode;
    /// \brief An enumerated integer property \b (read-only) containing the pixel format of this image.
    /**
     *  This might be important, when the image data needs to be processed or stored in
     *  a file or maybe even if the image shall be displayed.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TImageBufferPixelFormat.
     */
    PropertyIImageBufferPixelFormat imagePixelFormat;
    /// \brief A pointer property \b (read-only) containing the start address of the image data.
    /**
     *  This address in connection with \b mvIMPACT::acquire::Request::imageSize is sufficient
     *  to copy the complete image without having any additional information about it.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  FunctionInterface& fi = getFunctionInterfaceFromSomewhere();
     *  int currentRequestNr = getCurrentRequestNumberFromSomewhere();
     *  const Request* pRequest = fi.getRequest( currentRequestNr );
     *  char* pTempBuf = new char[pRequest->imageSize.read()];
     *  memcpy( pTempBuf, pRequest->imageData.read(), pRequest->imageSize.read() );
     *  // free the memory once no longer needed...
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     *  FunctionInterface fi = getFunctionInterfaceFromSomewhere();
     *  int currentRequestNr = getCurrentRequestNumberFromSomewhere();
     *  Request pRequest = fi.getRequest( currentRequestNr );
     *  byte[] data = new byte[pRequest.getImageSize().read()];
     *  pRequest.getImageBufferDesc().copy( data );
     * \code
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  currentRequestNr = getCurrentRequestNumberFromSomewhere()
     *  pRequest = fi.getRequest(currentRequestNr)
     *  cbuf = (ctypes.c_char * pRequest.imageSize.read()).from_address(int(pRequest.imageData.read()))
     * \endcode
     * \endif
     *
     *  \note
     *  It's not always necessary to copy the image data! Each image buffer is an
     *  integral part of the \b mvIMPACT::acquire::Request object returned to the user by a call to
     *  the corresponding 'waitFor' function offered by the interface.
     *  The data in this buffer remains valid until the user either
     *  unlocks the request buffer or closes the \b mvIMPACT::acquire::Device again.
     *
     *  \note
     *  By unlocking the \b mvIMPACT::acquire::Request, the user informs the driver that this \b mvIMPACT::acquire::Request
     *  and the image buffer belonging to that \b mvIMPACT::acquire::Request is no longer needed by the
     *  user. The driver then queues this \b mvIMPACT::acquire::Request for capturing image data into it once
     *  again. However, once a \b mvIMPACT::acquire::Request has been returned to the user, its image buffer
     *  can't be overwritten by the driver! Therefore the user can work with, modify, store or
     *  copy the data safely until he unlocks the \b mvIMPACT::acquire::Request again.
     *
     *  \note This property will become writeable if this request is in configuration mode.
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure, \n
     *  \b mvIMPACT::acquire::Request::configure, \n
     *  \b mvIMPACT::acquire::Request::imageSize, \n
     *  \b mvIMPACT::acquire::Request::imageFooterSize
     */
    PropertyPtr imageData;
    /// \brief An integer property \b (read-only) containing the size (in bytes) of the whole image.
    /**
     *  This value in connection with \b mvIMPACT::acquire::Request::imageData is sufficient
     *  to copy the complete image without having any additional information about it.
     *
     *  \note This property will become writeable if this request is in configuration mode.
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure, \n
     *  \b mvIMPACT::acquire::Request::configure, \n
     *  \b mvIMPACT::acquire::Request::imageData, \n
     *  \b mvIMPACT::acquire::Request::imageFooterSize
     */
    PropertyI imageSize;
    /// \brief A pointer property \b (read-only) containing the start address of the footer associated with this image.
    /**
     *  A footer may contain additional data like e.g. information about the image (e.g. the exposure time used for this image).
     *  If this property contains the value '0' no footer is attached to this image.
     *
     *  \note
     *  In general it is not necessary to access footer data. Sometime e.g. when the hardware already does some image pre-processing
     *  a footer containing additional information about the image data might be attached to the image. In this case some additional
     *  information about the structure of the footer might be needed as well.
     */
    PropertyPtr imageFooter;
    /// \brief An integer property \b (read-only) containing the size (in bytes) of the footer associated with this image.
    ///
    /// If this property contains the value '0' no footer is attached to this image.
    PropertyI imageFooterSize;
    /// \brief An integer property \b (read-only) containing the offset (in bytes) to the next pixel of the specified channel of this image.
    /**
     *  \note
     *  This property will store \a imageChannelCount values. These can be queried one by one using the \a index parameter of the function
     *  \b mvIMPACT::acquire::PropertyI::read() or in a single call by using the overloaded \a read function accepting a reference to a
     *  vector.
     */
    PropertyI imagePixelPitch;
    /// \brief An integer property \b (read-only) containing the number of channels this image consists of.
    /**
     *  For an RGB image this value e.g. would be 3. This value also defines how many parameters are stored by the properties
     *  \b mvIMPACT::acquire::Request::imagePixelPitch, \n
     *  \b mvIMPACT::acquire::Request::imageLinePitch, \n
     *  \b mvIMPACT::acquire::Request::imageChannelBitDepth, \n
     *  \b mvIMPACT::acquire::Request::imageChannelDesc and \n
     *  \b mvIMPACT::acquire::Request::imageChannelOffset.
     *
     *  If e.g. the channel count is 3 a call like pRequest->imageChannelOffset.read( 2 ) would return the channel offset of
     *  channel 3 (as calls to the read functions of properties are '0' based).
     */
    PropertyI imageChannelCount;
    /// \brief An integer property \b (read-only) containing the offset (in bytes) to each channel belonging to the current image relative to the address contained in \b mvIMPACT::acquire::Request::imageData.
    /**
     * \note
     * This property will store \a imageChannelCount values. These can be queried one by one using the \a index parameter of the function
     * \b mvIMPACT::acquire::PropertyI::read() or in a single call by using the overloaded \a read function accepting a reference to a
     * vector.
     */
    PropertyI imageChannelOffset;
    /// \brief An integer property \b (read-only) containing the number of effective bits stored in each channel belonging to the current image.
    /**
     *  \note
     *  This property will store \a imageChannelCount values. These can be queried one by one using the \a index parameter of the function
     *  \b mvIMPACT::acquire::PropertyI::read() or in a single call by using the overloaded \a read function accepting a reference to a
     *  vector.
     */
    PropertyI imageChannelBitDepth;
    /// \brief An integer property \b (read-only) containing the offset (in bytes) to the next line of each channel belonging to the current image.
    /**
     *  \note
     *  This property will store \a imageChannelCount values. These can be queried one by one using the \a index parameter of the function
     *  \b mvIMPACT::acquire::PropertyI::read() or in a single call by using the overloaded \a read function accepting a reference to a
     *  vector.
     */
    PropertyI imageLinePitch;
    /// \brief A string property \b (read-only) containing the string descriptors of each channel belonging to the current image.
    /**
     * \note
     *  This property will store \a imageChannelCount values. These can be queried one by one using the \a index parameter of the function
     *  \b mvIMPACT::acquire::PropertyS::read() or in a single call by using the overloaded \a read function accepting a reference to a
     *  vector.
     *
     *  For an RGB image this property e.g. might contain three values "R", "G" and "B".
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  FunctionInterface& fi = getFunctionInterfaceFromSomewhere();
     *  int currentRequestNr = getCurrentRequestNumberFromSomewhere();
     *  const Request* pRequest = fi.getRequest( currentRequestNr );
     *  int channelCount = pRequest->imageChannelCount.read();
     *  for( int i=0; i<channelCount; i++ )
     *  {
     *    cout << "channel[" << i << "]: " << pRequest->imageChannelDesc.read( i ) << endl;
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  FunctionInterface fi = getFunctionInterfaceFromSomewhere();
     *  int currentRequestNr = getCurrentRequestNumberFromSomewhere();
     *  Request pRequest = fi.getRequest( currentRequestNr );
     *  int channelCount = pRequest.getImageChannelCount().read();
     *  for( int i=0; i<channelCount; i++ )
     *  {
     *    System.out.println( String.format( "channel[%d]: %s", i, pRequest.getImageChannelDesc().read( i ) ) );
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  fi = getFunctionInterfaceFromSomewhere()
     *  currentRequestNr = getCurrentRequestNumberFromSomewhere()
     *  pRequest = fi.getRequest(currentRequestNr)
     *  channelCount = pRequest.imageChannelCount.read()
     *  for i in range(channelCount):
     *    print("channel[", i, "]: ", pRequest.imageChannelDesc.read(i))
     * \endcode
     * \endif
     */
    PropertyS imageChannelDesc;
    /// \brief An integer property \b (read-only) containing the number of bytes per pixel in this image.
    PropertyI imageBytesPerPixel;
    /// \brief An integer property \b (read-only) containing the X-offset of the image in pixels.
    /**
     *  \note
     *  This feature will be supported by devices using an mvIMPACT Acquire driver greater or equal version 1.10.92.
     */
    PropertyI imageOffsetX;
    /// \brief An integer property \b (read-only) containing the Y-offset of the image in pixels.
    /**
     *  \note
     *  This feature will be supported by devices using an mvIMPACT Acquire driver greater or equal version 1.10.92.
     */
    PropertyI imageOffsetY;
    /// \brief An integer property \b (read-only) containing the width of the image in pixels.
    PropertyI imageWidth;
    /// \brief An integer property \b (read-only) containing the total width of the image in pixels if this buffer is part of a larger image.
    /**
     *  \note
     *  This feature will be supported by devices using an mvIMPACT Acquire driver greater or equal version 1.11.50. Not
     *  every device driver will be capable of dealing with multiple buffers forming a single image. If a device driver can
     *  not deliver parts of a larger image, then this property will always contain the same value as returned by
     *  \b mvIMPACT::acquire::Request::imageWidth.
     */
    PropertyI imageWidthTotal;
    /// \brief An integer property \b (read-only) containing the height of the image in pixels.
    PropertyI imageHeight;
    /// \brief An integer property \b (read-only) containing the total height of the image in pixels if this buffer is part of a larger image.
    /**
     *  \note
     *  This feature will be supported by devices using an mvIMPACT Acquire driver greater or equal version 1.11.50. Not
     *  every device driver will be capable of dealing with multiple buffers forming a single image. If a device driver can
     *  not deliver parts of a larger image, then this property will always contain the same value as returned by
     *  \b mvIMPACT::acquire::Request::imageHeight.
     */
    PropertyI imageHeightTotal;
    /// \brief An enumerated integer property \b (read-only) containing the Bayer parity of this image.
    /**
     *  If the current image does not contain Bayer data, this value will be \b mvIMPACT::acquire::bmpUndefined.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBayerMosaicParity.
     */
    PropertyIBayerMosaicParity imageBayerMosaicParity;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A helper class to control the way an image request will be processed.
class ImageRequestControl : public ComponentCollection
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::ImageRequestControl object.
    explicit ImageRequestControl(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a
        /// \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal image request control to access with
        /// this instance. A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableImageRequestControls,
        /// new image request controls can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createImageRequestControl
        const std::string& name = "Base" ) : ComponentCollection( pDev ), mode(),
        imageCount(), setting(), requestQueue(), resultQueue(), requestToUse()
    {
        DeviceComponentLocator locator( pDev, dltRequestCtrl, name );
        m_hRoot = locator.searchbase_id();
        locator.bindComponent( mode, "Mode" );
        locator.bindComponent( imageCount, "ImageCount" );
        locator.bindComponent( setting, "Setting" );
        locator.bindComponent( requestQueue, "RequestQueue" );
        locator.bindComponent( resultQueue, "ResultQueue" );
        locator.bindComponent( requestToUse, "RequestToUse" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief The mode this object shall be operated in.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TImageRequestControlMode.
     *
     *  This property can e.g. be used to prepare internal data structures without requesting a
     *  'real' image from the hardware. This can be useful when the image dimensions must be known
     *  before the first image is captured.
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  Device* pDev = getDevicePointerFromSomewhere();
     *  ImageRequestControl irc( pDev );
     *  irc.mode.write( ircmTrial ); // set to prepare mode
     *  FunctionInterface fi( pDev );
     *  fi.imageRequestSingle( &irc ); // request dummy image
     *  int reqNr = fi.imageRequestWaitFor( 500 );
     *  // waitFor will return as fast as possible. No 'real' image will be taken
     *  // but a request object that contains a dummy image with the format, dimensions
     *  // and other information will be returned that is (apart from the pixel data)
     *  // similar to any 'real' image that would be captured with the current settings
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  Device pDev = getDevicePointerFromSomewhere();
     *  ImageRequestControl irc = new ImageRequestControl( pDev );
     *  irc.getMode().write( TImageRequestControlMode.ircmTrial ); // set to prepare mode
     *  FunctionInterface fi = new FunctionInterface( pDev );
     *  fi.imageRequestSingle( irc ); // request dummy image
     *  int reqNr = fi.imageRequestWaitFor( 500 );
     *  // waitFor will return as fast as possible. No 'real' image will be taken
     *  // but a request object that contains a dummy image with the format, dimensions
     *  // and other information will be returned that is (apart from the pixel data)
     *  // similar to any 'real' image that would be captured with the current settings
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  pDev = getDeviceFromSomewhere()
     *  irc = ImageRequestControl(pDev)
     *  irc.mode.write(acquire.ircmTrial) # set to prepare mode
     *  fi = FunctionInterface(pDev)
     *  fi.imageRequestSingle(irc) # request dummy image
     *  reqNr = fi.imageRequestWaitFor(500)
     *  # waitFor will return as fast as possible. No 'real' image will be taken
     *  # but a request object that contains a dummy image with the format, dimensions
     *  # and other information will be returned that is (apart from the pixel data)
     *  # similar to any 'real' image that would be captured with the current settings
     * \endcode
     * \endif
     */
    PropertyIImageRequestControlMode mode;
    /// \brief An integer property defining the number of images to capture with each request.
    /**
     *  \note This property will currently have no effect.
     */
    PropertyI imageCount;
    /// \brief An integer property defining which setting will be used for the acquisition.
    /**
     *  This property defines a translation dictionary. It maps the name of the setting (the parameter
     *  passed to the function \b mvIMPACT::acquire::FunctionInterface::createSetting) to the actual
     *  underlying handle of the request. Therefore either the name or the handle of the setting can be used
     *  to set this property to the desired value.
     */
    PropertyI setting;
    /// \brief An integer property defining to which request queue the image request will be sent.
    /**
     * This property defines the stream channel requests associated with this request control instance will be sent to.
     *
     * The maximum value for this feature corresponds to the number of independent stream channels offered by the device. Only devices operated in
     * interface layout \b mvIMPACT::acquire::dilGenICam may offer more than one stream channel. Therefore the default
     * value and the default maximum and minimum value will be 0 for most devices.
     *
     * \since 2.47.0
     */
    PropertyI requestQueue;
    /// \brief An integer property defining to which result queue the resulting image will be sent after the acquisition.
    PropertyI resultQueue;
    /// \brief An integer property defining which request object shall be used for the next image request.
    /**
     *  This is an advanced feature that should only be used if needed. A value smaller than 0 will
     *  result in an automatic mode. This is the default behaviour and the driver will decide which buffer to use next then.
     *
     *  A request can only be sent to the driver once. Until this request is returned to the user it can't
     *  be sent again thus this property must be changed for each request if multiple requests shall be sent to
     *  the capture queue.
     */
    PropertyI requestToUse;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A default request factory.
/**
 *  Applications need to derive from this class and must re-implement the function
 *  \b mvIMPACT::acquire::RequestFactory::createRequest to work with custom
 *  objects derived from \b mvIMPACT::acquire::Request.
 *
 *  Deriving from \b mvIMPACT::acquire::Request can be useful when a certain
 *  device driver or device offers a custom feature that is returned as part of
 *  the request object that can not be accessed using the \b mvIMPACT::acquire::Request
 *  class offered by this interface.
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 *  This shows how a request factory could be used to create custom request objects
 *  from within a \b mvIMPACT::acquire::FunctionInterface instance.
 *
 * \code
 *  class MyRequestFactory;
 *
 *  //-----------------------------------------------------------------------------
 *  // Example for a derived request object. It doesn't introduce new functionality
 *  // but rebinds an existing property. Custom properties could bound in a similar
 *  // way.
 *  class MyRequest : public mvIMPACT::acquire::Request
 *  //-----------------------------------------------------------------------------
 *  {
 *    friend class MyRequestFactory;
 *    void init( void )
 *    {
 *      DeviceComponentLocator locator(getComponentLocator());
 *      locator.bindComponent( myRequestResult, "Result" );
 *    }
 *  protected:
 *    explicit MyRequest( Device* pDev, int requestNr ) : Request(pDev, requestNr), myRequestResult()
 *    {
 *      init();
 *    }
 *  public:
 *    explicit MyRequest( const MyRequest& src ) : Request(src), myRequestResult(src.myRequestResult) {}
 *    MyRequest& operator=( const MyRequest& rhs )
 *    {
 *      if( this != &rhs )
 *      {
 *        Request::operator=( rhs );
 *        init();
 *      }
 *      return *this;
 *    }
 *    PropertyIRequestResult myRequestResult;
 *  };
 *
 *  //-----------------------------------------------------------------------------
 *  // Example for a factory that creates 'MyRequest' instances
 *  class MyRequestFactory : public mvIMPACT::acquire::RequestFactory
 *  //-----------------------------------------------------------------------------
 *  {
 *  public:
 *    virtual mvIMPACT::acquire::Request* createRequest( Device* pDev, int requestNr ) { return new MyRequest( pDev, requestNr ); }
 *  };
 *
 * \endcode
 *
 *  Now the request factory must be passed to the constructor of the function interface
 *
 * \code
 *  //-----------------------------------------------------------------------------
 *  void fn( mvIMPACT::acquire::Device* pDev )
 *  //-----------------------------------------------------------------------------
 *  {
 *    // ... some code ...
 *    MyRequestFactory mrf;
 *    FunctionInterface fi(pDev, &mrf);
 *    // ... more additional code
 *    // assuming we got back a request from the driver at this point:
 *    const Request* pRequest = fi.getRequest( getRequestNrFromSomewhere() );
 *    if( pRequest->isOK() )
 *    {
 *      const MyRequest* pMyRequest(dynamic_cast<const MyRequest*>(pRequest));
 *      cout << pMyRequest->myRequestResult.name() << ": " << pMyRequest->myRequestResult.readS() << endl;
 *      // do what you want to do with your derived request instance here!
 *    }
 *    // ... probably even more additional code
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 *  This shows how a request factory could be used to create custom request objects
 *  from within a \b mvIMPACT::acquire::FunctionInterface instance.
 *
 * MyRequest.java:
 *
 * \code
 * import mvIMPACT.acquire.*;
 *
 * //-----------------------------------------------------------------------------
 * // Example for a derived request object. It doesn't introduce new functionality
 * // but rebinds an existing property. Custom properties could bound in a similar
 * // way.
 * class MyRequest extends Request
 * //-----------------------------------------------------------------------------
 * {
 *   private PropertyI myRequestResult_ = new PropertyI();
 *
 *   private void init()
 *   {
 *     DeviceComponentLocator locator = new DeviceComponentLocator( getComponentLocator().hObj() );
 *     locator.bindComponent( myRequestResult_, "Result" );
 *   }
 *
 *   protected MyRequest( Device pDev, int requestNr )
 *   {
 *     super( pDev, requestNr );
 *     init();
 *   }
 *
 *   // Without this constructor this whole 'RequestFactory' concept will not work
 *   // at the moment as in 'FunctionInterface.getRequest' the internal correctly
 *   // constructed 'MyRequest' generated via the director class and 'MyRequestFactory'
 *   // will be used to create a new 'Request' instance from it. We now use this to
 *   // re-create yet another 'MyRequest' instance from that which is kind of silly
 *   // but in Python we have a very similar effect(see corresponding snippet in the Python manual).
 *   //
 *   // Maybe there is a better way to do this! Suggestions welcome!
 *   public MyRequest( Request pRequest )
 *   {
 *     super( Request.getCPtr( pRequest ), false );
 *     init();
 *   }
 *
 *   public PropertyI getMyRequestResult()
 *   {
 *     return myRequestResult_;
 *   }
 * }
 * \endcode
 *
 * MyRequestFactory.java:
 *
 * \code
 * import mvIMPACT.acquire.*;
 *
 * //-----------------------------------------------------------------------------
 * // Example for a factory that creates 'MyRequest' instances
 * class MyRequestFactory extends RequestFactory
 * //-----------------------------------------------------------------------------
 * {
 *   @Override
 *   public Request createRequest( Device pDev, int requestNr )
 *   {
 *     return new MyRequest( pDev, requestNr );
 *   }
 * }
 *
 * \endcode
 *
 *  Now the request factory must be passed to the constructor of the function interface!
 *  This might happen in some other source file or class within the application.
 *
 * \code
 *  //-----------------------------------------------------------------------------
 *  void fn( Device pDev )
 *  //-----------------------------------------------------------------------------
 *  {
 *    // ... some code ...
 *    MyRequestFactory mrf = new MyRequestFactory();
 *    FunctionInterface fi = new FunctionInterface( pDev, mrf );
 *    // ... more additional code
 *    // assuming we got back a request from the driver at this point:
 *    Request pRequest = fi.getRequest( getRequestNrFromSomewhere() );
 *    if( pRequest->isOK() )
 *    {
 *      System.out.println( String.format( "%s: %s", ( ( MyRequest )pRequest ).getMyRequestResult().name(), ( ( MyRequest )pRequest ).getMyRequestResult().readS() );
 *      // do what you want to do with your derived request instance here!
 *    }
 *    // ... probably even more additional code
 *  }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 *  This shows how a request factory could be used to create custom request objects
 *  from within a \b mvIMPACT::acquire::FunctionInterface instance.
 *
 * \code
 * # Example for a derived request object. It doesn't introduce new functionality
 * # but rebinds an existing property. Custom properties could bound in a similar
 * # way.
 * class MyRequest(acquire.Request):
 *   def __init__(self, *args):
 *     acquire.Request.__init__(self, *args)
 *     self.myRequestResult = acquire.PropertyIRequestResult()
 *     locator = acquire.DeviceComponentLocator(self.getComponentLocator().hObj())
 *     locator.bindComponent(self.myRequestResult, "Result")
 *
 * class MyRequestFactory(acquire.RequestFactory):
 *   def __init__(self):
 *     acquire.RequestFactory.__init__(self)
 *     self.__instances = []
 *
 *   def createRequest(self, pDev, requestNr):
 *     try:
 *       instance = MyRequest(pDev, requestNr)
 *       # We MUST keep a reference to this request object here as otherwise the instance gets cleaned up
 *       # by the garbage collector when leaving this function. We therefore add an artificial reference
 *       # by adding this MyRequest instance to the array which is kind of silly but in Java we have a
 *       # very similar effect (see corresponding snippet in the Java manual).
 *       #
 *       # Maybe there is a better way to do this! Suggestions welcome!
 *       self.__instances.append(instance)
 *         return instance
 *       except Exception as e:
 *         print("An exception has been raised by code that is not supposed to raise one: '" + str(e) + "'! If this is NOT handled here the application will crash as this Python exception instance will be returned back into the native code that fired this function callS!")
 *         return None
 * \endcode
 *
 *  Now the request factory must be passed to the constructor of the function interface
 *
 * \code
 *  def fn(pDev):
 *    # ... some code ...
 *    mrf = MyRequestFactory()
 *    fi = acquire.FunctionInterface(pDev, mrf)
 *    # ... more additional code
 *    # assuming we got back a request from the driver at this point:
 *    pRequest = fi.getRequest(getRequestNrFromSomewhere())
 *    if pRequest.isOK:
 *      # The paranoid could do this additional check, but it is not necessary:
 *      if type(pRequest) is MyRequest:
 *        print(pMyRequest.myRequestResult.name() + ": " + pMyRequest.myRequestResult.readS())
 *      else:
 *        print("ERROR! We should have an instance of our derived 'MyRequest' class here!")
 *        sys.exit(-1)
 *      # do what you want to do with your derived request instance here!
 *    # ... probably even more additional code
 *  }
 * \endcode
 * \endif
 *
 *  \since 1.12.56
 *
 */
class RequestFactory
//-----------------------------------------------------------------------------
{
public:
    virtual ~RequestFactory() {}
    virtual Request* createRequest(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from
        /// a \b mvIMPACT::acquire::>DeviceManager object.
        Device* /*pDev*/,
        /// [in] The request number that internally has been assigned to this
        /// request by the device driver.
        int /*requestNr*/ )
    {
        return 0;
    }
};

//-----------------------------------------------------------------------------
/// \brief The function interface to devices supported by this interface.
/**
 *  This class contains all the basic functions needed when working with a device.
 *  There are not too many functions as most data will be represented by 'properties'
 *  in other classes of this module, keeping the set of functions to remember rather
 *  small. To construct a new function interface, a pointer to a \b mvIMPACT::acquire::Device object
 *  must be passed to the constructor of \b mvIMPACT::acquire::FunctionInterface. In order to work
 *  with the \b mvIMPACT::acquire::FunctionInterface object the device needs to be initialized, so
 *  if the \b mvIMPACT::acquire::Device object pointed to by \a pDev in the constructors parameter list
 *  hasn't been opened already the constructor will try to do that.
 *
 * Please refer to one of the examples listed below to get an idea on how to use this class for data acquisition:
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * - \ref SingleCapture.cpp
 * - \ref ContinuousCapture.cpp
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * - \ref ContinuousCapture.java
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * - \ref ContinuousCapture.py
 * \endif
 */
class FunctionInterface
//-----------------------------------------------------------------------------
{
    typedef std::vector<Request*> RequestVector;
#   if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        ComponentList                       m_requestList;
        ComponentList                       m_imageRequestControlList;
        mutable std::vector<std::string>    m_imageRequestControls;
        mutable RequestVector               m_requests;
        Request*                            m_pCurrentCaptureBufferLayout;
        mutable std::vector<std::string>    m_settings;
        mutable unsigned int                m_lastImageRequestChangedCounter;
        mutable unsigned int                m_lastSettingsListChangedCounter;
        std::stack<std::string>             m_settingsInRAM;
        Device*                             m_pDevice;
        RequestFactory*                     m_pRequestFactory;
        PropertyI                           m_requestCount;
        PropertyI                           m_captureBufferAlignment;
        ComponentList                       m_settingsList;
        unsigned int                        m_refCnt;
        explicit ReferenceCountedData( Device* pDev, RequestFactory* pRequestFactory ) : m_requestList(), m_imageRequestControlList(),
            m_imageRequestControls(), m_requests(), m_pCurrentCaptureBufferLayout( 0 ), m_settings(), m_lastImageRequestChangedCounter( 0 ),
            m_lastSettingsListChangedCounter( 0 ), m_settingsInRAM(), m_pDevice( pDev ), m_pRequestFactory( pRequestFactory ),
            m_requestCount(), m_captureBufferAlignment(), m_settingsList(), m_refCnt( 1 ) {}
        // make sure there are NO assignments or copy constructions by accident!
        ReferenceCountedData& operator=( const ReferenceCountedData& rhs );
        ReferenceCountedData( const ReferenceCountedData& src );
        ~ReferenceCountedData()
        {
            RequestVector::size_type rvSize = m_requests.size();
            for( RequestVector::size_type i = 0; i < rvSize; i++ )
            {
                delete m_requests[i];
            }
            delete m_pCurrentCaptureBufferLayout;
            while( !m_settingsInRAM.empty() )
            {
                deleteSettingFromStack();
            }
        }
        //-----------------------------------------------------------------------------
        int deleteSettingFromStack( void )
        //-----------------------------------------------------------------------------
        {
            if( m_settingsInRAM.empty() )
            {
                return PROPHANDLING_LIST_CANT_ACCESS_DATA;
            }
            const int result = DMR_DeleteSetting( m_settingsInRAM.top().c_str(), slRAM, sUser );
            m_settingsInRAM.pop();
            return result;
        }
        //-----------------------------------------------------------------------------
        int saveCurrentSettingOnStack( TStorageFlag storageFlags )
        //-----------------------------------------------------------------------------
        {
            std::ostringstream oss;
            oss << m_pDevice->serial.read() << "_" << this << "_" << m_settingsInRAM.size();
            storageFlags = static_cast<TStorageFlag>( ( storageFlags & ( ~( sfFile | sfNative ) ) ) | sfRAM );
            const int result = DMR_SaveSetting( m_pDevice->hDrv(), oss.str().c_str(), storageFlags, sUser );
            if( result == DMR_NO_ERROR )
            {
                m_settingsInRAM.push( oss.str() );
            }
            return result;
        }
    }* m_pRefData;
#   endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    //-----------------------------------------------------------------------------
    Request* createRequest( int requestNr ) const
    //-----------------------------------------------------------------------------
    {
        if( m_pRefData->m_pRequestFactory )
        {
            return m_pRefData->m_pRequestFactory->createRequest( m_pRefData->m_pDevice, requestNr );
        }
        return new Request( m_pRefData->m_pDevice, requestNr );
    }
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    //-----------------------------------------------------------------------------
    void updateRequests( void ) const
    //-----------------------------------------------------------------------------
    {
        RequestVector::size_type rListSize = static_cast<RequestVector::size_type>( m_pRefData->m_requestList.size() );
        RequestVector::size_type vSize = m_pRefData->m_requests.size();
        if( rListSize < vSize )
        {
            // requests have been deleted...
            for( RequestVector::size_type i = rListSize; i < vSize; i++ )
            {
                delete m_pRefData->m_requests[i];
            }
            m_pRefData->m_requests.resize( rListSize );
        }
        else if( rListSize > vSize )
        {
            // there are new requests
            Component it( m_pRefData->m_requestList );
            it = it.firstChild();
            for( RequestVector::size_type i = 0; ( i < vSize ) && it.isValid(); i++ )
            {
                ++it;
            }
            while( it.isValid() )
            {
                // this might happen, if there are several instances referring to the same device
                // and another instance has created new requests in the meantime, or if this instance
                // has just been created
                m_pRefData->m_requests.push_back( createRequest( static_cast<int>( m_pRefData->m_requests.size() ) ) );
                ++it;
            }
        }
    }
    //-----------------------------------------------------------------------------
    void updateSettings( void ) const
    //-----------------------------------------------------------------------------
    {
        unsigned int actChangedCounter = m_pRefData->m_settingsList.changedCounter();
        if( m_pRefData->m_lastSettingsListChangedCounter != actChangedCounter )
        {
            // something has changed in the settings list -> update the string array
            // the string array must be filled from scratch each time because settings might have been
            // deleted as well...
            m_pRefData->m_settings.clear();
            Component it( m_pRefData->m_settingsList );
            it = it.firstChild();
            while( it.isValid() )
            {
                // this might happen, if there are several instances referring to the same device
                // and another instance has created new settings in the meantime, or if this instance
                // has just been created
                m_pRefData->m_settings.push_back( it.name() );
                ++it;
            }
            m_pRefData->m_lastSettingsListChangedCounter = actChangedCounter;
        }
    }
    //-----------------------------------------------------------------------------
    void updateImageRequestControls( void ) const
    //-----------------------------------------------------------------------------
    {
        unsigned int actChangedCounter = m_pRefData->m_imageRequestControlList.changedCounter();
        if( m_pRefData->m_lastImageRequestChangedCounter != actChangedCounter )
        {
            // something has changed in the image request controls list -> update the string array
            // the string array must be filled from scratch each time because objects might have been
            // deleted as well...
            m_pRefData->m_imageRequestControls.clear();
            Component it( m_pRefData->m_imageRequestControlList );
            it = it.firstChild();
            while( it.isValid() )
            {
                // this might happen, if there are several instances referring to the same device
                // and another instance has created new object in the meantime, or if this instance
                // has just been created
                m_pRefData->m_imageRequestControls.push_back( it.name() );
                ++it;
            }
            m_pRefData->m_lastImageRequestChangedCounter = actChangedCounter;
        }
    }
public:
    /// \brief Constructs a new function interface for the device pointed to by \a pDev.
    /**
     *  In order to work with the \b mvIMPACT::acquire::FunctionInterface object the device needs to be
     *  initialized, so if the \b mvIMPACT::acquire::Device object pointed to by \a pDev in the constructors
     *  parameter list hasn't been opened already the constructor will try to do that.
     *  Thus internally a call to \b mvIMPACT::acquire::Device::open might be preformed with all consequences
     *  following from this call.
     *
     *  \sa
     *  \b mvIMPACT::acquire::Device::open
     */
    explicit FunctionInterface(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from
        /// a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] A pointer to a request factory.
        /// By supplying a custom request factory the user can control the type of request objects
        /// that will be created by the function interface.
        /// \since 1.12.56
        RequestFactory* pRequestFactory = 0 ) : m_pRefData( 0 )
    {
        if( !pDev->isOpen() )
        {
            pDev->open();
        }
        m_pRefData = new ReferenceCountedData( pDev, pRequestFactory );
        DeviceComponentLocator locator( pDev, dltSetting );
        m_pRefData->m_settingsList = ComponentList( locator.searchbase_id() );
        locator.bindSearchBaseList( pDev, dltRequest );
        m_pRefData->m_requestList = ComponentList( locator.searchbase_id() );
        locator.bindSearchBaseList( pDev, dltRequestCtrl );
        m_pRefData->m_imageRequestControlList = ComponentList( locator.searchbase_id() );
        locator.bindSearchBaseList( pDev, dltSystemSettings );
        locator.bindComponent( m_pRefData->m_requestCount, "RequestCount" );
        locator.bindSearchBaseList( pDev, dltInfo );
        locator.bindComponent( m_pRefData->m_captureBufferAlignment, "CaptureBufferAlignment" );
        updateRequests();
        locator.bindSearchBaseList( pDev, dltInfo );
        if( locator.findComponent( "CurrentRequestLayout" ) != INVALID_ID )
        {
            m_pRefData->m_pCurrentCaptureBufferLayout = createRequest( -1 );
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::FunctionInterface from an existing one.
    FunctionInterface(
        /// [in] A constant reference to the \b mvIMPACT::acquire::FunctionInterface object, this object shall be created from
        const FunctionInterface& src ) : m_pRefData( src.m_pRefData )
    {
        ++( m_pRefData->m_refCnt );
    }
    /// \brief Class destructor.
    virtual ~FunctionInterface( void )
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::FunctionInterface objects.
    FunctionInterface& operator=( const FunctionInterface& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            // inc. the NEW reference count
            ++m_pRefData->m_refCnt;
        }
        return *this;
    }
    /// \brief Manually starts the acquisition engine of this device driver instance.
    /**
     *  Calling this function will manually start this device driver's acquisition engine. This will only
     *  have an effect on the overall behaviour if \b mvIMPACT::acquire::Device::acquisitionStartStopBehaviour is
     *  set to \b mvIMPACT::acquire::assbUser.
     *
     *  If supported by the device driver, starting and stopping the acquisition engine manually can sometimes
     *  help to overcome capture queue underruns or certain restrictions in the underlying device driver
     *  technology.
     *
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::acquisitionStop, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle, \n
     *  \b mvIMPACT::acquire::Request::unlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor, \n
     *  \b mvIMPACT::acquire::Request::configure, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure
     *
     * \since 1.12.11
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - \b mvIMPACT::acquire::DMR_FEATURE_NOT_AVAILABLE if this device/driver combination does not support manual control over the acquisition engine. This will also happen if \b mvIMPACT::acquire::Device::acquisitionStartStopBehaviour is \b NOT set to \b mvIMPACT::acquire::assbUser.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int acquisitionStart( void ) const
    {
        return DMR_AcquisitionStart( m_pRefData->m_pDevice->hDrv() );
    }
    /// \brief Manually stops the acquisition engine of this device driver instance.
    /**
     *  Calling this function will manually stop this device drivers acquisition engine. This will only
     *  have effect on the overall behaviour, if \b mvIMPACT::acquire::Device::acquisitionStartStopBehaviour is
     *  set to \b mvIMPACT::acquire::assbUser.
     *
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::acquisitionStart, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle, \n
     *  \b mvIMPACT::acquire::Request::unlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor, \n
     *  \b mvIMPACT::acquire::Request::configure, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure
     *
     * \since 1.12.11
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - \b mvIMPACT::acquire::DMR_FEATURE_NOT_AVAILABLE if this device/driver combination does not support manual control over the acquisition engine. This will also happen if \b mvIMPACT::acquire::Device::acquisitionStartStopBehaviour is \b NOT set to \b mvIMPACT::acquire::assbUser.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int acquisitionStop( void ) const
    {
        return DMR_AcquisitionStop( m_pRefData->m_pDevice->hDrv() );
    }
    /// \brief Creates a new \b mvIMPACT::acquire::ImageRequestControl object.
    /**
     *  This function creates a new \b mvIMPACT::acquire::ImageRequestControl based on an existing one. New \b mvIMPACT::acquire::ImageRequestControl instances can only be derived
     *  from \b mvIMPACT::acquire::ImageRequestControl instances that already exist. When the driver has been initialized there will be at least
     *  one base \b mvIMPACT::acquire::ImageRequestControl called 'Base', which acts as the base for all other request controls.
     *
     *  All \b mvIMPACT::acquire::ImageRequestControl constructed by the application must be derived either from this base or any of its children using this function.
     *
     *  When this function succeeds, the \b mvIMPACT::acquire::ImageRequestControl constructor can be called with the \a name parameter passed to this function
     *  to get access to this newly registered \b mvIMPACT::acquire::ImageRequestControl.
     *
     *  \note
     *  See all comments made under \b mvIMPACT::acquire::FunctionInterface::createSetting for understanding the relationship between base and
     *  derived \b mvIMPACT::acquire::ImageRequestControl objects.
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int createImageRequestControl(
        /// [in] The name of the new \b mvIMPACT::acquire::ImageRequestControl object.
        const std::string& name,
        /// [in] The name of the \b mvIMPACT::acquire::ImageRequestControl the new object shall be derived from.
        const std::string& parent = "Base",
        /// [out] A pointer to a \b mvIMPACT::acquire::ComponentList object that will receive the ID of the newly created request control.
        /// This parameter can be 0 if the application is not interested in that parameter.
        ComponentList* pNewRequestControl = 0 )
    {
        HLIST newID;
        int result = DMR_CreateRequestControl( m_pRefData->m_pDevice->hDrv(), name.c_str(), parent.c_str(), &newID, 0 );
        if( pNewRequestControl )
        {
            *pNewRequestControl = ComponentList( newID );
        }
        return result;
    }
    /// \brief Creates a new setting.
    /**
     *  This function creates a new setting base on an existing one. New settings can only be derived
     *  from settings that already exist. When the driver has been initialized there will be at least
     *  one base setting called 'Base', which acts as the base for all other settings.
     *
     *  When a new setting is created it derives all the properties from the parent setting. That means
     *  initially the new setting will contain the very same data as the parent setting. As long as a
     *  component hasn't been modified in the new setting it will depend on the parent settings data.
     *  That means if e.g. a property in the parent list is modified, the newly created setting will
     *  also benefit from the updated value.
     *
     *  To release a certain component from this dependency it must be assigned a new value. The function
     *  \b mvIMPACT::acquire::Component::isDefault will return false afterwards indicating that the component no longer
     *  depends on the parent.
     *
     *  To restore this parent <-> child dependency the user can call the function
     *  \b mvIMPACT::acquire::Component::restoreDefault. Afterwards settings applied to the parent component
     *  will also be visible in the child component again.
     *
     *  When a new setting has been created successfully the name used to create the setting can
     *  be passed to any of the constructors of the setting related classes (\b mvIMPACT::acquire::CameraSettingsBase,
     *  \b mvIMPACT::acquire::ImageProcessing, ...) to access the new components.
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int createSetting(
        /// [in] The name of the setting to be created.
        const std::string& name,
        /// [in] The name of the setting to derive the new setting from.
        const std::string& parent = "Base",
        /// [out] A pointer to a \b mvIMPACT::acquire::ComponentList object that will receive the ID of the newly created setting.
        /// This parameter can be 0 if the application is not interested in that parameter.
        ComponentList* pNewSetting = 0 )
    {
        HLIST newID = INVALID_ID;
        int result = DMR_CreateSetting( m_pRefData->m_pDevice->hDrv(), name.c_str(), parent.c_str(), &newID );
        updateSettings();
        if( pNewSetting )
        {
            if( newID == INVALID_ID )
            {
                *pNewSetting = ComponentList();
            }
            else
            {
                *pNewSetting = ComponentList( newID );
            }
        }
        return result;
    }
    /// \brief Deletes the last setting from the setting stack.
    /**
     *  This function deletes the last setting from the setting stack.
     *
     *  See <b>mvIMPACT::acquire::FunctionInterface::saveCurrentSettingOnStack</b> for an example how to use this feature.
     *
     * \sa
     * \b mvIMPACT::acquire::FunctionInterface::saveCurrentSettingOnStack \n
     * \b mvIMPACT::acquire::FunctionInterface::loadSettingFromStack \n
     * \b mvIMPACT::acquire::FunctionInterface::loadAndDeleteSettingFromStack \n
     *
     *  \since 2.19.0
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if the setting is available.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int deleteSettingFromStack( void )
    {
        return m_pRefData->deleteSettingFromStack();
    }
    /// \brief Deletes a setting from the specified location.
    /**
     *  This function deletes a setting from the specified location.
     *
     *  \since 2.19.0
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if the setting is available.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int deleteSetting(
        /// [in] The name or the full path under where the setting is located.
        const std::string& name,
        /// [in] The location of the setting.
        TStorageLocation storageLocation = slNative,
        /// [in] Specifies the scope of this operation.
        TScope scope = sGlobal ) const
    {
        return DMR_DeleteSetting( name.c_str(), storageLocation, scope );
    }
    /// \brief Returns the names of the settings available for this \b mvIMPACT::acquire::Device.
    /**
     *  This function returns a const reference to a string array containing the names of all settings available
     *  for the current \b mvIMPACT::acquire::Device. These names are valid constructor parameters for objects
     *  like \b mvIMPACT::acquire::CameraSettingsBase, \b mvIMPACT::acquire::ImageProcessing, \b mvIMPACT::acquire::ImageDestination or
     *  classes derived from these types.
     *
     *  New settings can be created by calling
     *  \b mvIMPACT::acquire::FunctionInterface::createSetting
     *  \return A const reference to an array containing the names of all request controls available.
     */
    const std::vector<std::string>& getAvailableSettings( void ) const
    {
        updateSettings();
        return m_pRefData->m_settings;
    }
    /// \brief Returns the names of the image request controls available for this \b mvIMPACT::acquire::Device.
    /**
     *  This function returns a const reference to a string array containing the names of all image request controls available
     *  for the current \b mvIMPACT::acquire::Device. These names are valid constructor parameters for objects
     *  of the type \b mvIMPACT::acquire::ImageRequestControl.
     *
     *  New image request controls can be created by calling \b mvIMPACT::acquire::FunctionInterface::createImageRequestControl.
     *  \return A const reference to an array containing the names of all settings available.
     */
    const std::vector<std::string>& getAvailableImageRequestControls( void ) const
    {
        updateImageRequestControls();
        return m_pRefData->m_imageRequestControls;
    }
    /// \brief Returns a pointer to the desired \b mvIMPACT::acquire::Request.
    /**
     *  This function returns a pointer to the \b mvIMPACT::acquire::Request stored at \a nr
     *  in the internal array of requests.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr refers to an invalid \b mvIMPACT::acquire::Request \n
     *  (e.g. when \a nr is higher than the actual number of \n
     *  available requests) an STL out_of_range exception will be thrown.
     *  \endif
     *  \return A pointer to a \b mvIMPACT::acquire::Request object.
     */
    Request* getRequest(
        /// [in] The number of the request to return
        int nr ) const
    {
        updateRequests();
        Request* pRequest = m_pRefData->m_requests.at( nr );
        if( !pRequest->imageWidth.isValid() || pRequest->imageWidth.parent().parent().name() != pRequest->getName() )
        {
            // This could happen because someone changed the request count back and forth to the same value as the
            // last time 'getRequest' got called. In that case 'updateRequests' will do nothing and we need to update
            // this object here!
            delete m_pRefData->m_requests[nr];
            pRequest = createRequest( nr );
            m_pRefData->m_requests[nr] = pRequest;
        }
        return pRequest;
    }
    /// \brief Returns a \b mvIMPACT::acquire::ComponentList object to a setting with a specified name.
    /**
     *  This function returns a \b mvIMPACT::acquire::ComponentList object to a setting with a specified name
     *  or will raise an exception if no such setting exists.
     *
     *  \since 1.12.58
     *
     *  \return A \b mvIMPACT::acquire::ComponentList object to a setting with a specified name
     */
    ComponentList getSetting(
        /// [in] The name of the setting to locate
        const std::string& name ) const
    {
        Component it( m_pRefData->m_settingsList );
        it = it.firstChild();
        while( it.isValid() )
        {
            if( name == it.name() )
            {
                return ComponentList( it );
            }
            ++it;
        }
        std::ostringstream oss;
        oss << MVIA_FUNCTION << " (line: " << __LINE__ << ")";
        throw EComponentNotFound( "Setting '" + name + "' could not be found", oss.str() );
    }
    /// \brief Sets a request into configuration mode.
    /**
     *  \note
     *  Another version of this function is available that might be nicer to use depending on personal
     *  preferences and use case: \b mvIMPACT::acquire::Request::configure.
     *
     *  In configuration mode certain properties like \b mvIMPACT::acquire::Request::imageData,
     *  \b mvIMPACT::acquire::Request::imageSize, \b mvIMPACT::acquire::Request::imageMemoryMode
     *  of a request object can be modified. This can be used to configure one or more requests
     *  to use a user supplied memory. To use only a subset of the \b mvIMPACT::acquire::Request
     *  objects available the \b mvIMPACT::acquire::ImageRequestControl::requestToUse feature
     *  can be used.
     *
     *  Only requests that are currently not used by the driver and are not locked
     *  because they contain image data that hasn't been processed can be set into
     *  configuration mode.
     *
     *  \note
     *  Instead of calling this function directly for most cases it is much more convenient to use
     *  the functions \b mvIMPACT::acquire::Request::attachUserBuffer and \b mvIMPACT::acquire::Request::detachUserBuffer
     *  instead.
     *
     *  User supplied buffers must follow the alignment and size requirements reported by versions of the
     *  function \b mvIMPACT::acquire::FunctionInterface::getCurrentCaptureBufferLayout. Calling
     *  a version of this function will return all the information required to allocate buffers that
     *  can be used to capture data for the specified settings.
     *
     *  When allocating memory on the heap, the complete buffer size is needed which is calculated like
     *  this:
     *
     *  \b size + alignment
     *
     *  \note
     *  The address passed to the request object must be aligned already!
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  Device* pDev = getDevicePointerFromSomewhere()
     *  FunctionInterface fi( pDev );
     *  ImageRequestControl irc( pDev );
     *  int bufferSize = 0;
     *  int bufferAlignment = 0;
     *  const TDMR_ERROR result = static_cast<TDMR_ERROR>( fi.getCurrentCaptureBufferLayout( irc, bufferSize, bufferAlignment ) );
     *  Request* pRequest = fi.getRequest( 0 );
     *  // the buffer assigned to the request object must be aligned accordingly
     *  // the size of the user supplied buffer MUST NOT include the additional size
     *  // caused by the alignment
     *  if( pRequest->attachUserBuffer( getAlignedMemoryPtr( bufferSize, bufferAlignment ), bufferSize ) == DMR_NO_ERROR )
     *  {
     *    irc.requestToUse.write( 0 ); // use the buffer just configured for the next image request
     *    // now the next image will be captured into the user supplied memory
     *    fi.imageRequestSingle( &irc ); // this will send request '0' to the driver
     *    // wait for the buffer. Once it has been returned by the driver AND the user buffer shall no
     *    // longer be used call
     *    if( pRequest->detachUserBuffer() != DMR_NO_ERROR )
     *    {
     *      // handle error
     *    }
     *    // now this request will use internal memory again.
     *  }
     *  else
     *  {
     *     // handle error
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \attention There is currently no way to deal with alignment in Java when capturing into user supplied(thus managed) memory! Suggestions welcome!
     *
     * \code
     *  import java.nio.ByteBuffer;
     *
     * // ...
     *
     *  Device pDev = getDevicePointerFromSomewhere()
     *  FunctionInterface fi = new FunctionInterface( pDev );
     *  ImageRequestControl irc = new ImageRequestControl( pDev );
     *  int[] bufferSize = {0};
     *  int[] bufferAlignment = {0};
     *  if( fi.getCurrentCaptureBufferLayout( irc, bufferSize, bufferAlignment ) == TDMR_ERROR.DMR_NO_ERROR )
     *  {
     *    Request pRequest = fi.getRequest( 0 );
     *    // the buffer assigned to the request object must be aligned accordingly
     *    // the size of the user supplied buffer MUST NOT include the additional size
     *    // caused by the alignment
     *    ByteBuffer pBuffer = ByteBuffer.allocateDirect( bufferSize[0] + bufferAlignment[0] ); // todo: There is currently no way to deal with alignment in Java! Suggestions welcome!
     *    if( pRequest.attachUserBuffer( pBuffer ) == TDMR_ERROR.DMR_NO_ERROR )
     *    {
     *      irc.getRequestToUse().write( 0 ); // use the buffer just configured for the next image request
     *      // now the next image will be captured into the user supplied memory
     *      fi.imageRequestSingle( irc ); // this will send request '0' to the driver
     *      // wait for the buffer. Once it has been returned by the driver AND the user buffer shall no
     *      // longer be used call
     *      if( pRequest.detachUserBuffer() != TDMR_ERROR.DMR_NO_ERROR )
     *      {
     *        // handle error
     *      }
     *      // now this request will use internal memory again.
     *    }
     *    else
     *    {
     *       // handle error
     *    }
     *  }
     *  else
     *  {
     *     // handle error
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  pDev = getDevicePointerFromSomewhere()
     *  fi = acquire.FunctionInterface(pDev)
     *  irc = acquire.ImageRequestControl(pDev)
     *  # this function returns a list containing [result, size, alignment]
     *  results = fi.getCurrentCaptureBufferLayout(irc)
     *  if results[0] == int(acquire.DMR_NO_ERROR):
     *    pRequest = fi.getRequest(0)
     *    # the buffer assigned to the request object must be aligned accordingly
     *    # the size of the user supplied buffer MUST NOT include the additional size
     *    # caused by the alignment
     *    if pRequest.attachUserBuffer(getAlignedMemoryPtr(results[1], results[2] ), results[2]) == int(acquire.DMR_NO_ERROR):
     *      irc.requestToUse.write(0) # use the buffer just configured for the next image request
     *      # now the next image will be captured into the user supplied memory
     *      fi.imageRequestSingle(irc) # this will send request '0' to the driver
     *      # wait for the buffer. Once it has been returned by the driver AND the user buffer shall no
     *      # longer be used call
     *      if pRequest.detachUserBuffer() != TDMR_ERROR.DMR_NO_ERROR:
     *        # handle error
     *      # now this request will use internal memory again.
     *    else:
     *       # handle error
     *  else:
     *     # handle error
     * \endcode
     * \endif
     *  \note
     *  A request that is in configuration mode can't be sent to the driver for acquisition until
     *  \b mvIMPACT::acquire::Request::unlock or \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock has been called again.
     *  By using \b mvIMPACT::acquire::Request::attachUserBuffer and \b mvIMPACT::acquire::Request::detachUserBuffer this locking
     *  and unlocking is done internally thus the application does not need to worry about this.
     *
     *  \sa
     *  \b mvIMPACT::acquire::Request::configure, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle, \n
     *  \b mvIMPACT::acquire::Request::attachUserBuffer, \n
     *  \b mvIMPACT::acquire::Request::detachUserBuffer, \n
     *  \b mvIMPACT::acquire::Request::unlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestReset
     *
     * \since 1.10.31
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int imageRequestConfigure(
        /// [in] A const pointer to the request object to configure
        const Request* pRequest ) const
    {
        return DMR_ImageRequestConfigure( m_pRefData->m_pDevice->hDrv(), pRequest->getNumber(), 0, 0 );
    }
    /// \brief Returns the number of \b mvIMPACT::acquire::Request objects in the result queue .
    /**
     *  This functions queries the number of \b mvIMPACT::acquire::Request objects currently in the result queue that are available for pickup. This number reflects the number of
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor calls that could be executed afterwards the would return with a valid \b mvIMPACT::acquire::Request
     *  object immediately without waiting!
     *
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::acquisitionStart, \n
     *  \b mvIMPACT::acquire::FunctionInterface::acquisitionStop, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestReset, \n
     *  \b mvIMPACT::acquire::Request::unlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestResultQueueElementCount, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor \n
     *  \b mvIMPACT::acquire::Request::configure, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure
     *
     * \since 2.9.0
     *
     *  \return
     *  - The number of \b mvIMPACT::acquire::Request objects in the result queue if successful.
     *  - \b mvIMPACT::acquire::DMR_INVALID_QUEUE_SELECTION if the selected result queue does not exist.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int imageRequestResultQueueElementCount(
        /// [in] The result queue to be queried.
        int queueNr = 0 ) const
    {
        int resultQueueElements;
        TDMR_ERROR result = DMR_ImageRequestResultQueueElementCount( m_pRefData->m_pDevice->hDrv(), queueNr, &resultQueueElements );
        return ( result != DMR_NO_ERROR ) ? static_cast<int>( result ) : resultQueueElements;
    }
    /// \brief Deletes all requests currently queued for the specified \b mvIMPACT::acquire::ImageRequestControl.
    /**
     *  This function will terminate all running image acquisitions associated with the queue
     *  bound to the specified image request control and in addition to that
     *  will empty the queue of pending image requests for that queue. Also all requests that reside in the
     *  result queue and have not been picked up by the application will be unlocked and removed from the
     *  result queue. So after this function returns only the requests currently in possession of the
     *  application (so requests that have been picked up by successful calls to \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor
     *  that have \b NOT been unlocked) need to be handled. All other requests are in a state where they
     *  can be queued for an acquisition again.
     *
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle, \n
     *  \b mvIMPACT::acquire::Request::unlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor, \n
     *  \b mvIMPACT::acquire::Request::configure, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int imageRequestReset(
        /// [in] The \b mvIMPACT::acquire::ImageRequestControl for which all
        /// the requests shall be cancelled.
        int requestCtrlNr,
        /// [in] Currently unsupported. MUST be set 0.
        int mode ) const
    {
        return DMR_ImageRequestReset( m_pRefData->m_pDevice->hDrv(), requestCtrlNr, mode );
    }
#ifndef WRAP_ANY
    /// \brief Sends an image request to the \b mvIMPACT::acquire::Device driver.
    /**
     *  This functions sends a single image request to the capture device. To wait for the image
     *  to become ready call the function
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor.
     *
     *  \attention
     *  In order to make sure that no image data is lost, it is important to understand how
     *  the request mechanism works. The driver works with a fixed number of \b mvIMPACT::acquire::Request
     *  objects. The number of \b mvIMPACT::acquire::Request objects available to the driver can be set
     *  by modifying the property \b mvIMPACT::acquire::SystemSettings::requestCount. Each \b mvIMPACT::acquire::Request will
     *  consume a certain amount of memory. Once an image has been captured by the \b mvIMPACT::acquire::Request,
     *  this amount will be slightly more than the image itself needs in memory, so modify this
     *  parameter gently. On the other hand, it's necessary to have more than a single request
     *  in order to ensure a lossless acquisition. E.g. when working with free running cameras an
     *  image might be lost because while an image has been captured and is being processed, the next
     *  vertical sync. pulse is already missed before the \b mvIMPACT::acquire::Request is unlocked again.
     *
     *  \note
     *  When \b mvIMPACT::acquire::Device::acquisitionStartStopBehaviour is
     *  set to \b mvIMPACT::acquire::assbUser several calls to \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle
     *  will \b NOT start the data acquisition! After requests have been sent down to the driver,
     *  \b mvIMPACT::acquire::FunctionInterface::acquisitionStart must be called. For performance reasons some device drivers
     *  will \b NOT allow to request data into buffers which have not been known to the driver when \b mvIMPACT::acquire::FunctionInterface::acquisitionStart
     *  was called, thus before starting the acquisition, \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle
     *  should be called as many times as there are request objects.
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::acquisitionStart, \n
     *  \b mvIMPACT::acquire::FunctionInterface::acquisitionStop, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestReset, \n
     *  \b mvIMPACT::acquire::Request::unlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestResultQueueElementCount, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor, \n
     *  \b mvIMPACT::acquire::Request::configure, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - \b mvIMPACT::acquire::DEV_NO_FREE_REQUEST_AVAILABLE if all mvIMPACT::acquire::Request objects are currently in use (either owned by the user or queued for acquisition).
     *  - \b mvIMPACT::acquire::DEV_INVALID_REQUEST_NUMBER if the request number defined by the property \b ImageRequestControl::requestToUse is invalid (out of bounds).
     *  - \b mvIMPACT::acquire::DEV_REQUEST_ALREADY_IN_USE if the request number defined by the property \b ImageRequestControl::requestToUse is already in use (either owned by the user or queued for acquisition).
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int imageRequestSingle(
        /// [in] A pointer to the \b mvIMPACT::acquire::ImageRequestControl object
        /// to be used for this request. \b mvIMPACT::acquire::ImageRequestControl
        /// objects define (among other things), which setting will
        /// be used for this image acquisition (via the property
        /// \b mvIMPACT::acquire::ImageRequestControl::setting). If this pointer is 0 the default request control will be used
        /// for this operation.
        ImageRequestControl* pImageRequestControl = 0,
        /// [out] If a valid pointer to an integer is passed here, this
        /// variable receives the number of the \b mvIMPACT::acquire::Request which
        /// will be used to process this request.
        int* pRequestUsed = 0 ) const
    {
        return DMR_ImageRequestSingle( m_pRefData->m_pDevice->hDrv(), pImageRequestControl ? pImageRequestControl->hObj() & 0xFFFF : 0, pRequestUsed );
    }
#endif // #ifndef WRAP_ANY
    /// \brief Unlocks the request for the driver again.
    /**
     * \note
     *  Another version of this function is available that might be nicer to use depending on personal
     *  preferences and use case: \b mvIMPACT::acquire::Request::unlock. Unlocking a certain request
     *  might be nicer by using this function, e.g. unlocking \b ALL requests in a loop is probably easier
     *  done by writing
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  Device* pDev = getDevicePointerFromSomewhere()
     *  FunctionInterface fi( pDev );
     *  const int rc = static_cast< int >( fi.requestCount() );
     *  for( int i=0; i<rc; i++ )
     *  {
     *    fi.imageRequestUnlock( i );
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  Device pDev = getDevicePointerFromSomewhere()
     *  FunctionInterface fi = new FunctionInterface( pDev );
     *  final long rc = fi.requestCount();
     *  for( long i=0; i<rc; i++ )
     *  {
     *    fi.imageRequestUnlock( ( int )i );
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  pDev = getDevicePointerFromSomewhere()
     *  fi = acquire.FunctionInterface(pDev)
     *  rc = fi.requestCount()
     *  for i in range(rc):
     *    fi.imageRequestUnlock(i)
     * \endcode
     * \endif
     *
     *  To ensure that no image data is overwritten by another image request while the user still
     *  deals with the image from a previous acquisition each image buffer will be locked by the driver when
     *  it is returned to the user by a call to \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor.
     *  No new image will be captured into the same buffer until the user unlocks the buffer again
     *  by calling \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock.
     *
     *  \note
     *  After unlocking a request it is no longer guaranteed that the memory once referenced by the
     *  request and the image buffer belonging to it stays valid, so do \b NEVER try to access
     *  memory belonging to an unlocked request object. If you need to copy the image buffer or
     *  modify it in any other way, do everything you have to do \b BEFORE calling this function!
     *
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestReset, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestResultQueueElementCount, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestConfigure, \n
     *  \b mvIMPACT::acquire::Request::configure
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - \b mvIMPACT::acquire::DEV_REQUEST_CANT_BE_UNLOCKED if the request number defined by \a nr is currently not owned by the application (either already unlocked or queued for acquisition).
     *  - \b mvIMPACT::acquire::DMR_INPUT_BUFFER_TOO_SMALL if the request number defined by \a nr has been configured to capture into a user supplied buffer but the buffer is too small to acquire data into.
     *  - \b mvIMPACT::acquire::DEV_REQUEST_BUFFER_MISALIGNED if the request number defined by \a nr has been configured to capture into a user supplied buffer but this buffer is not aligned in order to the alignment restrictions reported by this driver/device combination.
     *  - \b mvIMPACT::acquire::DEV_REQUEST_BUFFER_INVALID if the request number defined by \a nr has been configured to capture into a user supplied buffer but an invalid (NULL) pointer has been attached to the request.
     *  - \b mvIMPACT::acquire::DEV_INVALID_REQUEST_NUMBER if the request number defined by \a nr is invalid (out of bounds).
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int imageRequestUnlock(
        /// [in] The number of the request to unlock. This is typically
        /// a value returned from a call to
        /// \b mvIMPACT::acquire::FunctionInterface::imageRequestWaitFor.
        int nr ) const
    {
        return DMR_ImageRequestUnlock( m_pRefData->m_pDevice->hDrv(), nr );
    }
    /// \brief Waits for a request object to become ready.
    /**
     *  This function waits for a request object previously sent to the capture device by calling
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle. When a new request became ready during
     *  the period of time specified by the \a timeout_ms parameter this request is extracted from the
     *  result queue and is returned to the user so the same request can not be returned twice until
     *  it has been processed and unlocked by the application.
     *
     *  \note Whenever a \b mvIMPACT::acquire::Request is returned to the user the image data
     *  described by the \b mvIMPACT::acquire::Request remains valid until the user unlocks
     *  the image buffer again or the driver is closed.
     *
     *  \sa
     *  \b mvIMPACT::acquire::Request::unlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestUnlock, \n
     *  \b mvIMPACT::acquire::FunctionInterface::imageRequestResultQueueElementCount, \n
     *  \b mvIMPACT::acquire::FunctionInterface::getRequest
     *  \return If the return value is greater than or equal to zero, the return value is the request number of the
     *  image request in the interface's internal array of image requests. In this case the user
     *  can call \b mvIMPACT::acquire::FunctionInterface::getRequest to get access to the
     *  results. \n \n If the result is negative, the return value is an error code.
     *  The error code that is returned in most cases will be \b mvIMPACT::acquire::DEV_WAIT_FOR_REQUEST_FAILED.
     *  To find out possible reasons for this error, look at the corresponding explanation.
     */
    int imageRequestWaitFor(
        /// [in] The maximum wait time in milliseconds (ms) for
        /// this request to become ready. If \a timeout_ms
        /// is '-1', the function's timeout interval never
        /// elapses. If the result queue specified by the \a queueNr parameter already contains
        /// a request when calling this function the function will return immediately. Please note
        /// that each request has its own timeout that is independent from
        /// this wait timeout, thus this function will return with a valid request after the timeout
        /// for this request has elapsed even if e.g. a trigger has not been detected. For detailed
        /// information on the interaction of the timeout of this function and the timeout of a
        /// request please refer to the chapter \ref ImageAcquisition_capture_AcquiringData in the C++ section.
        int timeout_ms,
        /// [in] The queue where to wait for the request.
        /// The number of request queues available depends on the number of video channels offered by the
        /// device. The queue a processed request ends up in can be defined by setting the property
        /// \b mvIMPACT::acquire::ImageRequestControl::resultQueue \b BEFORE calling \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle.
        int queueNr = 0 ) const
    {
        int requestNr;
        TDMR_ERROR result = DMR_ImageRequestWaitFor( m_pRefData->m_pDevice->hDrv(), timeout_ms, queueNr, &requestNr );
        return ( result != DMR_NO_ERROR ) ? static_cast<int>( result ) : requestNr;
    }
#ifndef WRAP_ANY
    /// \brief Returns information about the current capture buffer requirements.
    /**
     *  When an application wants to provide capture buffers, this function will be needed in order to
     *  get information on how the capture buffers must be constructed. The most important parameters
     *  will probably be \a alignment and \a size, thus for most application calling the other overload
     *  of this function will probably be enough.
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  To find out more about capturing to user memory please refer to the application
     *  \ref CaptureToUserMemory.cpp
     *  \endif
     *
     *  \sa mvIMPACT::acquire::Request::configure
     *
     *  \since 1.12.68
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int getCurrentCaptureBufferLayout(
        /// [in] A reference to the \b mvIMPACT::acquire::ImageRequestControl object
        /// containing the setting for which the current capture buffer layout shall
        /// be queried. The setting can be defined via the property
        /// \b mvIMPACT::acquire::ImageRequestControl::setting.
        ImageRequestControl& imageRequestControl,
        /// [out] On a successful call this variable will receive a pointer to a
        /// \b mvIMPACT::acquire::Request object reflecting the current
        /// capture buffer layout.
        Request** ppRequest = 0,
        /// [out] On a successful call this variable will receive the alignment
        /// needed for capturing into user supplied buffers that use the
        /// current settings.
        int* pAlignment = 0 ) const
    {
        int result = DMR_NO_ERROR;
        if( ppRequest )
        {
            if( !m_pRefData->m_pCurrentCaptureBufferLayout )
            {
                // This feature is available for every driver, but could not be detected thus an
                // update might be required.
                return DMR_NEWER_LIBRARY_REQUIRED;
            }
            const TImageRequestControlMode previousMode( static_cast<TImageRequestControlMode>( imageRequestControl.mode.read() ) );
            if( previousMode != ircmUpdateBufferLayout )
            {
                imageRequestControl.mode.write( ircmUpdateBufferLayout );
            }
            result = imageRequestSingle( &imageRequestControl );
            if( previousMode != ircmUpdateBufferLayout )
            {
                imageRequestControl.mode.write( previousMode );
            }
            *ppRequest = m_pRefData->m_pCurrentCaptureBufferLayout;
        }
        if( pAlignment )
        {
            *pAlignment = m_pRefData->m_captureBufferAlignment.read();
        }
        return result;
    }
#endif // #ifndef WRAP_ANY
    /// \brief Returns information about the current capture buffer requirements.
    /**
     *  When an application wants to provide capture buffers, this function will be needed in order to
     *  get information on how the capture buffers must be constructed.
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  To find out more about capturing to user memory please refer to the application
     *  \ref CaptureToUserMemory.cpp
     *  \endif
     *
     *  \sa
     *  \b mvIMPACT::acquire::Request::configure
     *
     *  \since 1.12.68
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int getCurrentCaptureBufferLayout(
        /// [in] A reference to the \b mvIMPACT::acquire::ImageRequestControl object
        /// containing the setting for which the current capture buffer layout shall
        /// be queried. The setting can be defined via the property
        /// \b mvIMPACT::acquire::ImageRequestControl::setting.
        ImageRequestControl& imageRequestControl,
        /// [out] On a successful call this variable will receive the size
        /// needed for capturing into user supplied buffers that use the
        /// current settings.
        int& size,
        /// [out] On a successful call this variable will receive the alignment
        /// needed for capturing into user supplied buffers that use the
        /// current settings.
        int& alignment ) const
    {
        Request* pRequest = 0;
        size = 0;
        const int result = getCurrentCaptureBufferLayout( imageRequestControl, &pRequest, &alignment );
        if( m_pRefData->m_pCurrentCaptureBufferLayout )
        {
            const unsigned int bufferPartCount = m_pRefData->m_pCurrentCaptureBufferLayout->getBufferPartCount();
            if( bufferPartCount > 0 )
            {
                for( unsigned int i = 0; i < bufferPartCount; i++ )
                {
                    size += static_cast<int>( m_pRefData->m_pCurrentCaptureBufferLayout->getBufferPart( i ).dataSize.read() );
                }
            }
            else
            {
                size = m_pRefData->m_pCurrentCaptureBufferLayout->imageSize.read();
            }
            size += m_pRefData->m_pCurrentCaptureBufferLayout->imageFooterSize.read();
        }
        return result;
    }
    /// \brief Check if \a nr specifies a valid \b mvIMPACT::acquire::Request.
    /**
     *  \return
     *  - true if \a nr specifies a valid request.
     *  - false otherwise
     */
    bool isRequestNrValid( int nr ) const
    {
        if( nr < 0 )
        {
            return false;
        }

        if( nr >= static_cast<int>( m_pRefData->m_requests.size() ) )
        {
            updateRequests();
        }

        return nr < static_cast<int>( m_pRefData->m_requests.size() );
    }
    /// \brief Checks if a certain setting is available under the specified location.
    /**
     *  This function checks if a certain setting is available under the specified location.
     *
     *  \since 2.19.0
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if the setting is available.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int isSettingAvailable(
        /// [in] The name or the full path under where the setting is located.
        const std::string& name,
        /// [in] The location of the setting.
        TStorageLocation storageLocation = slNative,
        /// [in] Specifies the scope of this operation.
        TScope scope = sGlobal ) const
    {
        return DMR_IsSettingAvailable( name.c_str(), storageLocation, scope );
    }
    /// \brief Loads a previously stored setting.
    /**
     *  This function can be used to restore a previously stored setting again.
     *
     *  To load a setting from a file the \b mvIMPACT::acquire::sfFile should be specified
     *  as part of \a storageFlags. To load a setting from a platform specific location
     *  such as the Registry under Windows&copy; \b mvIMPACT::acquire::sfNative should be
     *  specified. It's not allowed to combine \b mvIMPACT::acquire::sfFile and
     *  \b mvIMPACT::acquire::sfNative for this operation.
     *
     *  \attention Since mvIMPACT Acquire 2.9.0 GenICam devices will be able to save their properties in an XML File, only if the properties have the \b streamable attribute set (for more information refer to the <a href="http://www.emva.org/standards-technology/genicam/genicam-downloads/">GenICam standard specification</a>). Properties with no \b streamable attribute set, will be silently ignored when saving, which means they will \b not be saved in the XML file. For MATRIX VISION GenICam devices, starting with firmware version 1.6.414 the \b streamable attribute is set for all the necessary properties.
     *
     *  <BR>
     *
     *  \attention Since mvIMPACT Acquire 2.9.0 and again in version 2.11.0 storing and loading of camera settings in an XML file for the \b mvIMPACT::acquire::dilGenICam
     *  interface layout has been updated. As a result XML files created with newer versions of mvIMPACT Acquire might \b not
     *  be readable on systems with older version of mvIMPACT Acquire installed. XML files created on systems
     *  with earlier versions of mvIMPACT Acquire will always be readable this or newer versions. See the following table for details.
     *  <TABLE>
     *    <TR><TH>mvIMPACT Acquire Version<TH>Loading an XML settings file created with mvIMPACT Acquire version &lt; 2.9.0<TH>Loading an XML settings file created with mvIMPACT Acquire version 2.9.0 - 2.10.1<TH>Loading an XML settings file created with mvIMPACT Acquire version 2.11.0 or later
     *    <TR><TH> &lt; 2.9.0 <TD> YES <TD> NO <TD> NO
     *    <TR><TH> 2.9.0 - 2.10.1 <TD> YES <TD> YES <TD> NO
     *    <TR><TH> &gt;= 2.11.0 <TD> YES <TD> YES <TD> YES
     *  </TABLE>
     *
     *  \attention Since mvIMPACT Acquire 2.28.0 it is possible for devices operated in the \b ::dilGenICam interface layout to store settings including
     *  sequencer sets and user sets (see SFNC for details) data by specifying the \b ::sfProcessGenICamSequencerData and/or \b ::sfProcessGenICamUserSetData
     *  during the storage operation. Settings stored like this cannot be loaded by previous mvIMPACT Acquire versions.
     *
     *  \note For devices operated in the \b mvIMPACT::acquire::dilGenICam interface layout further restriction apply: Settings created with a certain product type can only
     *  be used with other devices belonging to the exact same type as defined by the property mvIMPACT::acquire::Device::product inside the device list (the one device specific property list that
     *  is accessible without initialising the device before). Even if a setting can be used with various firmware versions it is recommended to use one setting
     *  for multiple devices all updated to the very same firmware version to avoid compatibility problems.
     *
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::saveSetting.
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int loadSetting(
        /// [in] The name or the full path under where the setting is located.
        const std::string& name,
        /// [in] The flags which define which information shall be read from the location
        /// and how this information shall be interpreted.
        TStorageFlag storageFlags = sfNative,
        /// [in] Specifies where the information is located.
        TScope scope = sGlobal ) const
    {
        return DMR_LoadSetting( m_pRefData->m_pDevice->hDrv(), name.c_str(), storageFlags, scope );
    }
    /// \brief loads the last setting from the setting stack.
    /**
     *  This function loads the last setting from the setting stack.
     *
     *  See <b>mvIMPACT::acquire::FunctionInterface::saveCurrentSettingOnStack</b> for an example how to use this feature.
     *
     *  See also <b>mvIMPACT::acquire::FunctionInterface::loadSetting</b> to find out which features of a GenICam device
     *  are stored in a setting and which are not!
     *
     * \sa
     * \b mvIMPACT::acquire::FunctionInterface::saveCurrentSettingOnStack \n
     * \b mvIMPACT::acquire::FunctionInterface::deleteSettingFromStack \n
     * \b mvIMPACT::acquire::FunctionInterface::loadAndDeleteSettingFromStack \n
     *
     *  \since 2.19.0
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if the setting is available.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int loadSettingFromStack( void )
    {
        if( m_pRefData->m_settingsInRAM.empty() )
        {
            return PROPHANDLING_LIST_CANT_ACCESS_DATA;
        }
        return DMR_LoadSetting( m_pRefData->m_pDevice->hDrv(), m_pRefData->m_settingsInRAM.top().c_str(), sfRAM, sUser );
    }
    /// \brief loads the last setting from the setting stack and then removes this setting from the stack.
    /**
     *  This function loads the last setting from the setting stack and then removes this setting from the stack.
     *
     *  See <b>mvIMPACT::acquire::FunctionInterface::saveCurrentSettingOnStack</b> for an example how to use this feature.
     *
     *  See also <b>mvIMPACT::acquire::FunctionInterface::loadSetting</b> to find out which features of a GenICam device
     *  are stored in a setting and which are not!
     *
     * \sa
     * \b mvIMPACT::acquire::FunctionInterface::saveCurrentSettingOnStack \n
     * \b mvIMPACT::acquire::FunctionInterface::deleteSettingFromStack \n
     * \b mvIMPACT::acquire::FunctionInterface::loadSettingFromStack \n
     *
     *  \since 2.19.0
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if the setting is available.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int loadAndDeleteSettingFromStack( void )
    {
        int result = loadSettingFromStack();
        if( result == DMR_NO_ERROR )
        {
            result = deleteSettingFromStack();
        }
        return result;
    }
    /// \brief Loads the default settings.
    /**
     *  This function will try to load the settings from a default location. This function
     *  can only succeed if a setting has been stored previously by a call to
     *  \b mvIMPACT::acquire::FunctionInterface::saveSettingToDefault.
     *
     *  \attention There has been an incompatible change when loading settings in version 2.9.0 and 2.11.0 of mvIMPACT Acquire as well as in version 2.28.0. See <b>mvIMPACT::acquire::FunctionInterface::loadSetting</b> for details.
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int loadSettingFromDefault(
        /// [in] Specifies where the information is located.
        TScope scope = sUser ) const
    {
        return DMR_LoadSettingFromDefault( m_pRefData->m_pDevice->hDrv(), scope );
    }
    /// \brief Returns the number of available request objects.
    /**
     *  \sa
     *  \b mvIMPACT::acquire::SystemSettings::requestCount to change the number of request objects
     *
     *  \return Returns the number of available request objects.
     */
    unsigned int requestCount( void ) const
    {
        updateRequests();
        return static_cast<unsigned int>( m_pRefData->m_requests.size() );
    }
    /// \brief Saves the current setting on the setting stack.
    /**
     *  This function saves the current setting on the setting stack. Together which the
     *  functions mentioned below this implements a stack for capture settings. This can
     *  become handy when entering a section of code that might modify the current capture settings
     *  in various ways and depending on the result these modifications shall either be kept or
     *  discarded at the end of the operation.
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  // ...
     *  enum TResult
     *  {
     *    rApply,
     *    rDiscard
     *  };
     *  // ...
     *  FunctionInterface& fi = getFunctionInterfaceFromSomewhere();
     *  fi.saveCurrentSettingOnStack();
     *  switch( enterSectionThatModifiesDeviceSettings() )
     *  {
     *  case rDiscard:
     *      fi.loadAndDeleteSettingFromStack(); // revert all changes just applied without worrying about what these changes actually are
     *      break;
     *  case rApply:
     *      fi.deleteSettingFromStack(); // remove the setting from the stack, but keep changes
     *      break;
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  // ...
     *  final int Apply = 1;
     *  final int Discard = 2;
     *  // ...
     *  FunctionInterface fi = getFunctionInterfaceFromSomewhere();
     *  fi.saveCurrentSettingOnStack();
     *  final int option = enterSectionThatModifiesDeviceSettings();
     *  if( option == Discard )
     *  {
     *    fi.loadAndDeleteSettingFromStack(); // revert all changes just applied without worrying about what these changes actually are
     *  }
     *  else if( option == Apply )
     *  {
     *    fi.deleteSettingFromStack(); // remove the setting from the stack, but keep changes
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * DISCARD_SETTING = 1
     * APPLY_SETTING = 2
     * fi = getFunctionInterfaceFromSomewhere()
     * fi.saveCurrentSettingOnStack()
     * option = enterSectionThatModifiesDeviceSettings()
     * if option == DISCARD_SETTING: # discard
     *    fi.loadAndDeleteSettingFromStack() # revert all changes just applied without worrying about what these changes actually are
     * elif option == APPLY_SETTING: # apply
     *    fi.deleteSettingFromStack() # remove the setting from the stack, but keep changes
     * \endif
     *
     *  The stack makes use of mvIMPACT Acquires ability to store capture settings in the memory of
     *  the current process. Once the last instance of this <b>mvIMPACT::acquire::FunctionInterface</b>
     *  object is deleted all settings pushed on this stack will be deleted automatically.
     *
     * \sa
     * \b mvIMPACT::acquire::FunctionInterface::deleteSettingFromStack \n
     * \b mvIMPACT::acquire::FunctionInterface::loadSettingFromStack \n
     * \b mvIMPACT::acquire::FunctionInterface::loadAndDeleteSettingFromStack \n
     *
     *  \since 2.19.0
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if the setting is available.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int saveCurrentSettingOnStack(
        /// [in] The flags which define which information shall be stored and how this
        /// information shall be stored.
        TStorageFlag storageFlags = sfRAM )
    {
        return m_pRefData->saveCurrentSettingOnStack( storageFlags );
    }
    /// \brief Stores the current settings.
    /**
     *  This function can be used to store the current settings either in an XML-file or
     *  (under Windows&copy;) into the Registry. A setting contains all the values set
     *  for properties that control the overall way an image is acquired( e.g. the exposure time, etc.).
     *
     *  To store a setting in a file the \b mvIMPACT::acquire::sfFile should be specified
     *  as part of \a storageFlags. To store a setting in a platform specific location
     *  such as the Registry under Windows&copy; \b mvIMPACT::acquire::sfNative should be
     *  specified. Both flags can be combined. In that case the same setting will be stored in a
     *  file \b AND in a platform specific location if these location differ (platform dependent!).
     *
     *  \attention There has been an incompatible change when loading settings in version 2.9.0 and 2.11.0 of mvIMPACT Acquire as well as in version 2.28.0. See <b>mvIMPACT::acquire::FunctionInterface::loadSetting</b> for details.
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int saveSetting(
        /// [in] The name or the full path under which this setting shall be stored
        const std::string& name,
        /// [in] The flags which define which information shall be stored and how this
        /// information shall be stored.
        TStorageFlag storageFlags = sfNative,
        /// [in] Specifies where the information shall be stored.
        TScope scope = sGlobal ) const
    {
        return DMR_SaveSetting( m_pRefData->m_pDevice->hDrv(), name.c_str(), storageFlags, scope );
    }
    /// \brief Stores the current settings under a default location.
    /**
     *  Under Windows&copy; this will be in the Registry. A setting contains all the values set
     *  for properties that control the overall way an image is acquired( e.g. the exposure time, etc.).
     *
     *  \attention There has been an incompatible change when loading settings in version 2.9.0 and 2.11.0 of mvIMPACT Acquire as well as in version 2.28.0. See <b>mvIMPACT::acquire::FunctionInterface::loadSetting</b> for details.
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int saveSettingToDefault(
        /// [in] Specifies where the information shall be stored.
        TScope scope = sUser ) const
    {
        return DMR_SaveSettingToDefault( m_pRefData->m_pDevice->hDrv(), scope );
    }
};

//-----------------------------------------------------------------------------
/// \brief A base class to access various general information about the device and its driver.
/**
 *  This class contains a collection of properties providing various information about
 *  the device and its driver.
 *
 *  Instances of this class can't be constructed directly. Use one of the derived types.
 */
class Info : public ComponentCollection
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::Info object.
    explicit Info( /// A pointer to a \b mvIMPACT::acquire::Device object obtained from
        /// a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : ComponentCollection( pDev ), deviceDriverVersion(), driverDate(),
        driverVersion(), state(), loadedSettings(), logFile(), systemPhysicalProcessorCount(), systemLogicalProcessorCount(), captureBufferAlignment(),
        recommendedListsForUIs()
    {
        DeviceComponentLocator locator( pDev, dltInfo );
        m_hRoot = locator.searchbase_id();
        locator.bindComponent( deviceDriverVersion, "DeviceDriverVersion" );
        locator.bindComponent( driverDate, "DriverDate" );
        locator.bindComponent( driverVersion, "DriverVersion" );
        locator.bindComponent( state, "State" );
        locator.bindComponent( loadedSettings, "LoadedSettings" );
        locator.bindComponent( logFile, "LogFile" );
        locator.bindComponent( systemPhysicalProcessorCount, "SystemPhysicalProcessorCount" );
        locator.bindComponent( systemLogicalProcessorCount, "SystemLogicalProcessorCount" );
        locator.bindComponent( captureBufferAlignment, "CaptureBufferAlignment" );
        locator.bindComponent( recommendedListsForUIs, "RecommendedListsForUIs" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property \b (read-only) containing the device driver version used by this device.
    /**
     *  This is the version of the underlying hardware driver. For device drivers that don't have another
     *  user mode driver below the interface driver this property will contain the same version information
     *  as the property \b mvIMPACT::acquire::Info::driverVersion.
     */
    PropertyS deviceDriverVersion;
    /// \brief A string property \b (read-only) containing the date the device driver has been compiled.
    PropertyS driverDate;
    /// \brief A string property \b (read-only) containing the version number of the device driver.
    PropertyS driverVersion;
    /// \brief An enumerated integer property \b (read-only) containing the current state of this device.
    /**
     *  This property e.g. provides information about the current state of the device. For USB devices this can e.g. indicate whether
     *  a device is currently plugged into the system or not.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceState.
     *
     *  \b GenICam/GenTL \b device \b specific:
     *  In order to reduce the amount of network traffic to a minimum, this property will only be updated automatically
     *  for network devices if the property \b mvIMPACT::acquire::Device::registerErrorEvent is set to
     *  \b mvIMPACT::acquire::bTrue (which is the default behaviour). If the IP addresses stay the same the
     *  connection is automatically re-established then once the device is detected by the driver again.
     *  However if the IP address of the device and/or the network adapter of the system it is used from changes
     *  \b mvIMPACT::acquire::DeviceManager::updateDeviceList()
     *  must be called regardless of the value of \b mvIMPACT::acquire::Device::registerErrorEvent before a device
     *  that was lost can re-establish a connection to the capture driver.
     */
    PropertyIDeviceState state;
    /// \brief A string property \b (read-only) containing the name of the setting currently loaded.
    PropertyS loadedSettings;
    /// \brief A string property \b (read-only) containing the name and the full path of the current log-file for this device.
    PropertyS logFile;
    /// \brief An integer property \b (read-only) containing the number of physical processors detected in the current system.
    /**
     * \since 2.44.0
     */
    PropertyI systemPhysicalProcessorCount;
    /// \brief An integer property \b (read-only) containing the number of logical processors detected in the current system.
    /**
     * \since 2.44.0
     */
    PropertyI systemLogicalProcessorCount;
    /// \brief An integer property \b (read-only) containing the capture buffer alignment in bytes needed by this device driver.
    PropertyI captureBufferAlignment;
    /// \brief A string property \b (read-only) containing an array of full search paths to lists which are recommended to be displayed in a user interface that is created dynamically.
    PropertyS recommendedListsForUIs;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

#ifndef WRAP_ANY
/// \brief \b deprecated. Use the class \b mvIMPACT::acquire::Info instead.
/**
 *  \deprecated
 *  This class has been declared \b deprecated and might not be available in future releases.
 *  All features of this class are available in \b mvIMPACT::acquire::Info as well, so please use
 *  this class instead.
 */
typedef Info MVIMPACT_DEPRECATED_CPP( InfoBase );
#endif // #ifndef WRAP_ANY

//-----------------------------------------------------------------------------
/// \brief A base class for essential device related settings.
/**
 *  This class acts as a base class for essential device related settings. It only contains
 *  features that are available for every device.
 *
 *  \since 1.12.58
 *
 */
class BasicDeviceSettings : public ComponentCollection
//-----------------------------------------------------------------------------
{
public:
    /// brief Constructs a new \b mvIMPACT::acquire::BasicDeviceSettings object.
    explicit BasicDeviceSettings(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : ComponentCollection( pDev ), basedOn(), imageRequestTimeout_ms()
    {
        DeviceComponentLocator locator( pDev, dltSetting, settingName );
        locator.bindComponent( basedOn, "BasedOn" );
        locator.bindSearchBase( locator.searchbase_id(), "Camera" );
        m_hRoot = locator.searchbase_id();
        locator.bindComponent( imageRequestTimeout_ms, "ImageRequestTimeout_ms" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief A string property \b (read-only) containing the name of the setting this setting is based on.
    /**
     *  \since 1.12.67
     */
    PropertyS basedOn;
    /// \brief An integer property defining the maximum time to wait for an image in ms.
    /**
     * \attention Since mvIMPACT Acquire 2.32.0 the default value for this property has been changed! See \ref KnownIssuesPage_ApplicationTerminationWaitingForRequests for details.
     *
     *  When this property is set to 0 the timeout never elapses. If the timeout this property
     *  defines elapses the currently processed request will be returned to the user even if no data
     *  has been captured so far. The result structure of the request object should be examined in that
     *  case. Also this should be considered as an error from the users point of view in which case he
     *  should clean up the acquisition queue by calling \b mvIMPACT::acquire::FunctionInterface::imageRequestReset.
     *  Afterwards the capture loop can be restarted.
     *
     *  \note
     *  It is crucial to understand that this is a timeout <b>PER REQUEST</b>! The timespan taken into account for the measurement
     *  starts when the driver begins to capture data into <b>this particular buffer</b>! So when queuing 4 buffers with a timeout of 3000
     *  ms each and no data being transmitted by the device for any reason will cause the last buffer to time out 3000*4 = 12000 ms AFTER
     *  the buffer has been queued and the acquisition has been started as the driver will wait for up to 3 seconds for each buffer that is
     *  being processed. When the device sends data this timeout does not affect the runtime behaviour at all. No additional delay is introduced
     *  by it when everything runs as planned.
     */
    PropertyI imageRequestTimeout_ms;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A class to configure the behaviour of trigger signals.
/**
 *  Features in this class will open up a more flexible way to configure certain
 *  trigger events for devices then the previous features('triggerInterface',
 *  'triggerSource' and 'triggerMode' used.
 *
 *  \note
 *  Not ever device will support every property listed in this class for every trigger
 *  mode. Always call \b mvIMPACT::acquire::Component::isValid to check whether
 *  a feature is available or not before using it. Otherwise an exception will
 *  be generated.
 */
class TriggerControl : public ComponentCollection
//-----------------------------------------------------------------------------
{
    friend class CameraSettingsBlueCOUGAR;
    friend class CameraSettingsFrameGrabber;
    Method m_triggerSoftware;
    explicit TriggerControl( HLIST hList ) : ComponentCollection( hList ), m_triggerSoftware()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( m_triggerSoftware, "TriggerSoftware@i" );
        locator.bindComponent( triggerMode, "TriggerMode" );
        locator.bindComponent( triggerSource, "TriggerSource" );
        locator.bindComponent( triggerActivation, "TriggerActivation" );
        locator.bindComponent( triggerDivider, "TriggerDivider" );
        // unfortunately there are a couple of different names around...
        locator.bindComponent( triggerDelayAbs_us, "TriggerDelayAbs_us" );
        if( !triggerDelayAbs_us.isValid() )
        {
            locator.bindComponent( triggerDelayAbs_us, "TriggerDelayAbs" );
            if( !triggerDelayAbs_us.isValid() )
            {
                locator.bindComponent( triggerDelayAbs_us, "TriggerDelay" );
            }
        }
        locator.bindComponent( triggerDelayLines, "TriggerDelayLines" );
        locator.bindComponent( triggerOverlap, "TriggerOverlap" );
    }
public:
    /// \brief Returns a name of the trigger being configured.
    std::string getDescription( void ) const
    {
        return ComponentList( m_hRoot ).name();
    }
    /// \brief Generates of software trigger command.
    /**
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int triggerSoftware( void ) const
    {
        if( !m_triggerSoftware.isValid() )
        {
            return DMR_FEATURE_NOT_AVAILABLE;
        }
        return m_triggerSoftware.call();
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief Defines if the selected trigger is active.
    PropertyI64 triggerMode;
    /// \brief Defines the signal that will cause the trigger event.
    /**
     *  Currently this property will define a translation dictionary that can e.g. be queried via a call to
     *  \b mvIMPACT::acquire::PropertyI64::getTranslationDict. The resulting translation dictionary can be used
     *  to select the desired trigger source either via a string or the associated 64 bit integer value.
     */
    PropertyI64 triggerSource;
    /// \brief An enumerated 64 bit integer property that defines the start condition for the selected trigger.
    /**
     *  Valid value will be 'RisingEdge', 'FallingEdge', 'AnyEdge', 'LevelLow' or 'LevelHigh'.
     */
    PropertyI64 triggerActivation;
    /// \brief An integer property used to divide the number of incoming trigger pulses by an integer factor.
    /**
     *  E.g. setting this value to 2 would generate 5 internal trigger events from a 10 Hz external signal.
     */
    PropertyI triggerDivider;
    /// \brief Specifies the absolute delay in microseconds (us) to apply after the trigger reception before
    /// effectively activating it.
    PropertyF triggerDelayAbs_us;
    /// \brief Specifies the absolute delay in lines to apply after the trigger reception before effectively activating it.
    PropertyI triggerDelayLines;
    /// \brief Specifies the type trigger overlap permitted with the previous frame.
    ///
    /** This defines when a valid trigger will be accepted (or latched) for a new frame.
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceTriggerOverlap.
     */
    PropertyI64DeviceTriggerOverlap triggerOverlap;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief Properties to define the format of resulting images.
/**
 *  This class provides properties allowing the user to define how the resulting
 *  image should be created. Things like the width and height of the captured image
 *  can be defined here for example.
 */
class ImageDestination : public ComponentCollection
//-----------------------------------------------------------------------------
{
public:
    /// brief Constructs a new \b mvIMPACT::acquire::ImageDestination object.
    explicit ImageDestination(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : ComponentCollection( pDev ), pixelFormat(),
        scalerMode(), scalerInterpolationMode(), scalerAoiEnable(), scalerAoiHeight(), scalerAoiStartX(),
        scalerAoiStartY(), scalerAoiWidth(), imageWidth(), imageHeight()
    {
        DeviceComponentLocator locator( pDev, dltSetting, settingName );
        locator.bindSearchBase( locator.searchbase_id(), "ImageDestination" );
        m_hRoot = locator.searchbase_id();
        locator.bindComponent( pixelFormat, "PixelFormat" );
        locator.bindComponent( scalerMode, "ScalerMode" );
        locator.bindComponent( scalerInterpolationMode, "ScalerInterpolationMode" );
        locator.bindComponent( scalerAoiEnable, "ScalerAoiEnable" );
        if( locator.findComponent( "ScalerAoi" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "ScalerAoi" );
            locator.bindComponent( scalerAoiHeight, "H" );
            locator.bindComponent( scalerAoiStartX, "X" );
            locator.bindComponent( scalerAoiStartY, "Y" );
            locator.bindComponent( scalerAoiWidth, "W" );
        }
        locator.bindSearchBase( m_hRoot );
        locator.bindComponent( imageWidth, "ImageWidth" );
        locator.bindComponent( imageHeight, "ImageHeight" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the pixel format of the resulting image.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TImageDestinationPixelFormat.
     */
    PropertyIImageDestinationPixelFormat pixelFormat;
    /// \brief An integer property defining whether the image is scaled or not.
    /**
     *  \note
     *  This feature is available for every device! However currently only \b mvDELTA / \b mvSIGMA
     *  devices provide hardware support for \b REDUCING the image size. In this case the scaled width
     *  and height must be divisible by 4. For every other device this
     *  will be done by a software filter and therefore will introduce additional CPU load. Increasing
     *  the image size will always be done in software. When using the scaler the property
     *  \b mvIMPACT::acquire::Statistics::imageProcTime_s can be used to observe the additional
     *  CPU time needed for the image processing.
     */
    PropertyIScalerMode scalerMode;
    /// \brief An integer property defining the interpolation method used when the scaler is active.
    /**
     *  \note
     *  Whenever the property \b mvIMPACT::acquire::ImageDestination::scalerMode is set to
     *  \b mvIMPACT::acquire::smOff modifying or reading this property will have no effect.
     *  Call \b Component::isVisible to find out whether this property is currently active or not.
     *
     *  \note
     *  Please see remarks under \b mvIMPACT::acquire::ImageDestination::scalerMode. The interpolation mode
     *  currently will only be used when scaling is \b NOT done by the hardware.
     */
    PropertyIScalerInterpolationMode scalerInterpolationMode;
    /// \brief A boolean property defining whether an AOI, rather than the whole image, will be used for scaling.
    /**
     *  \note
     *  Whenever the property \b mvIMPACT::acquire::ImageDestination::scalerAoiEnable is set to
     *  \b mvIMPACT::acquire::bTrue the relevant AOI configuration properties will become visible.
     */
    PropertyIBoolean scalerAoiEnable;
    /// \brief An integer property defining the height of the AOI in pixel to be used for scaling.
    /**
     *  \note
     *  This property will be visible only when \b mvIMPACT::acquire::ImageDestination::scalerAoiEnable
     *  is set to \b mvIMPACT::acquire::bTrue.
     */
    PropertyI scalerAoiHeight;
    /// \brief An integer property defining the X-offset of the AOI in pixel to be used for the calculation.
    /**
     *  \note
     *  This property will be visible only when \b mvIMPACT::acquire::ImageDestination::scalerAoiEnable
     *  is set to \b mvIMPACT::acquire::bTrue.
     */
    PropertyI scalerAoiStartX;
    /// \brief An integer property defining the Y-offset of the AOI in pixel to be used for the calculation.
    /**
     *  \note
     *  This property will be visible only when \b mvIMPACT::acquire::ImageDestination::scalerAoiEnable
     *  is set to \b mvIMPACT::acquire::bTrue.
     */
    PropertyI scalerAoiStartY;
    /// \brief An integer property defining the width of the AOI in pixel to be used for the calculation.
    /**
     *  \note
     *  This property will be visible only when \b mvIMPACT::acquire::ImageDestination::scalerAoiEnable
     *  is set to \b mvIMPACT::acquire::bTrue.
     */
    PropertyI scalerAoiWidth;
    /// \brief An integer property defining the width of the scaled image.
    /**
     *  \note
     *  Whenever the property \b mvIMPACT::acquire::ImageDestination::scalerMode is set to
     *  \b mvIMPACT::acquire::smOff modifying or reading this property will have no effect.
     *  Call \b Component::isVisible to find out whether this property is currently active or not.
     *
     *  \note
     *  Please see remarks under \b mvIMPACT::acquire::ImageDestination::scalerMode.
     */
    PropertyI imageWidth;
    /// \brief An integer property defining the height of the scaled image.
    /**
     *  \note
     *  Whenever the property \b mvIMPACT::acquire::ImageDestination::scalerMode is set to
     *  \b mvIMPACT::acquire::smOff modifying or reading this property will have no effect.
     *  Call \b Component::isVisible to find out whether this property is currently active or not.
     *
     *  \note
     *  Please see remarks under \b mvIMPACT::acquire::ImageDestination::scalerMode.
     */
    PropertyI imageHeight;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief Properties to configure which information shall be attached to the resulting images.
/**
 *  This class provides properties allowing the user to define which additional information
 *  shall be attached to the resulting images. For example some devices can transmit the state
 *  of the digital I/Os at the time the exposure of an image has been started. Some information
 *  will always be attached to the resulting images other information will only be available
 *  if it has been explicitly enabled before.
 *
 *  \if DOXYGEN_CPP_DOCUMENTATION
 *
 *  \b EXAMPLE:
 *
 *  Enable the transmission of the \c LineStatusAll information in device interface layout
 *  <b>mvIMPACT::acquire::dilDeviceSpecific</b>:
 *
 * \code
 *  //-----------------------------------------------------------------------------
 *  void fn( Device* pDev )
 *  //-----------------------------------------------------------------------------
 *  {
 *     RequestInfoConfiguration ric( pDev );
 *     if( !ric.lineStatusAll.isValid() )
 *     {
 *        // feature not supported
 *        return;
 *     }
 *     ric.lineStatusAll.write( bTrue );
 *     Request* pRequest = captureAnImage( pDev );
 *     printf( "%s: 0x%08x\n", pRequest->chunkLineStatusAll.name().c_str(), static_cast< int >( pRequest->chunkLineStatusAll.read() ) );
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  //-----------------------------------------------------------------------------
 *  public void fn( Device pDev )
 *  //-----------------------------------------------------------------------------
 *  {
 *     RequestInfoConfiguration ric = new RequestInfoConfiguration( pDev );
 *     if( !ric.lineStatusAll.isValid() )
 *     {
 *        // feature not supported
 *        return;
 *     }
 *     ric.getLineStatusAll().write( TBoolean.bTrue );
 *     Request pRequest = captureAnImage( pDev );
 *     System.out.println( String.format( "%s: 0x%08x\n", pRequest.getChunkLineStatusAll().name(), ( int )( pRequest.getChunkLineStatusAll().read() ) ) );
 *  }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  def fn(pdev, pRequest):
 *    ric = acquire.RequestInfoConfiguration(pDev)
 *    if ric.lineStatusAll.isValid == False:
 *      # feature not supported
 *      return
 *    else:
 *      ric.lineStatusAll.write(acquire.bTrue)
 *      print(pRequest.chunkLineStatusAll.name() + ": 0x%x" %(pRequest.chunkLineStatusAll.read()))
 * \endcode
 * \endif
 *  E.g. for the \b mvBlueCOUGAR-X/XD series possible \c LineStatusAll values are
 *
 *  - \b 0x11, Out0 and In0 on (Out0 needs to be connected with In0 for this to work)
 *  - \b 0x33, Out0, Out1, In0 and In1 on (Out0 and Out1 need to be connected with In0 and In1 for this to work)
 *  - \b 0x37, Out0, Out1, Out2, In0 and In1 on (Out0 and Out1 need to be connected with In0 and In1 for this to work)
 *  - \b 0x3f, Out0, Out1, Out2, Out3, In0 and In1 on (Out0 and Out1 need to be connected with in0 and in1 for this to work)
 *
 *  \since 2.10.0
 */
class RequestInfoConfiguration : public ComponentCollection
//-----------------------------------------------------------------------------
{
public:
    /// brief Constructs a new \b mvIMPACT::acquire::RequestInfoConfiguration object.
    explicit RequestInfoConfiguration(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : ComponentCollection( pDev ), frameNr(), timeStamp_us(), settingUsed(),
        exposeStart_us(), exposeTime_us(), gain_dB(), videoChannel(), missingData_pc(), transferDelay_us(),
        imageAverage(), IOStatesAtExposureStart(), triggerCounterAcquisitionStart(), triggerCounterFrameStart(),
        lineCounter(), userData(), lineStatusAll()
    {
        DeviceComponentLocator locator( pDev, dltSetting, settingName );
        locator.bindSearchBase( locator.searchbase_id(), "RequestInfo" );
        m_hRoot = locator.searchbase_id();
        locator.bindComponent( frameNr, "FrameNr" );
        locator.bindComponent( timeStamp_us, "TimeStamp_us" );
        locator.bindComponent( settingUsed, "SettingUsed" );
        locator.bindComponent( frameID, "FrameID" );
        locator.bindComponent( exposeStart_us, "ExposeStart_us" );
        locator.bindComponent( exposeTime_us, "ExposeTime_us" );
        locator.bindComponent( gain_dB, "Gain_dB" );
        locator.bindComponent( videoChannel, "VideoChannel" );
        locator.bindComponent( missingData_pc, "MissingData_pc" );
        locator.bindComponent( transferDelay_us, "TransferDelay_us" );
        locator.bindComponent( imageAverage, "ImageAverage" );
        locator.bindComponent( IOStatesAtExposureStart, "IOStatesAtExposureStart" );
        locator.bindComponent( triggerCounterAcquisitionStart, "TriggerCounterAcquisitionStart" );
        locator.bindComponent( triggerCounterFrameStart, "TriggerCounterFrameStart" );
        locator.bindComponent( lineCounter, "LineCounter" );
        locator.bindComponent( userData, "UserData" );
        locator.bindComponent( lineStatusAll, "LineStatusAll" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property which can be used to configure whether the frame number information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean frameNr;
    /// \brief An enumerated integer property which can be used to configure whether the time stamp(us) information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean timeStamp_us;
    /// \brief An enumerated integer property which can be used to configure whether the 'setting used' information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean settingUsed;
    /// \brief An enumerated integer property which can be used to configure whether the frame ID information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean frameID;
    /// \brief An enumerated integer property which can be used to configure whether the exposure start(us) information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean exposeStart_us;
    /// \brief An enumerated integer property which can be used to configure whether the exposure time(us) information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean exposeTime_us;
    /// \brief An enumerated integer property which can be used to configure whether the gain(dB) information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean gain_dB;
    /// \brief An enumerated integer property which can be used to configure whether the video channel information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean videoChannel;
    /// \brief An enumerated integer property which can be used to configure whether the missing data information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean missingData_pc;
    /// \brief An enumerated integer property which can be used to configure whether the transfer delay(us) information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *  \note
     *  - This feature currently is only available for \b mvBlueFOX devices
     */
    PropertyIBoolean transferDelay_us;
    /// \brief An enumerated integer property which can be used to configure whether the image average information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *  \note
     *  - This feature currently is only available for \b mvBlueFOX devices
     */
    PropertyIBoolean imageAverage;
    /// \brief An enumerated integer property which can be used to configure whether the I/O states at exposure start information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *  \note
     *  This feature currently is only available for \b mvBlueFOX-MLC devices.
     */
    PropertyIBoolean IOStatesAtExposureStart;
    /// \brief An enumerated integer property which can be used to configure whether the trigger counter at acquisition start information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *  \note
     *  - This feature currently is only available for \b mvHYPERION devices
     */
    PropertyIBoolean triggerCounterAcquisitionStart;
    /// \brief An enumerated integer property which can be used to configure whether the trigger counter at frame start information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *  \note
     *  - This feature currently is only available for \b mvHYPERION devices
     */
    PropertyIBoolean triggerCounterFrameStart;
    /// \brief An enumerated integer property which can be used to configure whether the line counter information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *  \note
     *  - This feature currently is only available for \b mvTITAN-CL, \b mvGAMMA-CL and \b mvTITAN-DIG devices
     */
    PropertyIBoolean lineCounter;
    /// \brief An enumerated integer property which can be used to configure whether the user data information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *  \note
     *  This feature currently is only available for \b mvVirtual devices.
     */
    PropertyIBoolean userData;
    /// \brief An enumerated integer property which can be used to configure whether the line status all information shall be attached to the resulting \b mvIMPACT::acquire::Request objects.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *  \note
     *  - This feature may be available for GenICam compliant devices
     */
    PropertyIBoolean lineStatusAll;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief Properties for adjusting the colors during a Bayer conversion.
/**
 *  This class provides properties to adjust the parameters needed for a
 *  Bayer conversion.
 *
 *  \note
 *  Objects of this class can't be constructed directly. Its parameters can
 *  be accessed via an instance of a class derived from \b mvIMPACT::acquire::ImageProcessing.
 */
class WhiteBalanceSettings : public ComponentCollection
//-----------------------------------------------------------------------------
{
    // only ImageProcessing objects can create these objects, as these objects are
    // fixed parts of that class.
    friend class ImageProcessing;
    explicit WhiteBalanceSettings( HOBJ hObj ): ComponentCollection( hObj ), WBAoiMode(), aoiHeight(), aoiStartX(), aoiStartY(),
        aoiWidth(), totalGain(), redGain(), greenGain(), blueGain(),  WBResult()
    {
        ComponentLocator locator( hObj );
        locator.bindComponent( WBAoiMode, "WBAoiMode" );
        locator.bindComponent( totalGain, "TotalGain" );
        locator.bindComponent( redGain, "RedGain" );
        locator.bindComponent( greenGain, "GreenGain" );
        locator.bindComponent( blueGain, "BlueGain" );
        locator.bindComponent( WBResult, "WBResult" );
        locator.bindSearchBase( locator.searchbase_id(), "WBAoi" );
        locator.bindComponent( aoiHeight, "H" );
        locator.bindComponent( aoiStartX, "X" );
        locator.bindComponent( aoiStartY, "Y" );
        locator.bindComponent( aoiWidth, "W" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the which area of the image is used
    /** for the calculation of the parameters.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAoiMode.
     */
    PropertyIAoiMode WBAoiMode;
    /// \brief An integer property defining the height of the AOI in pixel to be used for the calculation.
    /**
     *  \note
     *  This property will be visible only when \b mvIMPACT::acquire::WhiteBalanceSettings::WBAoiMode
     *  is set to \b mvIMPACT::acquire::amUseAoi.
     */
    PropertyI aoiHeight;
    /// \brief An integer property defining the X-offset of the AOI in pixel to be used for the calculation.
    /**
     *  \note
     *  This property will be visible only when \b mvIMPACT::acquire::WhiteBalanceSettings::WBAoiMode
     *  is set to \b mvIMPACT::acquire::amUseAoi.
     */
    PropertyI aoiStartX;
    /// \brief An integer property defining the Y-offset of the AOI in pixel to be used for the calculation.
    /**
     *  \note
     *  This property will be visible only when \b mvIMPACT::acquire::WhiteBalanceSettings::WBAoiMode
     *  is set to \b mvIMPACT::acquire::amUseAoi.
     */
    PropertyI aoiStartY;
    /// \brief An integer property defining the width of the AOI in pixel to be used for the calculation.
    /**
     *  \note
     *  This property will be visible only when \b mvIMPACT::acquire::WhiteBalanceSettings::WBAoiMode
     *  is set to \b mvIMPACT::acquire::amUseAoi.
     */
    PropertyI aoiWidth;
    /// \brief A float property defining the overall gain.
    PropertyF totalGain;
    /// \brief A float property defining the gain for the red channel.
    PropertyF redGain;
    /// \brief A float property defining the gain for the green channel.
    PropertyF greenGain;
    /// \brief A float property defining the gain for the blue channel.
    PropertyF blueGain;
    /// \brief An enumerated integer property \b (read-only) containing the result of the last white balance calibration.
    /**
     *  After the \b mvIMPACT::acquire::Device has been initialized, the value of this property will be
     *  \b mvIMPACT::acquire::bwbrUnknown.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBayerWhiteBalanceResult.
     */
    PropertyIBayerWhiteBalanceResult WBResult;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief Properties for configuring settings belonging to a certain channel of the GainOffsetKnee filter.
/**
 *  First the master offset will be added to all channels of the image, then each
 *  channels individual gain factor will be applied to the pixel of each channel and
 *  finally the channel specific offset will be added.
 *
 *  \image html GainOffsetKnee.png
 *
 *  \note
 *  Objects of this class can't be constructed directly. Its parameters can
 *  be accessed via an instance of a class derived from \b mvIMPACT::acquire::ImageProcessing.
 */
class GainOffsetKneeChannelParameters : public ComponentCollection
//-----------------------------------------------------------------------------
{
    // only ImageProcessing objects can create these objects, as these objects are
    // fixed parts of that class.
    friend class ImageProcessing;
    explicit GainOffsetKneeChannelParameters( HOBJ hObj ): ComponentCollection( hObj ), gain(), offset_pc()
    {
        ComponentLocator locator( hObj );
        locator.bindComponent( gain, "Gain" );
        locator.bindComponent( offset_pc, "Offset_pc" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief A float property that contains the channel specific gain to be applied to the selected channel of the image.
    /**
     *  This gain will be applied after the master offset but before the channel specific offset.
     */
    PropertyF gain;
    /// \brief A float property that contains the channel specific offset (in percent) to be applied to the selected channel of the image.
    /**
     *  This offset will be applied after the channel specific gain.
     */
    PropertyF offset_pc;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief Properties for configuring settings belonging to a certain LUT (<b>L</b>ook <b>U</b>p <b>T</b>able) to be applied to a captured image.
/**
 *  \note
 *  Objects of this class can't be constructed directly. Its parameters can
 *  be accessed via an instance of a class derived from \b mvIMPACT::acquire::ImageProcessing.
 */
class LUTParameters : public ComponentCollection
//-----------------------------------------------------------------------------
{
    // only ImageProcessing objects can create these objects, as these objects are
    // fixed parts of that class.
    friend class ImageProcessing;
    explicit LUTParameters( HOBJ hObj ): ComponentCollection( hObj ), gamma(),
        gammaAlpha(), gammaMode(), gammaStartThreshold(), gammaInverter(),
        valueCount(), inputValues(), outputValues(), directValues()
    {
        ComponentLocator locator( hObj );
        locator.bindComponent( gamma, "Gamma" );
        locator.bindComponent( gammaAlpha, "GammaAlpha" );
        locator.bindComponent( gammaMode, "GammaMode" );
        locator.bindComponent( gammaStartThreshold, "GammaStartThreshold" );
        locator.bindComponent( gammaInverter, "GammaInverter" );
        locator.bindComponent( valueCount, "ValueCount" );
        locator.bindComponent( inputValues, "InputValues" );
        locator.bindComponent( outputValues, "OutputValues" );
        locator.bindComponent( directValues, "DirectValues" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief A float property which can be used to set the gamma value.
    /**
     *  Gamma correction is explained e.g. in this Wikipedia article: http://en.wikipedia.org/wiki/Gamma_correction.
     *
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTmGamma.
     *
     *  The gamma value will be used to calculate the corresponding input -> output transformation LUT.
     *
     *  The following formula will be used:
     * \code
     *   ( ( 1 + gammaAlpha ) * inputValue^(1/gamma) ) - gammaAlpha
     * \endcode
     */
    PropertyF gamma;
    /// \brief A float property which can be used to set the gammaAlpha value.
    /**
     *  Refer to \b mvIMPACT::acquire::LUTParameters::gamma to see how this parameter affects the resulting
     *  LUT data.
     *
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTmGamma.
     */
    PropertyF gammaAlpha;
    /// \brief An enumerated integer property which can be used to configure the LUT(<b>L</b>ook <b>U</b>p <b>T</b>able) gamma mode.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TLUTGammaMode.
     *
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTmGamma.
     */
    PropertyILUTGammaMode gammaMode;
    /// \brief An integer property which can be used to define a start threshold above which the gamma correction formula shall be used in \b mvIMPACT::acquire::LUTParameters::gammaMode \b mvIMPACT::acquire::LUTgmLinearStart.
    /**
     *  Values below that threshold will be calculated using linear interpolation.
     *
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTmGamma or if \b mvIMPACT::acquire::LUTParameters::gammaMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTgmLinearStart.
     */
    PropertyI gammaStartThreshold;
    /// \brief An enumerated integer property defining whether the calculated gamma correction function shall be inverted or not
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTmGamma.
     *
     *  \attention This property is mainly provided for compatibility reasons since the original implementation of
     *  the mvIMPACT Acquire framework and the implementation inside MATRIX VISION GmbH GenICam devices introduced later
     *  differ. The default behaviour of the mvIMPACT Acquire results in the reverse function of the gamma function
     *  inside the device firmware thus the gamma value specified here results in the same response as if applying
     *  (1/gamma value) to a device. So a gamma value of 2.2 with the inverter switched off this would result in the same
     *  response as a gamma value of 0.45 with the inverter switched on. In order not to change the default behaviour of this filter
     *  the default value for this property will be \b mvIMPACT::acquire::bTrue and can be set to
     *  \b mvIMPACT::acquire::bFalse to achieve the same behaviour as implemented for GenICam devices and specified in
     *  the SFNC (GenICam Standard Features Naming Convention).
     *
     *  \since 2.38.0
     */
    PropertyIBoolean gammaInverter;
    /// \brief An integer property to define the number of sampling points for interpolated LUT transformations.
    /**
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTmInterpolated.
     *
     *  At least 2 sampling points are needed, the max. number of sampling points is defined by the bit depth of the input
     *  image, thus a 8 bit input image can have no more than 2^8 (256) sampling points. if the max. number of sampling points
     *  is used, the behaviour is the same a when working with \b mvIMPACT::acquire::ImageProcessing::LUTMode set to
     *  \b mvIMPACT::acquire::LUTmDirect.
     *
     *  \b EXAMPLE
     *
     *  Assuming 4 sampling points in \b mvIMPACT::acquire::LUTimThreshold mode for an 8 to 8 bit transformation where the following
     *  values are used:
     *
     *  <table>
     *  <tr><td class="header">index</td><td class="header">input value</td><td class="header">output value</td></tr>
     *  <tr><td class="indexvalue">0</td><td class="indexvalue">0</td><td class="indexvalue">64</td></tr>
     *  <tr><td class="indexvalue">1</td><td class="indexvalue">128</td><td class="indexvalue">255</td></tr>
     *  <tr><td class="indexvalue">2</td><td class="indexvalue">192</td><td class="indexvalue">0</td></tr>
     *  <tr><td class="indexvalue">3</td><td class="indexvalue">255</td><td class="indexvalue">0</td></tr>
     *  </table>
     *
     *  This will result in the following transfer function characteristic:
     *
     *  \image html LUT_ThresholdInterpolation_4SamplingPoints.png
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  \b The following C++ code would be needed to achieve this behaviour for mono video sources:
     *
     * \code
     *  //-----------------------------------------------------------------------------
     *  void fn( ImageProcessing& ip, TLUTImplemention LUTImplementation )
     *  //-----------------------------------------------------------------------------
     *  {
     *    ip.LUTEnable.write( bTrue );
     *    ip.LUTMode.write( LUTmInterpolated );
     *    ip.LUTImplementation.write( LUTImplementation );
     *    ip.LUTInterpolationMode.write( LUTimThreshold );
     *    switch( LUTImplementation )
     *    {
     *      case LUTiHardware:
     *        ip.LUTMappingHardware.write( LUTm8To8 );
     *        break;
     *      case LUTiSoftware:
     *        ip.LUTMappingSoftware.write( LUTm8To8 );
     *        break;
     *     }
     *     LUTParameters& LUTAccess = ip.getLUTParameter( 0 );
     *     LUTAccess.valueCount.write( 4 );
     *     vector<int> v(4);
     *     v[0] = 0;
     *     v[1] = 128;
     *     v[2] = 192;
     *     v[3] = 255;
     *     LUTAccess.inputValues.write( v );
     *     v[0] = 64;
     *     v[1] = 255;
     *     v[2] = 0;
     *     v[3] = 0;
     *     LUTAccess.outputValues.write( v );
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  //-----------------------------------------------------------------------------
     *  public void fn( ImageProcessing ip, final int LUTImplementation )
     *  //-----------------------------------------------------------------------------
     *  {
     *    ip.getLUTEnable().write( TBoolean.bTrue );
     *    ip.getLUTMode().write( TLUTMode.LUTmInterpolated );
     *    ip.getLUTImplementation().write( LUTImplementation );
     *    ip.getLUTInterpolationMode().write( TLUTInterpolationMode.LUTimThreshold );
     *    if( LUTImplementation == TLUTImplementation.LUTiHardware )
     *    {
     *      ip.getLUTMappingHardware().write( TLUTMapping.LUTm8To8 );
     *    }
     *    else if( LUTImplementation == TLUTImplementation.LUTiSoftware )
     *    {
     *      ip.getLUTMappingSoftware().write( TLUTMapping.LUTm8To8 );
     *    }
     *    LUTParameters LUTAccess = ip.getLUTParameter( 0 );
     *    LUTAccess.getValueCount().write( 4 );
     *    {
     *      IntVector v = new IntVector();
     *      v.add( 0 );
     *      v.add( 128 );
     *      v.add( 192 );
     *      v.add( 255 );
     *      LUTAccess.getInputValues().write( v );
     *    }
     *    {
     *      IntVector v = new IntVector();
     *      v.add( 64 );
     *      v.add( 255 );
     *      v.add( 0 );
     *      v.add( 0 );
     *      LUTAccess.getOutputValues().write( v );
     *    }
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *  This sample assumes a valid reference to a \b mvIMPACT::acquire::ImageProcessing object has been obtained.
     *  def fn(ip, LUTImplementation):
     *    ip.LUTEnable.write(acquire.bTrue)
     *    ip.LUTMode.write(acquire.LUTmInterpolated)
     *    ip.LUTImplementation.write(LUTImplementation)
     *    ip.LUTInterpolationMode.write(LUTimThreshold)
     *    if LUTImplementation == LUTiHardware:
     *        ip.LUTMappingHardware.write(acquire.LUTm8To8)
     *    elif LUTImplementation == LUTiSoftware:
     *        ip.LUTMappingSoftware.write(acquire.LUTm8To8)
     *
     *    LUTAccess = ip.getLUTParameter(0)
     *    LUTAccess.valueCount.write(4)
     *    v = []
     *    v[0] = 0
     *    v[1] = 128
     *    v[2] = 192
     *    v[3] = 255
     *    LUTAccess.inputValues.write(v)
     *
     *    v[0] = 64
     *    v[1] = 255
     *    v[2] = 0
     *    v[3] = 0
     *    LUTAccess.outputValues.write(v)
     * \endcode
     * \endif
     *  Assuming 3 sampling points in \b mvIMPACT::acquire::LUTimLinear mode for an 8 to 8 bit transformation where the following
     *  values are used:
     *
     *  <table>
     *  <tr><td class="header">index</td><td class="header">input value</td><td class="header">output value</td></tr>
     *  <tr><td class="indexvalue">0</td><td class="indexvalue">0</td><td class="indexvalue">64</td></tr>
     *  <tr><td class="indexvalue">1</td><td class="indexvalue">128</td><td class="indexvalue">255</td></tr>
     *  <tr><td class="indexvalue">2</td><td class="indexvalue">255</td><td class="indexvalue">0</td></tr>
     *  </table>
     *
     *  This will result in the following transfer function characteristic:
     *
     *  \image html LUT_linearInterpolation_3SamplingPoints.png
     *
     *  Assuming 4 sampling points in \b mvIMPACT::acquire::LUTimCubic mode for an 8 to 8 bit transformation where the following
     *  values are used:
     *
     *  <table>
     *  <tr><td class="header">index</td><td class="header">input value</td><td class="header">output value</td></tr>
     *  <tr><td class="indexvalue">0</td><td class="indexvalue">0</td><td class="indexvalue">0</td></tr>
     *  <tr><td class="indexvalue">1</td><td class="indexvalue">128</td><td class="indexvalue">255</td></tr>
     *  <tr><td class="indexvalue">2</td><td class="indexvalue">192</td><td class="indexvalue">192</td></tr>
     *  <tr><td class="indexvalue">3</td><td class="indexvalue">255</td><td class="indexvalue">0</td></tr>
     *  </table>
     *
     *  This will result in the following transfer function characteristic:
     *
     *  \image html LUT_CubicInterpolation_4SamplingPoints.png
     */
    PropertyI valueCount;
    /// \brief An integer property to define the input values for sampling points for interpolated LUT transformations.
    /**
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTmInterpolated.
     *
     *  The number of values stored by this property can be changed by writing to the property \b mvIMPACT::acquire::LUTParameters::valueCount.
     *  The documentation of this property also provides some example values and resulting transfer characteristics.
     */
    PropertyI inputValues;
    /// \brief An integer property to define the output values for sampling points for interpolated LUT transformations.
    /**
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTmInterpolated.
     *
     *  The number of values stored by this property can be changed by writing to the property \b mvIMPACT::acquire::LUTParameters::valueCount.
     *  The documentation of this property also provides some example values and resulting transfer characteristics.
     */
    PropertyI outputValues;
    /// \brief An integer property which can be used to directly define a LUT.
    /**
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTmDirect.
     *
     *  This property will provide a complete LUT thus e.g. in a LUT mapping to a 10 bit output this property will store 2^10 (1024)
     *  values that can be accessed and modified by the user.
     */
    PropertyI directValues;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief Properties for configuring settings belonging to the mirror filter that processes a certain channel of a captured image.
/**
 *  Properties in this class will only have influence on the capture process if
 *  \b mvIMPACT::acquire::ImageProcessing::mirrorOperationMode is set to \b mvIMPACT::acquire::momChannelBased.
 *
 *  \note
 *  Objects of this class can't be constructed directly. Its parameters can
 *  be accessed via an instance of a class derived from \b mvIMPACT::acquire::ImageProcessing.
 */
class MirrorParameters : public ComponentCollection
//-----------------------------------------------------------------------------
{
    // only ImageProcessing objects can create these objects, as these objects are
    // fixed parts of that class.
    friend class ImageProcessing;
    explicit MirrorParameters( HOBJ hObj ): ComponentCollection( hObj ), mirrorMode()
    {
        ComponentLocator locator( hObj );
        locator.bindComponent( mirrorMode, "MirrorMode" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the mirror mode to be applied to this channel of the image.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TMirrorMode.
     */
    PropertyIMirrorMode mirrorMode;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*

};

//-----------------------------------------------------------------------------
/// \brief Base class for image processing related properties.
/**
 *  This class provides access to properties, which define how the image shall
 *  be processed after it has been captured but before it will be handed back to
 *  the user.
 */
class ImageProcessing : public ComponentCollection
//-----------------------------------------------------------------------------
{
    typedef std::vector<GainOffsetKneeChannelParameters*> GainOffsetKneeParameterContainer;
    typedef std::vector<LUTParameters*> LUTParameterContainer;
    typedef std::vector<MirrorParameters*> MirrorParameterContainer;
    typedef std::vector<WhiteBalanceSettings*> WBSettingsContainer;
#   ifndef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        GainOffsetKneeParameterContainer m_GainOffsetKneeParameters;
        LUTParameterContainer            m_LUTParameters;
        MirrorParameterContainer         m_MirrorParameters;
        WBSettingsContainer              m_WBUserSettings;
        unsigned int                     m_refCnt;
        explicit ReferenceCountedData() : m_GainOffsetKneeParameters(), m_LUTParameters(),
            m_MirrorParameters(), m_WBUserSettings(), m_refCnt( 1 ) {}
        ~ReferenceCountedData()
        {
            const GainOffsetKneeParameterContainer::size_type GainOffsetKneeParameterCnt = m_GainOffsetKneeParameters.size();
            for( GainOffsetKneeParameterContainer::size_type h = 0; h < GainOffsetKneeParameterCnt; h++ )
            {
                delete m_GainOffsetKneeParameters[h];
            }
            const LUTParameterContainer::size_type LUTParametersCnt = m_LUTParameters.size();
            for( LUTParameterContainer::size_type i = 0; i < LUTParametersCnt; i++ )
            {
                delete m_LUTParameters[i];
            }
            const MirrorParameterContainer::size_type MirrorParametersCnt = m_MirrorParameters.size();
            for( MirrorParameterContainer::size_type j = 0; j < MirrorParametersCnt; j++ )
            {
                delete m_MirrorParameters[j];
            }
            const WBSettingsContainer::size_type WBSettingsCnt = m_WBUserSettings.size();
            for( WBSettingsContainer::size_type k = 0; k < WBSettingsCnt; k++ )
            {
                delete m_WBUserSettings[k];
            }
        }
    }* m_pRefData;
#   endif // #ifdef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    void bindPublicProperties( void )
    //-----------------------------------------------------------------------------
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( colorProcessing, "ColorProcessing" );
        locator.bindComponent( bayerConversionMode, "BayerConversionMode" );
        locator.bindComponent( adaptiveEdgeSensingPlusSharpenThreshold, "AdaptiveEdgeSensingPlusSharpenThreshold" );
        locator.bindComponent( adaptiveEdgeSensingPlusSharpenGain, "AdaptiveEdgeSensingPlusSharpenGain" );
        locator.bindComponent( whiteBalance, "WhiteBalance" );
        locator.bindComponent( whiteBalanceCalibration, "WhiteBalanceCalibration" );
        locator.bindComponent( filter, "Filter" );
        if( locator.findComponent( "Mirror" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "Mirror" );
            locator.bindComponent( mirrorOperationMode, "MirrorOperationMode" );
            locator.bindComponent( mirrorModeGlobal, "MirrorModeGlobal" );
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "PolarizedDataExtraction" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "PolarizedDataExtraction" );
            locator.bindComponent( polarizedDataExtractionEnable, "PolarizedDataExtractionEnable" );
            locator.bindComponent( polarizedDataExtractionMode, "PolarizedDataExtractionMode" );
            locator.bindComponent( polarizedDataExtractionInterpolationMode, "PolarizedDataExtractionInterpolationMode" );
            locator.bindComponent( polarizedDataExtractionChannelIndex, "PolarizedDataExtractionChannelIndex" );
            locator.bindComponent( polarizedDataExtractionLowerLimit, "PolarizedDataExtractionLowerLimit" );
            locator.bindComponent( polarizedDataExtractionUpperLimit, "PolarizedDataExtractionUpperLimit" );
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "DefectivePixelsFilter" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "DefectivePixelsFilter" );
            locator.bindComponent( defectivePixelsFilterMode, "Mode" );
            locator.bindComponent( defectivePixelsFilterLeakyPixelDeviation_ADCLimit, "LeakyPixelDeviation_ADCLimit" );
            locator.bindComponent( defectivePixelsFilterColdPixelDeviation_pc, "ColdPixelDeviation_pc" );
            locator.bindComponent( defectivePixelsMaxDetectionCount, "DefectivePixelsMaxDetectionCount" );
            locator.bindComponent( defectivePixelsFound, "DefectivePixelsFound" );
            locator.bindComponent( defectivePixelOffsetX, "DefectivePixelOffsetX" );
            locator.bindComponent( defectivePixelOffsetY, "DefectivePixelOffsetY" );
            locator.bindComponent( defectivePixelReadFromDevice, "DefectivePixelReadFromDevice@i" );
            locator.bindComponent( defectivePixelWriteToDevice, "DefectivePixelWriteToDevice@i" );
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "FlatFieldFilter" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "FlatFieldFilter" );
            locator.bindComponent( flatFieldFilterMode, "Mode" );
            locator.bindComponent( flatFieldFilterCorrectionMode, "CorrectionMode" );
            locator.bindComponent( flatFieldFilterCorrectionModeReverseX, "CorrectionModeReverseX" );
            locator.bindComponent( flatFieldFilterCorrectionModeReverseY, "CorrectionModeReverseY" );
            locator.bindComponent( flatFieldFilterCorrectionAoiMode, "CorrectionAoiMode" );
            locator.bindComponent( flatFieldFilterCalibrationImageCount, "CalibrationImageCount" );
            locator.bindComponent( flatFieldFilterCalibrationAoiMode, "CalibrationAoiMode" );
            HOBJ hObj = locator.findComponent( "CorrectionAOI" );
            if( hObj != INVALID_ID )
            {
                ComponentLocator l( hObj );
                l.bindComponent( flatFieldFilterCorrectionAoiOffsetX, "X" );
                l.bindComponent( flatFieldFilterCorrectionAoiOffsetY, "Y" );
                l.bindComponent( flatFieldFilterCorrectionAoiWidth, "W" );
                l.bindComponent( flatFieldFilterCorrectionAoiHeight, "H" );
            }
            hObj = locator.findComponent( "CalibrationAOI" );
            if( hObj != INVALID_ID )
            {
                ComponentLocator l( hObj );
                l.bindComponent( flatFieldFilterCalibrationAoiOffsetX, "X" );
                l.bindComponent( flatFieldFilterCalibrationAoiOffsetY, "Y" );
                l.bindComponent( flatFieldFilterCalibrationAoiWidth, "W" );
                l.bindComponent( flatFieldFilterCalibrationAoiHeight, "H" );
            }
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "DarkCurrentFilter" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "DarkCurrentFilter" );
            locator.bindComponent( darkCurrentFilterMode, "Mode" );
            locator.bindComponent( darkCurrentFilterCalibrationImageCount, "CalibrationImageCount" );
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "GainOffsetKnee" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "GainOffsetKnee" );
            locator.bindComponent( gainOffsetKneeEnable, "GainOffsetKneeEnable" );
            locator.bindComponent( gainOffsetKneeMasterOffset_pc, "GainOffsetKneeMasterOffset_pc" );
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "LUTOperations" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "LUTOperations" );
            locator.bindComponent( LUTEnable, "LUTEnable" );
            locator.bindComponent( LUTMode, "LUTMode" );
            locator.bindComponent( LUTInterpolationMode, "LUTInterpolationMode" );
            locator.bindComponent( LUTImplementation, "LUTImplementation" );
            locator.bindComponent( LUTMappingHardware, "LUTMappingHardware" );
            locator.bindComponent( LUTMappingSoftware, "LUTMappingSoftware" );
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "TapSort" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "TapSort" );
            locator.bindComponent( tapSortEnable, "TapSortEnable" );
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "ChannelSplit" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "ChannelSplit" );
            locator.bindComponent( channelSplitEnable, "ChannelSplitEnable" );
            locator.bindComponent( channelSplitMode, "ChannelSplitMode" );
            locator.bindComponent( channelSplitChannelIndex, "ChannelSplitChannelIndex" );
            locator.bindComponent( channelSplitDeinterlaceEnable, "ChannelSplitDeinterlaceEnable" );
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "ColorTwist" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "ColorTwist" );
            locator.bindComponent( colorTwistInputCorrectionMatrixEnable, "ColorTwistInputCorrectionMatrixEnable" );
            locator.bindComponent( colorTwistInputCorrectionMatrixMode, "ColorTwistInputCorrectionMatrixMode" );
            locator.bindComponent( colorTwistInputCorrectionMatrixRow0, "ColorTwistInputCorrectionMatrixRow0" );
            locator.bindComponent( colorTwistInputCorrectionMatrixRow1, "ColorTwistInputCorrectionMatrixRow1" );
            locator.bindComponent( colorTwistInputCorrectionMatrixRow2, "ColorTwistInputCorrectionMatrixRow2" );
            locator.bindComponent( colorTwistEnable, "ColorTwistEnable" );
            locator.bindComponent( colorTwistRow0, "ColorTwistRow0" );
            locator.bindComponent( colorTwistRow1, "ColorTwistRow1" );
            locator.bindComponent( colorTwistRow2, "ColorTwistRow2" );
            locator.bindComponent( colorTwistOutputCorrectionMatrixEnable, "ColorTwistOutputCorrectionMatrixEnable" );
            locator.bindComponent( colorTwistOutputCorrectionMatrixMode, "ColorTwistOutputCorrectionMatrixMode" );
            locator.bindComponent( colorTwistOutputCorrectionMatrixRow0, "ColorTwistOutputCorrectionMatrixRow0" );
            locator.bindComponent( colorTwistOutputCorrectionMatrixRow1, "ColorTwistOutputCorrectionMatrixRow1" );
            locator.bindComponent( colorTwistOutputCorrectionMatrixRow2, "ColorTwistOutputCorrectionMatrixRow2" );
            locator.bindComponent( colorTwistResultingMatrixRow0, "ColorTwistResultingMatrixRow0" );
            locator.bindComponent( colorTwistResultingMatrixRow1, "ColorTwistResultingMatrixRow1" );
            locator.bindComponent( colorTwistResultingMatrixRow2, "ColorTwistResultingMatrixRow2" );
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "FormatReinterpreter" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "FormatReinterpreter" );
            locator.bindComponent( formatReinterpreterEnable, "FormatReinterpreterEnable" );
            locator.bindComponent( formatReinterpreterMode, "FormatReinterpreterMode" );
            locator.bindComponent( formatReinterpreterBayerMosaicParity, "FormatReinterpreterBayerMosaicParity" );
        }
        locator.bindSearchBase( m_hRoot );
        if( locator.findComponent( "Rotation" ) != INVALID_ID )
        {
            locator.bindSearchBase( m_hRoot, "Rotation" );
            locator.bindComponent( rotationEnable, "RotationEnable" );
            locator.bindComponent( rotationAngle, "RotationAngle" );
        }
    }
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::ImageProcessing object.
    explicit ImageProcessing(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : ComponentCollection( pDev ), m_pRefData( 0 ),
        colorProcessing(), bayerConversionMode(), adaptiveEdgeSensingPlusSharpenThreshold(),
        adaptiveEdgeSensingPlusSharpenGain(), whiteBalance(), whiteBalanceCalibration(), filter(),
        mirrorOperationMode(), mirrorModeGlobal(), polarizedDataExtractionEnable(),
        polarizedDataExtractionMode(), polarizedDataExtractionInterpolationMode(),
        polarizedDataExtractionChannelIndex(),
        polarizedDataExtractionLowerLimit(), polarizedDataExtractionUpperLimit(),
        defectivePixelsFilterMode(), defectivePixelsFilterLeakyPixelDeviation_ADCLimit(),
        defectivePixelsFilterColdPixelDeviation_pc(), defectivePixelsMaxDetectionCount(), defectivePixelsFound(),
        defectivePixelOffsetX(), defectivePixelOffsetY(), defectivePixelReadFromDevice(), defectivePixelWriteToDevice(),
        flatFieldFilterMode(), flatFieldFilterCorrectionMode(), flatFieldFilterCorrectionModeReverseX(), flatFieldFilterCorrectionModeReverseY(),
        flatFieldFilterCorrectionAoiMode(), flatFieldFilterCorrectionAoiOffsetX(), flatFieldFilterCorrectionAoiOffsetY(),
        flatFieldFilterCorrectionAoiWidth(), flatFieldFilterCorrectionAoiHeight(), flatFieldFilterCalibrationImageCount(),
        flatFieldFilterCalibrationAoiMode(), flatFieldFilterCalibrationAoiOffsetX(), flatFieldFilterCalibrationAoiOffsetY(),
        flatFieldFilterCalibrationAoiWidth(), flatFieldFilterCalibrationAoiHeight(),
        darkCurrentFilterMode(), darkCurrentFilterCalibrationImageCount(),
        gainOffsetKneeEnable(), gainOffsetKneeMasterOffset_pc(),
        LUTEnable(), LUTMode(), LUTInterpolationMode(),
        LUTImplementation(), LUTMappingHardware(), LUTMappingSoftware(),
        tapSortEnable(), channelSplitEnable(), channelSplitMode(), channelSplitChannelIndex(), channelSplitDeinterlaceEnable(),
        colorTwistInputCorrectionMatrixEnable(), colorTwistInputCorrectionMatrixMode(),
        colorTwistInputCorrectionMatrixRow0(), colorTwistInputCorrectionMatrixRow1(), colorTwistInputCorrectionMatrixRow2(),
        colorTwistEnable(), colorTwistRow0(), colorTwistRow1(), colorTwistRow2(),
        colorTwistOutputCorrectionMatrixEnable(), colorTwistOutputCorrectionMatrixMode(),
        colorTwistOutputCorrectionMatrixRow0(), colorTwistOutputCorrectionMatrixRow1(), colorTwistOutputCorrectionMatrixRow2(),
        colorTwistResultingMatrixRow0(), colorTwistResultingMatrixRow1(), colorTwistResultingMatrixRow2(),
        formatReinterpreterEnable(), formatReinterpreterMode(), formatReinterpreterBayerMosaicParity(), rotationEnable(), rotationAngle()
    {
        DeviceComponentLocator locator( pDev, dltSetting, settingName );
        m_pRefData = new ReferenceCountedData();
        locator.bindSearchBase( locator.searchbase_id(), "ImageProcessing" );
        m_hRoot = locator.searchbase_id();
        bindPublicProperties();
        int number = 1;
        HOBJ hList = INVALID_ID;
        // create the WB user parameter objects for this setting
        do
        {
            std::ostringstream oss;
            oss << "WhiteBalanceSettings-" << number++;
            if( ( hList = locator.findComponent( oss.str() ) ) != INVALID_ID )
            {
                m_pRefData->m_WBUserSettings.push_back( new WhiteBalanceSettings( hList ) );
            }
        }
        while( hList != INVALID_ID );

        // create the GainOffsetKnee parameter objects for this setting
        if( locator.findComponent( "GainOffsetKnee" ) != INVALID_ID )
        {
            // this driver offers GainOffsetKnee support
            locator.bindSearchBase( locator.searchbase_id(), "GainOffsetKnee" );
            locator.bindSearchBase( locator.searchbase_id(), "GainOffsetKneeChannels" );
            number = 0;
            do
            {
                std::ostringstream oss;
                oss << "Channel-" << number++;
                if( ( hList = locator.findComponent( oss.str() ) ) != INVALID_ID )
                {
                    m_pRefData->m_GainOffsetKneeParameters.push_back( new GainOffsetKneeChannelParameters( hList ) );
                }
            }
            while( hList != INVALID_ID );
        }

        locator.bindSearchBase( m_hRoot );
        // create the Mirror parameter objects for this setting
        if( locator.findComponent( "Mirror" ) != INVALID_ID )
        {
            // this driver offers Mirror support
            locator.bindSearchBase( locator.searchbase_id(), "Mirror" );
            locator.bindSearchBase( locator.searchbase_id(), "MirrorChannels" );
            number = 0;
            do
            {
                std::ostringstream oss;
                oss << "Channel-" << number++;
                if( ( hList = locator.findComponent( oss.str() ) ) != INVALID_ID )
                {
                    m_pRefData->m_MirrorParameters.push_back( new MirrorParameters( hList ) );
                }
            }
            while( hList != INVALID_ID );
        }

        locator.bindSearchBase( m_hRoot );
        // create the LUT parameter objects for this setting
        if( locator.findComponent( "LUTOperations" ) != INVALID_ID )
        {
            // this driver offers LUT support
            locator.bindSearchBase( locator.searchbase_id(), "LUTOperations" );
            locator.bindSearchBase( locator.searchbase_id(), "LUTs" );
            number = 0;
            do
            {
                std::ostringstream oss;
                oss << "LUT-" << number++;
                if( ( hList = locator.findComponent( oss.str() ) ) != INVALID_ID )
                {
                    m_pRefData->m_LUTParameters.push_back( new LUTParameters( hList ) );
                }
            }
            while( hList != INVALID_ID );
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::ImageProcessing from an existing one.
    ImageProcessing(
        /// [in] A constant reference to the \b mvIMPACT::acquire::ImageProcessing object, this object shall be created from
        const ImageProcessing& src ) : ComponentCollection( src.hObj() ), m_pRefData( src.m_pRefData ),
        colorProcessing( src.colorProcessing ), bayerConversionMode( src.bayerConversionMode ),
        adaptiveEdgeSensingPlusSharpenThreshold( src.adaptiveEdgeSensingPlusSharpenThreshold ),
        adaptiveEdgeSensingPlusSharpenGain( src.adaptiveEdgeSensingPlusSharpenGain ), whiteBalance( src.whiteBalance ),
        whiteBalanceCalibration( src.whiteBalanceCalibration ), filter( src.filter ),
        mirrorOperationMode( src.mirrorOperationMode ),
        mirrorModeGlobal( src.mirrorModeGlobal ), polarizedDataExtractionEnable( src.polarizedDataExtractionEnable ),
        polarizedDataExtractionMode( src.polarizedDataExtractionMode ),
        polarizedDataExtractionInterpolationMode( src.polarizedDataExtractionInterpolationMode ),
        polarizedDataExtractionChannelIndex( src.polarizedDataExtractionChannelIndex ),
        polarizedDataExtractionLowerLimit( src.polarizedDataExtractionLowerLimit ),
        polarizedDataExtractionUpperLimit( src.polarizedDataExtractionUpperLimit ),
        defectivePixelsFilterMode( src.defectivePixelsFilterMode ),
        defectivePixelsFilterLeakyPixelDeviation_ADCLimit( src.defectivePixelsFilterLeakyPixelDeviation_ADCLimit ),
        defectivePixelsFilterColdPixelDeviation_pc( src.defectivePixelsFilterColdPixelDeviation_pc ),
        defectivePixelsFound( src.defectivePixelsFound ),
        defectivePixelOffsetX( src.defectivePixelOffsetX ),
        defectivePixelOffsetY( src.defectivePixelOffsetY ),
        defectivePixelReadFromDevice( src.defectivePixelReadFromDevice ),
        defectivePixelWriteToDevice( src.defectivePixelWriteToDevice ),
        flatFieldFilterMode( src.flatFieldFilterMode ),
        flatFieldFilterCorrectionMode( src.flatFieldFilterCorrectionMode ),
        flatFieldFilterCorrectionModeReverseX( src.flatFieldFilterCorrectionModeReverseX ),
        flatFieldFilterCorrectionModeReverseY( src.flatFieldFilterCorrectionModeReverseY ),
        flatFieldFilterCorrectionAoiMode( src.flatFieldFilterCorrectionAoiMode ),
        flatFieldFilterCorrectionAoiOffsetX( src.flatFieldFilterCorrectionAoiOffsetX ),
        flatFieldFilterCorrectionAoiOffsetY( src.flatFieldFilterCorrectionAoiOffsetY ),
        flatFieldFilterCorrectionAoiWidth( src.flatFieldFilterCorrectionAoiWidth ),
        flatFieldFilterCorrectionAoiHeight( src.flatFieldFilterCorrectionAoiHeight ),
        flatFieldFilterCalibrationImageCount( src.flatFieldFilterCalibrationImageCount ),
        flatFieldFilterCalibrationAoiMode( src.flatFieldFilterCalibrationAoiMode ),
        flatFieldFilterCalibrationAoiOffsetX( src.flatFieldFilterCalibrationAoiMode ),
        flatFieldFilterCalibrationAoiOffsetY( src.flatFieldFilterCalibrationAoiOffsetY ),
        flatFieldFilterCalibrationAoiWidth( src.flatFieldFilterCalibrationAoiWidth ),
        flatFieldFilterCalibrationAoiHeight( src.flatFieldFilterCalibrationAoiHeight ),
        darkCurrentFilterMode( src.darkCurrentFilterMode ),
        darkCurrentFilterCalibrationImageCount( src.darkCurrentFilterCalibrationImageCount ),
        gainOffsetKneeEnable( src.gainOffsetKneeEnable ), gainOffsetKneeMasterOffset_pc( src.gainOffsetKneeMasterOffset_pc ),
        LUTEnable( src.LUTEnable ), LUTMode( src.LUTMode ), LUTInterpolationMode( src.LUTInterpolationMode ),
        LUTImplementation( src.LUTImplementation ), LUTMappingHardware( src.LUTMappingHardware ), LUTMappingSoftware( src.LUTMappingSoftware ),
        tapSortEnable( src.tapSortEnable ), channelSplitEnable( src.channelSplitEnable ), channelSplitMode( src.channelSplitMode ),
        channelSplitChannelIndex( src.channelSplitChannelIndex ), channelSplitDeinterlaceEnable( src.channelSplitDeinterlaceEnable ),
        colorTwistInputCorrectionMatrixEnable( src.colorTwistInputCorrectionMatrixEnable ),
        colorTwistInputCorrectionMatrixMode( src.colorTwistInputCorrectionMatrixMode ),
        colorTwistInputCorrectionMatrixRow0( src.colorTwistInputCorrectionMatrixRow0 ),
        colorTwistInputCorrectionMatrixRow1( src.colorTwistInputCorrectionMatrixRow1 ),
        colorTwistInputCorrectionMatrixRow2( src.colorTwistInputCorrectionMatrixRow2 ),
        colorTwistEnable( src.colorTwistEnable ),
        colorTwistRow0( src.colorTwistRow0 ), colorTwistRow1( src.colorTwistRow1 ), colorTwistRow2( src.colorTwistRow2 ),
        colorTwistOutputCorrectionMatrixEnable( src.colorTwistOutputCorrectionMatrixEnable ),
        colorTwistOutputCorrectionMatrixMode( src.colorTwistOutputCorrectionMatrixMode ),
        colorTwistOutputCorrectionMatrixRow0( src.colorTwistOutputCorrectionMatrixRow0 ),
        colorTwistOutputCorrectionMatrixRow1( src.colorTwistOutputCorrectionMatrixRow1 ),
        colorTwistOutputCorrectionMatrixRow2( src.colorTwistOutputCorrectionMatrixRow2 ),
        colorTwistResultingMatrixRow0( src.colorTwistResultingMatrixRow0 ),
        colorTwistResultingMatrixRow1( src.colorTwistResultingMatrixRow1 ),
        colorTwistResultingMatrixRow2( src.colorTwistResultingMatrixRow2 ),
        formatReinterpreterEnable( src.formatReinterpreterEnable ),
        formatReinterpreterMode( src.formatReinterpreterMode ),
        formatReinterpreterBayerMosaicParity( src.formatReinterpreterBayerMosaicParity ),
        rotationEnable( src.rotationEnable ), rotationAngle( src.rotationAngle )
    {
        ++( m_pRefData->m_refCnt );
    }
    /// \brief Class destructor.
    virtual ~ImageProcessing()
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::ImageProcessing objects.
    ImageProcessing& operator=( const ImageProcessing& rhs )
    {
        if( this != &rhs )
        {
            ComponentCollection::operator=( rhs );
            dealloc();
            m_pRefData = rhs.m_pRefData;
            ++m_pRefData->m_refCnt;
            bindPublicProperties();
        }
        return *this;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining what kind of color processing shall be applied to the raw image data.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TColorProcessingMode.
     */
    PropertyIColorProcessingMode colorProcessing;
    /// \brief An enumerated integer property defining what kind of algorithm shall be used during Bayer to RGB conversion.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBayerConversionMode.
     */
    PropertyIBayerConversionMode bayerConversionMode;
    /// \brief An integer property defining the max. brightness level difference for which sharpening is not applied during AdaptiveEdgeSensingPlus deBayering.
    /**
     *  Valid values for this property are between 0 and 2^(bits per pixel).
     *
     *  \since 2.26.0
     */
    PropertyI adaptiveEdgeSensingPlusSharpenThreshold;
    /// \brief A floating point property defining the intensity of the sharpening during AdaptiveEdgeSensingPlus deBayering.
    /**
     *  Valid values for this property are between 0. and 100. (percent).
     *
     *  \since 2.26.0
     */
    PropertyF adaptiveEdgeSensingPlusSharpenGain;
    /// \brief An integer property defining the parameter set to be used to perform the white balance correction.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TWhiteBalanceParameter.
     */
    PropertyIWhiteBalanceParameter whiteBalance;
    /// \brief An enumerated integer property defining the mode used for white balance calibration.
    /**
     *  This property can be used to define the way a white balance calibration shall be performed.
     *  Currently only the \b mvIMPACT::acquire::wbcmNextFrame mode is supported,
     *  but new modes might appear in later revisions of the interface.
     *
     *  When this property is set to \b mvIMPACT::acquire::wbcmNextFrame the next
     *  image captured will be used as a reference to calculate the gain factors for the
     *  \e red, \e green and \e blue channel. So make sure when the next image is captured the camera
     *  looks on a plain white or slightly grey surface in order to obtain correct results. After
     *  the calibration has been done, the property will be reset to \b mvIMPACT::acquire::wbcmOff
     *  again.
     *
     *  \note
     *  Performing this kind of white balance calibration will only affect Bayer color sensors and will
     *  only have any visual effect on the image if one of the user definable parameter sets has been
     *  selected before. This can be done by modifying the property \b mvIMPACT::acquire::ImageProcessing::whiteBalance.
     *  Afterwards the calculated factors will be stored in the \b mvIMPACT::acquire::WhiteBalanceSettings selected.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TWhiteBalanceCalibrationMode.
     */
    PropertyIWhiteBalanceCalibrationMode whiteBalanceCalibration;
    /// \brief An enumerated integer property defining the filter to be applied to the image before it is transferred to the user.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TImageProcessingFilter.
     */
    PropertyIImageProcessingFilter filter;
    /// \brief An enumerated integer property defining the general mode the mirror filter will work in.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TMirrorOperationMode.
     */
    PropertyIMirrorOperationMode mirrorOperationMode;
    /// \brief An enumerated integer property defining the mirror mode to be applied to ALL channels of the image.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TMirrorMode.
     *
     *  \note This property will only be visible, when \b mvIMPACT::acquire::ImageProcessing::mirrorOperationMode is set
     *  to \b mvIMPACT::acquire::momGlobal.
     */
    PropertyIMirrorMode mirrorModeGlobal;
    /// \brief An enumerated integer property defining whether the polarization data extraction filter shall be active or not.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \since 2.29.0
     */
    PropertyIBoolean polarizedDataExtractionEnable;
    /// \brief An enumerated integer property defining in which mode the polarization data extraction filter shall be operated in.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TPolarizedDataExtractionMode.
     *
     *  \since 2.29.0
     */
    PropertyIPolarizedDataExtractionMode polarizedDataExtractionMode;
    /// \brief An enumerated integer property defining the interpolation mode the polarization data extraction filter shall be operated in.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TPolarizedDataExtractionInterpolationMode.
     *
     *  \note This property will only be available when the polarization data extraction mode is either horizontal, vertical or single.
     *
     *  \since 2.29.0
     */
    PropertyIPolarizedDataExtractionInterpolationMode polarizedDataExtractionInterpolationMode;
    /// \brief An integer property defining the channel within the processing window of the polarization data extraction filter.
    /**
     *  This channel will only be taken into account when \b mvIMPACT::acquire::ImageProcessing::polarizedDataExtractionMode is set to
     *  \b mvIMPACT::acquire::prmExtractSingle.
     *
     *  \since 2.29.0
     */
    PropertyI polarizedDataExtractionChannelIndex;
    /// \brief An integer property defining the lower limit of the grey value of a pixel to be taken into account within the processing window of the polarization data extraction filter.
    /**
     *  This limit will only be taken into account when \b mvIMPACT::acquire::ImageProcessing::polarizedDataExtractionMode is set to
     *  \b mvIMPACT::acquire::prmMeanValue.
     *
     *  \since 2.29.0
     */
    PropertyI polarizedDataExtractionLowerLimit;
    /// \brief An integer property defining the upper limit of the grey value of a pixel to be taken into account within the processing window of the polarization data extraction filter.
    /**
     *  This limit will only be taken into account when \b mvIMPACT::acquire::ImageProcessing::polarizedDataExtractionMode is set to
     *  \b mvIMPACT::acquire::prmMeanValue.
     *
     *  \since 2.29.0
     */
    PropertyI polarizedDataExtractionUpperLimit;
    /// \brief An enumerated integer property defining the operation mode of the defective pixels filter.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDefectivePixelsFilterMode.
     */
    PropertyIDefectivePixelsFilterMode defectivePixelsFilterMode;
    /// \brief An integer property defining the max. allowed offset from the average grey value for a pixel during calibration.
    /**
     *  When this filter is calibrated each pixel producing a grey value higher than the average grey value plus
     *  the value of this property will be considered as a leaky pixel and therefore will be replaced by
     *  a value depending on the operation mode of the filter.
     */
    PropertyI defectivePixelsFilterLeakyPixelDeviation_ADCLimit;
    /// \brief An integer property defining the max. allowed deviation for a pixel in per cent from the average grey value.
    /**
     *  If this filter is active every pixel that during the calibration produces a grey value which is
     *  lower than the average grey value of the image minus the allowed deviation in per cent will be
     *  considered as a cold pixel and therefore will be replaced by a value depending on the operation
     *  mode of the filter.
     */
    PropertyI defectivePixelsFilterColdPixelDeviation_pc;
    /// \brief An integer property defining maximum the number of pixels considered as being defective during consecutive calibration runs.
    /**
     *  With this property it is possible to define an upper limit for the number of detected defective pixels. This is not to be meant
     *  as an error checking mechanism for sensors reporting more defective pixels but to allow an application to keep the length of the
     *  list of defective pixels within reasonable boundaries. The more pixels a sensor has the higher a reasonable value might be. Set this
     *  to a value suitable for your application to protect the algorithm from huge lists due to incorrect calibration environments (too much light,
     *  not enough light, ...).
     *
     *  When after a calibration this value and the value of the \b mvIMPACT::acquire::ImageProcessing::defectivePixelsFound property are the
     *  same this indicates a problem. There are several possible reasons for this:
     *
     *  - the lighting conditions or calibration parameters have not been set up correctly (fix your setup then)
     *  - the sensor is damaged (replace the device then)
     *  - the sensor has more defective pixels then indicated by the value of this property but which are still valid according to the specification of the sensor manufacturer (adjust the value of this property accordingly then)
     *
     *  \attention When reducing this value at runtime excess pixels will be dropped from the current list of defective pixels if the new maximum list length is smaller than the amount of
     *  defective pixels currently detected.
     *
     *  \attention Some devices might offer to store defective pixels inside the device in an mvIMPACT Acquire compatible format by calling \b mvIMPACT::acquire::ImageProcessing::defectivePixelWriteToDevice.
     *  However the device might not be able to store all these pixels due to a lack of storage space. Therefore always check the return value of the function!
     *
     *  \note
     *  In order to get rid of currently detected pixels an application must set the property
     *  \b mvIMPACT::acquire::ImageProcessing::defectivePixelsFilterMode to \b mvIMPACT::acquire::dpfmResetCalibration
     *  and then capture a fresh image. Only then all currently detected pixels will be discarded.
     *
     *  \since 2.37.0
     */
    PropertyI defectivePixelsMaxDetectionCount;
    /// \brief An integer property \b (read-only) containing the number of pixels considered as being defective with respect to the
    /// calibration runs executed after the last reset of the calibration data.
    /**
     *  \note
     *  In order to collect \b ALL defective pixels the list of detected pixels is not emptied each time a new calibration
     *  is started. In order to get rid of currently detected pixels an application must set the property
     *  \b mvIMPACT::acquire::ImageProcessing::defectivePixelsFilterMode to \b mvIMPACT::acquire::dpfmResetCalibration
     *  and then capture a fresh image. Only then all currently detected pixels will be discarded.
     *
     *  \since 2.5.9
     */
    PropertyI defectivePixelsFound;
    /// \brief An integer property defining a list of X-offsets of all pixels currently treated as defective.
    /**
     *  All these pixels will be replaced depending on the selected algorithm in \b mvIMPACT::acquire::ImageProcessing::defectivePixelsFilterMode.
     *
     *  \note
     *  In order to collect \b ALL defective pixels the list of detected pixels is not emptied each time a new calibration
     *  is started. In order to get rid of currently detected pixels an application must set the property
     *  \b mvIMPACT::acquire::ImageProcessing::defectivePixelsFilterMode to \b mvIMPACT::acquire::dpfmResetCalibration
     *  and then capture a fresh image. Only then all currently detected pixels will be discarded.
     *
     *  \since 2.17.1
     */
    PropertyI defectivePixelOffsetX;
    /// \brief An integer property defining a list of Y-offsets of all pixels currently treated as defective.
    /**
     *  All these pixels will be replaced depending on the selected algorithm in \b mvIMPACT::acquire::ImageProcessing::defectivePixelsFilterMode.
     *
     *  \note
     *  In order to collect \b ALL defective pixels the list of detected pixels is not emptied each time a new calibration
     *  is started. In order to get rid of currently detected pixels an application must set the property
     *  \b mvIMPACT::acquire::ImageProcessing::defectivePixelsFilterMode to \b mvIMPACT::acquire::dpfmResetCalibration
     *  and then capture a fresh image. Only then all currently detected pixels will be discarded.
     *
     *  \since 2.17.1
     */
    PropertyI defectivePixelOffsetY;
    /// \brief Calling this method will download defective pixels from the device.
    /**
     *  \note
     *  In order to collect \b ALL defective pixels the list of detected pixels is not emptied each time a download from the device is executed.
     *  In order to get rid of currently detected pixels an application must set the property
     *  \b mvIMPACT::acquire::ImageProcessing::defectivePixelsFilterMode to \b mvIMPACT::acquire::dpfmResetCalibration
     *  and then capture a fresh image. Only then all currently detected pixels will be discarded.
     *
     *  \attention
     *  This feature will only be supported by some devices providing a special interface inside their firmware.
     *
     *  \since 2.17.1
     *
     *  Calling this method will return \n
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise. Most likely mvIMPACT::acquire::DMR_FEATURE_NOT_AVAILABLE if the device does not support this feature.
     */
    Method defectivePixelReadFromDevice;
    /// \brief Calling this method will upload defective pixels from the device.
    /**
     *  \note
     *  This will \b NOT automatically store this data in non-volatile memory on the device!
     *  A call to \b mvIMPACT::acquire::GenICam::mvDefectivePixelCorrectionControl::mvDefectivePixelDataSave might be needed!
     *
     *  \attention
     *  This feature will only be supported by some devices providing a special interface inside their firmware.
     *
     *  \since 2.17.1
     *
     *  Calling this method will return \n
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise. Most likely mvIMPACT::acquire::DMR_FEATURE_NOT_AVAILABLE if the device does not support this feature.
     */
    Method defectivePixelWriteToDevice;
    /// \brief An enumerated integer property defining the operation mode of the flat field correction filter.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TFlatFieldFilterMode.
     */
    PropertyIFlatFieldFilterMode flatFieldFilterMode;
    /// \brief An enumerated integer property defining the correction mode of the flat field correction filter.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TFlatFieldFilterCorrectionMode.
     */
    PropertyIFlatFieldFilterCorrectionMode flatFieldFilterCorrectionMode;
    /// \brief An enumerated integer property defining the X-orientation that shall be used when applying the correction.
    /**
     *  When active the calibration image will be applied reversed X direction thus the last correction factor of each line of the correction image will be applied to the first pixel of the image etc.. This can be useful e.g. if the calibration has been done and the device shall transmit the image flipped on a vertical axis in some configurations.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \since 2.40.0
     */
    PropertyIBoolean flatFieldFilterCorrectionModeReverseX;
    /// \brief An enumerated integer property defining the Y-orientation that shall be used when applying the correction.
    /**
     *  When active the calibration image will be applied reversed Y direction thus the last line of correction factors of the correction image will be applied to the first line of the image etc.. This can be useful e.g. if the calibration has been done and the device shall transmit the image flipped on a horizontal axis in some configurations.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \since 2.40.0
     */
    PropertyIBoolean flatFieldFilterCorrectionModeReverseY;
    /// \brief An enumerated integer property defining the correction AOI mode of the flat field correction filter.
    /**
     *  When using an AOI only the AOI region is corrected by this filter.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAoiMode.
     *
     *  \since 2.31.0
     */
    PropertyIAoiMode flatFieldFilterCorrectionAoiMode;
    /// \brief An integer property defining the correction AOI's X-offset of the flat field correction filter.
    /**
     *
     *  \since 2.31.0
     */
    PropertyI flatFieldFilterCorrectionAoiOffsetX;
    /// \brief An integer property defining the correction AOI's Y-offset of the flat field correction filter.
    /**
     *
     *  \since 2.31.0
     */
    PropertyI flatFieldFilterCorrectionAoiOffsetY;
    /// \brief An integer property defining the correction AOI's width of the flat field correction filter.
    /**
     *
     *  \since 2.31.0
     */
    PropertyI flatFieldFilterCorrectionAoiWidth;
    /// \brief An integer property defining the correction AOI's height of the flat field correction filter.
    /**
     *
     *  \since 2.31.0
     */
    PropertyI flatFieldFilterCorrectionAoiHeight;
    /// \brief An integer property defining the number of consecutive images to take into account during the calibration of the flat field filter.
    PropertyI flatFieldFilterCalibrationImageCount;
    /// \brief An enumerated integer property defining the correction AOI mode of the flat field correction filter.
    /**
     *  When using an AOI only the AOI region is taken into consideration during calibration by this filter.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAoiMode.
     *
     *  \since 2.31.0
     */
    PropertyIAoiMode flatFieldFilterCalibrationAoiMode;
    /// \brief An integer property defining the calibration AOI's X-offset of the flat field correction filter.
    /**
     *
     *  \since 2.31.0
     */
    PropertyI flatFieldFilterCalibrationAoiOffsetX;
    /// \brief An integer property defining the calibration AOI's Y-offset of the flat field correction filter.
    /**
     *
     *  \since 2.31.0
     */
    PropertyI flatFieldFilterCalibrationAoiOffsetY;
    /// \brief An integer property defining the calibration AOI's width of the flat field correction filter.
    /**
     *
     *  \since 2.31.0
     */
    PropertyI flatFieldFilterCalibrationAoiWidth;
    /// \brief An integer property defining the calibration AOI's height of the flat field correction filter.
    /**
     *
     *  \since 2.31.0
     */
    PropertyI flatFieldFilterCalibrationAoiHeight;
    /// \brief An enumerated integer property defining the operation mode of the dark current filter.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDarkCurrentFilterMode.
     */
    PropertyIDarkCurrentFilterMode darkCurrentFilterMode;
    /// \brief An integer property defining the number of consecutive images to take into account during calibration of the dark current filter.
    PropertyI darkCurrentFilterCalibrationImageCount;
    /// \brief An enumerated integer property which can be used to enable the Gain, Offset, Knee filter.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean gainOffsetKneeEnable;
    /// \brief A float property that contains master offset(in percent).
    /**
     *  This offset will be applied before the channel specific gain.
     */
    PropertyF gainOffsetKneeMasterOffset_pc;
    /// \brief An enumerated integer property which can be used to enable LUT (<b>L</b>ook <b>U</b>p <b>T</b>able) transformations.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean LUTEnable;
    /// \brief An enumerated integer property which can be used to configure the LUT (<b>L</b>ook <b>U</b>p <b>T</b>able) transformation mode.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TLUTMode.
     *
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse.
     */
    PropertyILUTMode LUTMode;
    /// \brief An enumerated integer property which can be used to configure the LUT (<b>L</b>ook <b>U</b>p <b>T</b>able) interpolation mode.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TLUTInterpolationMode.
     *
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTMode is \b NOT set to
     *  \b mvIMPACT::acquire::LUTmInterpolated.
     */
    PropertyILUTInterpolationMode LUTInterpolationMode;
    /// \brief An enumerated integer property which can be used to configure the LUT (<b>L</b>ook <b>U</b>p <b>T</b>able) implementation.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TLUTImplementation.
     *
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse.
     */
    PropertyILUTImplementation LUTImplementation;
    /// \brief An enumerated integer property which can be used to configure the LUT (<b>L</b>ook <b>U</b>p <b>T</b>able) mapping mode for LUT transformations done by the hardware.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TLUTMapping.
     *
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTImplementation is \b NOT set to
     *  \b mvIMPACT::acquire::LUTiHardware.
     */
    PropertyILUTMapping LUTMappingHardware;
    /// \brief An enumerated integer property which can be used to configure the LUT (<b>L</b>ook <b>U</b>p <b>T</b>able) mapping mode for LUT transformations done optimized software algorithms.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TLUTMapping.
     *
     *  \note This property will be invisible when \b mvIMPACT::acquire::ImageProcessing::LUTEnable is set to
     *  \b mvIMPACT::acquire::bFalse or if \b mvIMPACT::acquire::ImageProcessing::LUTImplementation is \b NOT set to
     *  \b mvIMPACT::acquire::LUTiSoftware.
     */
    PropertyILUTMapping LUTMappingSoftware;
    /// \brief An enumerated integer property which can be used to enable/disable automatic data re-ordering from image sources delivering data from multiple taps that require re-ordering to reconstruct the image.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean tapSortEnable;
    /// \brief An enumerated integer property which can be used to enable/disable automatic data re-ordering or extraction from multi-channel images.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean channelSplitEnable;
    /// \brief An enumerated integer property which can be used to define how data from multi-channel images shall be re-ordered.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TChannelSplitMode.
     */
    PropertyIChannelSplitMode channelSplitMode;
    /// \brief An integer property which can be used to define which channel of the image shall be extracted.
    /**
     *  This property will only be visible if \b mvIMPACT::acquire::ImageProcessing::channelSplitMode is set
     *  to \b mvIMPACT::acquire::csmExtractSingle.
     */
    PropertyI channelSplitChannelIndex;
    /// \brief An enumerated integer property which can be used to enable/disable data re-ordering for interlaced images.
    /**
     *  Enabling this feature will cause interlaced images in a way that the 2 fields will be display next to each other. This
     *  will modify the original image in an image with twice the width but half the height.
     *
     *  \note
     *  Right now this property will only result in correct results for images, that are line wise interlaced, thus
     *  some special sensors that e.g. transfer Bayer interlaced data (2 lines field 0, 2 lines field even, etc.)
     *  can not be re-arranged in a meaningful way.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean channelSplitDeinterlaceEnable;
    /// \brief An enumerated integer property which can be used to enable/disable the color twist input correction matrix.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \since 2.2.2.
     */
    PropertyIBoolean colorTwistInputCorrectionMatrixEnable;
    /// \brief An enumerated integer property which can be used to select an input color correction matrix.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TColorTwistInputCorrectionMatrixMode.
     *
     *  \since 2.2.2.
     */
    PropertyIColorTwistInputCorrectionMatrixMode colorTwistInputCorrectionMatrixMode;
    /// \brief The first row of the input color correction matrix.
    /**
     *  This property stores the first row of a user defined 3x3 input color correction matrix if
     *  \b mvIMPACT::acquire::ImageProcessing::colorTwistInputCorrectionMatrixMode is set to
     *  \b mvIMPACT::acquire::cticmmUser. For other values of \b mvIMPACT::acquire::ImageProcessing::colorTwistInputCorrectionMatrixMode
     *  modifying this property will have no effect.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistInputCorrectionMatrixRow0;
    /// \brief The second row of the input color correction matrix.
    /**
     *  This property stores the second row of a user defined 3x3 input color correction matrix if
     *  \b mvIMPACT::acquire::ImageProcessing::colorTwistInputCorrectionMatrixMode is set to
     *  \b mvIMPACT::acquire::cticmmUser. For other values of \b mvIMPACT::acquire::ImageProcessing::colorTwistInputCorrectionMatrixMode
     *  modifying this property will have no effect.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistInputCorrectionMatrixRow1;
    /// \brief The third row of the input color correction matrix.
    /**
     *  This property stores the third row of a user defined 3x3 input color correction matrix if
     *  \b mvIMPACT::acquire::ImageProcessing::colorTwistInputCorrectionMatrixMode is set to
     *  \b mvIMPACT::acquire::cticmmUser. For other values of \b mvIMPACT::acquire::ImageProcessing::colorTwistInputCorrectionMatrixMode
     *  modifying this property will have no effect.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistInputCorrectionMatrixRow2;
    /// \brief An enumerated integer property which can be used to enable/disable the color twist matrix.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  The color twist filter can be used to apply a linear transformation to a 3 channel image. Each pixel will
     *  at first be multiplied by a 3x3 matrix and afterwards an offset triplet can be added.
     *
     *  \since 2.2.2.
     */
    PropertyIBoolean colorTwistEnable;
    /// \brief The first row of the color twist matrix.
    /**
     *  This property stores 4 values. The first 3 components for the first row of the 3x4 matrix, the last component is the
     *  offset of this row.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistRow0;
    /// \brief The second row of the color twist matrix.
    /**
     *  This property stores 4 values. The first 3 components for the second row of the 3x4 matrix, the last component is the
     *  offset of this row.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistRow1;
    /// \brief The third row of the color twist matrix.
    /**
     *  This property stores 4 values. The first 3 components for the third row of the 3x4 matrix, the last component is the
     *  offset of this row.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistRow2;
    /// \brief An enumerated integer property which can be used to enable/disable the color twist output correction matrix.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \since 2.2.2.
     */
    PropertyIBoolean colorTwistOutputCorrectionMatrixEnable;
    /// \brief An enumerated integer property which can be used to select an output color correction matrix.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TColorTwistOutputCorrectionMatrixMode.
     *
     *  \since 2.2.2.
     */
    PropertyIColorTwistOutputCorrectionMatrixMode colorTwistOutputCorrectionMatrixMode;
    /// \brief The first row of the output color correction matrix.
    /**
     *  This property stores the first row of a user defined 3x3 output color correction matrix if
     *  \b mvIMPACT::acquire::ImageProcessing::colorTwistOutputCorrectionMatrixMode is set to
     *  \b mvIMPACT::acquire::ctocmmUser. For other values of \b mvIMPACT::acquire::ImageProcessing::colorTwistOutputCorrectionMatrixMode
     *  modifying this property will have no effect.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistOutputCorrectionMatrixRow0;
    /// \brief The second row of the output color correction matrix.
    /**
     *  This property stores the second row of a user defined 3x3 output color correction matrix if
     *  \b mvIMPACT::acquire::ImageProcessing::colorTwistOutputCorrectionMatrixMode is set to
     *  \b mvIMPACT::acquire::ctocmmUser. For other values of \b mvIMPACT::acquire::ImageProcessing::colorTwistOutputCorrectionMatrixMode
     *  modifying this property will have no effect.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistOutputCorrectionMatrixRow1;
    /// \brief The third row of the output color correction matrix.
    /**
     *  This property stores the third row of a user defined 3x3 output color correction matrix if
     *  \b mvIMPACT::acquire::ImageProcessing::colorTwistOutputCorrectionMatrixMode is set to
     *  \b mvIMPACT::acquire::ctocmmUser. For other values of \b mvIMPACT::acquire::ImageProcessing::colorTwistOutputCorrectionMatrixMode
     *  modifying this property will have no effect.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistOutputCorrectionMatrixRow2;
    /// \brief The first row of the resulting color twist matrix.
    /**
     *  This property will store the first row of the 3x4 resulting color twist matrix. This matrix
     *  is created by multiplying the input correction matrix by the color twist matrix by the output correction matrix.
     *  Only active matrices will be used to calculate the resulting matrix.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistResultingMatrixRow0;
    /// \brief The second row of the resulting color twist matrix.
    /**
     *  This property will store the second row of the 3x4 resulting color twist matrix. This matrix
     *  is created by multiplying the input correction matrix by the color twist matrix by the output correction matrix.
     *  Only active matrices will be used to calculate the resulting matrix.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistResultingMatrixRow1;
    /// \brief The third row of the resulting color twist matrix.
    /**
     *  This property will store the third row of the 3x4 resulting color twist matrix. This matrix
     *  is created by multiplying the input correction matrix by the color twist matrix by the output correction matrix.
     *  Only active matrices will be used to calculate the resulting matrix.
     *
     *  \since 2.2.2.
     */
    PropertyF colorTwistResultingMatrixRow2;
    /// \brief An enumerated integer property which can be used to enable/disable the format reinterpreter filter.
    /**
     *  This filter can be used if a device transmits data in a non-compliant or incorrect format. Using this filter the incoming
     *  data will simply be treated as a different pixel format then. This will \b NOT copy or modify the pixel data but will only
     *  adjust some of the elements describing the buffer (e.g. the pixel format and width). When e.g. setting this filter to treat
     *  mono data as RGB data, this will result in buffers with a width divided by 3 but RGB pixels instead of mono pixel afterwards.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \since 2.10.1
     */
    PropertyIBoolean formatReinterpreterEnable;
    /// \brief An enumerated integer property which can be used to configure the format reinterpreter filter.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TImageBufferFormatReinterpreterMode.
     *
     *  \since 2.10.1
     */
    PropertyIImageBufferFormatReinterpreterMode formatReinterpreterMode;
    /// \brief An enumerated integer property defining the new Bayer parity of this buffer.
    /**
     *  After applying the format reinterpreter this will be the new Bayer parity of the buffer when the filter is operated
     *  in one of the \c Mono \c To \c Mono modes.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBayerMosaicParity.
     *
     *  \since 2.31.0
     */
    PropertyIBayerMosaicParity formatReinterpreterBayerMosaicParity;
    /// \brief An enumerated integer property which can be used to enable/disable the rotation filter.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \since 2.13.2
     */
    PropertyIBoolean rotationEnable;
    /// \brief The counterclockwise angle at which the image will be rotated.
    /**
     *  This property will store the counterclockwise angle at which the image will be rotated.
     *
     *  \since 2.13.2
     */
    PropertyF rotationAngle;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
    /// \brief Sets the saturation by using the color twist matrix.
    /**
     *  The following saturation formula is used:
     *
     * \code
     *   [0.299 + 0.701*K       , 0.587*(1-K) , 0.114*(1-K)     ]
     *   [0.299*(1-K) + 0.701*K , 0.587       , 0.114*(1-K)     ]
     *   [0.299*(1-K) + 0.701*K , 0.587*(1-K) , 0.114 + 0.886*K ]
     * \endcode
     *
     *  K is the saturation factor
     *  K > 1 increases saturation
     *  K = 1 means no change
     *  0 < K < 1 decreases saturation
     *  K = 0 produces B&W
     *  K < 0 inverts color
     *
     *  \note
     *  To enable/disable the saturation the application must write to \b mvIMPACT::acquire::ImageProcessing::colorTwistEnable.
     */
    void setSaturation(
        /// [in] The saturation value.
        double K )
    {
        std::vector<double> row( 3, 0. );
        row[0] = 0.299       + 0.701 * K;
        row[1] = 0.587 * ( 1 - K );
        row[2] = 0.114 * ( 1 - K );
        colorTwistRow0.write( row, true );
        row[0] = 0.299 * ( 1 - K );
        row[1] = 0.587       + 0.413 * K;
        row[2] = 0.114 * ( 1 - K );
        colorTwistRow1.write( row, true );
        row[0] = 0.299 * ( 1 - K );
        row[1] = 0.587 * ( 1 - K );
        row[2] = 0.114       + 0.886 * K;
        colorTwistRow2.write( row, true );
    }
    /// \brief Returns a reference to a set of user definable parameters to configure a certain channel of the GainOffsetKnee filter.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \return A reference to one of the parameter sets for the GainOffsetKnee filter that
     *  can be altered by the user.
     */
    GainOffsetKneeChannelParameters& getGainOffsetKneeParameter(
        /// [in] The index of the gain, offset, knee parameter set to be returned
        unsigned int index ) const
    {
        return *( m_pRefData->m_GainOffsetKneeParameters.at( index ) );
    }
    /// \brief Returns the number of available user definable parameter sets for the GainOffsetKnee filter.
    unsigned int getGainOffsetKneeParameterCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_GainOffsetKneeParameters.size() );
    }
    /// \brief Returns a reference to a set of user definable parameters to configure mirror filter related features.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \return A reference to one of the parameter sets for mirror filter related features that
     *  can be altered by the user.
     */
    MirrorParameters& getMirrorParameter(
        /// [in] The index of the mirror parameter set to be returned
        unsigned int index ) const
    {
        return *( m_pRefData->m_MirrorParameters.at( index ) );
    }
    /// \brief Returns the number of available user definable parameter sets mirror filter related operations.
    unsigned int getMirrorParameterCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_MirrorParameters.size() );
    }
    /// \brief Returns a reference to a set of user definable parameters to configure LUT (<b>L</b>ook <b>U</b>p <b>T</b>able) operations.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \return A reference to one of the parameter sets for LUT (<b>L</b>ook <b>U</b>p <b>T</b>able) operations that
     *  can be altered by the user.
     */
    LUTParameters& getLUTParameter(
        /// [in] The index of the LUT parameter set to be returned
        unsigned int index ) const
    {
        return *( m_pRefData->m_LUTParameters.at( index ) );
    }
    /// \brief Returns the number of available user definable parameter sets for LUT (<b>L</b>ook <b>U</b>p <b>T</b>able) operations.
    unsigned int getLUTParameterCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_LUTParameters.size() );
    }
    /// \brief Returns a reference to a set of user definable parameters to perform a white balance correction.
    /**
     *  Pass '0' for the setting that is activated by setting the property \b mvIMPACT::acquire::ImageProcessing::whiteBalance
     *  to \b mvIMPACT::acquire::wbpUser1, '1' for
     *  \b mvIMPACT::acquire::wbpUser2 and so on.
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \return A reference to one of the parameter sets for white balance correction that
     *  can be altered by the user.
     */
    WhiteBalanceSettings& getWBUserSetting(
        /// [in] The index of the white balance parameter set to be returned
        unsigned int index ) const
    {
        return *( m_pRefData->m_WBUserSettings.at( index ) );
    }
    /// \brief Returns the number of available user definable parameter sets for white balance correction.
    unsigned int getWBUserSettingsCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_WBUserSettings.size() );
    }
};



//-----------------------------------------------------------------------------
/// \brief Convenience class to provide an easy way for a more precise white balance calibration.
/**
 *  A convenience function which will be used to do a white balance calibration
 *  with more than 8bit image data to increase the precision of the calculated
 *  gain values.
 *
 *  \note
 *  Since a homogeneous grey image is needed for the processing, it is necessary
 *  that the camera is not configured to a triggered mode and a reasonable
 *  exposure time.
 */
class WhiteBalancer
//-----------------------------------------------------------------------------
{
public:

    static void highQualityWhiteBalance( Device* pDev )
    {
        FunctionInterface fi( pDev );
        ImageProcessing ip( pDev );
        fi.saveCurrentSettingOnStack();

        PropertyI64 pixelFormat;
        DeviceComponentLocator locator( pDev, dltSetting, "" );
        locator.bindComponent( pixelFormat, "PixelFormat" );

        std::vector<std::string> availablePixelFormats;
        pixelFormat.getTranslationDictStrings( availablePixelFormats );
        std::string sBayerColorMask;
        bool boIsBayer = false;
        bool boIsMono = false;
        int iMaxBitDepth = 0;
        const std::string bayerToken = "Bayer";
        const std::string monoToken = "Mono";

        for( std::vector<std::string>::size_type i = 0; i != availablePixelFormats.size(); i++ )
        {
            boIsBayer = ( availablePixelFormats[i].find( bayerToken ) ) != std::string::npos;
            boIsMono = ( availablePixelFormats[i].find( monoToken ) ) != std::string::npos;
            std::string sTempBitDepth = "";
            for( size_t j = 0; j < availablePixelFormats[i].length(); j++ )
            {
                if( isdigit( availablePixelFormats[i][j] ) )
                {
                    sTempBitDepth += availablePixelFormats[i][j];
                }
                if( boIsBayer )
                {
                    if( sBayerColorMask == "" )
                    {
                        // extract the Bayer parity AFTER the word 'Bayer'
                        const std::string::size_type len = bayerToken.length();
                        sBayerColorMask += availablePixelFormats[i][len];
                        sBayerColorMask += availablePixelFormats[i][len + 1];
                    }
                }
            }
            const int iTempBitDepth = atoi( sTempBitDepth.c_str() );
            if( iTempBitDepth > iMaxBitDepth )
            {
                iMaxBitDepth = iTempBitDepth;
            }
        }

        const std::string sPixelFormatPrefix = ( boIsBayer && !boIsMono ) ? bayerToken : monoToken;
        std::ostringstream sOptimalPixelFormat;
        sOptimalPixelFormat << sPixelFormatPrefix << sBayerColorMask << iMaxBitDepth;

        try
        {
            pixelFormat.writeS( sOptimalPixelFormat.str() );
        }
        catch( const ImpactAcquireException& ) {}

        PropertyF balanceRatio;
        PropertyI64 balanceRatioSelector;
        locator.bindComponent( balanceRatio, "BalanceRatio" );
        locator.bindComponent( balanceRatioSelector, "BalanceRatioSelector" );

        if( ( pDev->interfaceLayout.read() == dilGenICam ) && balanceRatioSelector.isValid() && balanceRatio.isValid() )
        {
            try
            {
                balanceRatioSelector.writeS( "Red" );
                balanceRatio.write( 1.00 );

                balanceRatioSelector.writeS( "Blue" );
                balanceRatio.write( 1.00 );
            }
            catch( const ImpactAcquireException& ) {}
        }

        ip.whiteBalance.write( wbpUser1 );
        ip.whiteBalanceCalibration.write( wbcmNextFrame );

        fi.imageRequestSingle();
        fi.acquisitionStart();
        int requestNr = fi.imageRequestWaitFor( 8000 );
        Request* pRequest = fi.isRequestNrValid( requestNr ) ? fi.getRequest( requestNr ) : 0;
        if( pRequest )
        {
            pRequest->unlock();
        }
        fi.acquisitionStop();

        WhiteBalanceSettings& wbs( ip.getWBUserSetting( 0 ) );
        const double dRedGain = wbs.redGain.read();
        const double dGreenGain = wbs.greenGain.read();
        const double dBlueGain = wbs.blueGain.read();

        fi.loadAndDeleteSettingFromStack();

        if( ( pDev->interfaceLayout.read() == dilGenICam ) && balanceRatioSelector.isValid() && balanceRatio.isValid() )
        {
            balanceRatioSelector.writeS( "Red" );
            balanceRatio.write( dRedGain / dGreenGain );

            balanceRatioSelector.writeS( "Blue" );
            balanceRatio.write( dBlueGain / dGreenGain );
        }
        else
        {
            wbs.redGain.write( dRedGain );
            wbs.greenGain.write( dGreenGain );
            wbs.blueGain.write( dBlueGain );
        }
    }
};

//-----------------------------------------------------------------------------
/// \brief Contains basic statistical information.
/**
 *  This class contains basic statistical information about the \b mvIMPACT::acquire::Device and the
 *  the current image acquisition progress.
 */
class Statistics : public ComponentCollection
//-----------------------------------------------------------------------------
{
    Method m_resetStatistics;
public:
    explicit Statistics(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : ComponentCollection( pDev ), m_resetStatistics(), captureTime_s(),
        bandwidthConsumed(), errorCount(), abortedRequestsCount(), timedOutRequestsCount(), framesPerSecond(),
        frameCount(), imageProcTime_s(), formatConvertTime_s(), queueTime_s(), lostImagesCount(),
        framesIncompleteCount(), missingDataAverage_pc(), retransmitCount()
    {
        DeviceComponentLocator locator( pDev, dltStatistics );
        m_hRoot = locator.searchbase_id();
        locator.bindComponent( m_resetStatistics, "ResetStatistics@i" );
        locator.bindComponent( captureTime_s, "CaptureTime_s" );
        locator.bindComponent( bandwidthConsumed, "BandwidthConsumed" );
        locator.bindComponent( errorCount, "ErrorCount" );
        locator.bindComponent( abortedRequestsCount, "AbortedRequestsCount" );
        locator.bindComponent( timedOutRequestsCount, "TimedOutRequestsCount" );
        locator.bindComponent( framesPerSecond, "FramesPerSecond" );
        locator.bindComponent( frameCount, "FrameCount" );
        locator.bindComponent( imageProcTime_s, "ImageProcTime_s" );
        locator.bindComponent( formatConvertTime_s, "FormatConvertTime_s" );
        locator.bindComponent( queueTime_s, "QueueTime_s" );
        locator.bindComponent( lostImagesCount, "LostImagesCount" );
        locator.bindComponent( framesIncompleteCount, "FramesIncompleteCount" );
        locator.bindComponent( missingDataAverage_pc, "MissingDataAverage_pc" );
        locator.bindComponent( retransmitCount, "RetransmitCount" );
    }
    /// \brief Resets all statistical properties.
    /**
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int reset( void ) const
    {
        if( !m_resetStatistics.isValid() )
        {
            return DMR_FEATURE_NOT_AVAILABLE;
        }
        return m_resetStatistics.call();
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief A float property \b (read-only) containing the overall time an image request spent in the device drivers processing chain.
    /**
     *  This time is \b NOT the reciprocal of the frame rate, but usually a much longer period of time as it includes the time
     *  elapsed from sending the request into the capture queue until the buffer has been placed back into one of the result queues again.
     *  This time increases with the amount of requests being used.
     */
    PropertyF captureTime_s;
    /// \brief A float property \b (read-only) containing the current bandwidth consumed by this device in KB/s based on the average buffer size and the timestamps delivered from the device driver.
    /**
     *  \since 2.12.3
     */
    PropertyF bandwidthConsumed;
    /// \brief An integer property \b (read-only) containing the overall count of image requests which returned with an error since the
    /// \b mvIMPACT::acquire::Device has been opened OR since the last call to \b mvIMPACT::acquire::Statistics::reset().
    PropertyI errorCount;
    /// \brief An integer property \b (read-only) containing the overall count of image requests which have been aborted since the
    /// \b mvIMPACT::acquire::Device has been opened OR since the last call to \b mvIMPACT::acquire::Statistics::reset().
    PropertyI abortedRequestsCount;
    /// \brief An integer property \b (read-only) containing the overall count of image requests which have timed out since the
    /// \b mvIMPACT::acquire::Device has been opened OR since the last call to \b mvIMPACT::acquire::Statistics::reset().
    PropertyI timedOutRequestsCount;
    /// \brief A float property \b (read-only) containing the current number of frames captured per second.
    PropertyF framesPerSecond;
    /// \brief An integer property \b (read-only) containing the overall count of images captured since the
    /// \b mvIMPACT::acquire::Device has been opened OR since the last call to \b mvIMPACT::acquire::Statistics::reset().
    /**
     *  This counter is incremented regardless of the result a request is returned with thus also e.g. if a request did time out, was aborted(e.g. due to a call to \b mvIMPACT::acquire::FunctionInterface::imageRequestReset or \b mvIMPACT::acquire::FunctionInterface::acquisitionStop) or the data was not completely captured.
     */
    PropertyI frameCount;
    /// \brief An integer property \b (read-only) containing the time (in seconds) needed to process the image data internally.
    /**
     *  This time might be interesting e.g. if the image data is transformed into a color
     *  image by the driver (e.g. when working with Bayer mosaic cameras) or if any other processing function is applied to the
     *  image before it is transferred to the user.
     */
    PropertyF imageProcTime_s;
    /// \brief An integer property \b (read-only) containing the time (in seconds) needed to convert the image data delivered by the hardware and/or active internal driver filter nodes to the format specified by \b mvIMPACT::acquire::ImageDestination::pixelFormat internally.
    /**
     *  This time will be almost 0 when no custom destination pixel format has been specified and if a custom destination format
     *  was selected and this format differs from the pixel format that is transferred by the hardware this time will be a part
     *  (or all, but never more) than the time reported by \b mvIMPACT::acquire::Statistics::imageProcTime_s.
     *
     *  \since 1.12.58
     *
     */
    PropertyF formatConvertTime_s;
    /// \brief A float property \b (read-only) containing the average time (in seconds) a \b mvIMPACT::acquire::Request object spends in the request queue of the device.
    /**
     *  This is the time between a call to \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle() and the time the driver actually uses this buffer
     *  to capture data into it or to forward it into a kernel driver.
     */
    PropertyF queueTime_s;
    /// \brief An integer property \b (read-only) containing the number of images that have been lost from a continuous image stream coming from a video signal source.
    /**
     *  \note
     *  For some devices this value is based on an assumption so it's by no means absolutely accurate, but when this
     *  value starts to increase this might indicate that a problem is present.
     *
     *  Possible causes (among others) might be:
     *  - the capture device or device driver can't cope with the amount of data the video signal source is delivering in the current mode of operation
     *  - the capture device or device driver can't transfer all the data to the host PC because of bus bandwidth shortages
     *  - the capture device or device driver image request queue ran low because the system is busy doing other things or because of a bug
     *  in the application
     *
     *  \note
     *  This feature is supported by every device driver. If a device does not seem to support this feature (calling \b mvIMPACT::acquire::Component::isValid returns false)
     *  a driver update will fix this.
     */
    PropertyI lostImagesCount;
    /// \brief An integer property \b (read-only) containing the overall count of image requests which haven't been captured completely since the \b mvIMPACT::acquire::Device has been opened.
    /**
     *  This value is a good indicator for bandwidth problems on the device to host connection.
     *
     *  \note
     *  This feature is supported by every device driver. If a device does not seem to support this feature (calling \b mvIMPACT::acquire::Component::isValid returns false)
     *  a driver update will fix this.
     */
    PropertyI framesIncompleteCount;
    /// \brief A float property \b (read-only) containing the average amount of data missing in frames that haven't been captured completely since the \b mvIMPACT::acquire::Device has been opened OR since the last call to \b mvIMPACT::acquire::Statistics::reset().
    /**
     *  This value is a good indicator for bandwidth problems on the device to host connection.
     *
     *  \note
     *  This feature is supported by every device driver. If a device does not seem to support this feature (calling \b mvIMPACT::acquire::Component::isValid returns false)
     *  a driver update will fix this.
     */
    PropertyF missingDataAverage_pc;
    /// \brief A 64 bit integer property \b (read-only) containing the number of retransmit requests issued due to temporary bus bandwidth shortages or other transmission problems since this \b mvIMPACT::acquire::Device has been opened OR since the last call to \b mvIMPACT::acquire::Statistics::reset().
    /**
     *  This value can be an indicator for transmission problems because of bad signal quality or bus
     *  bandwidth shortages in the system.
     *  Ideally this property should stay 0 all the time if the system can cope with the amount of data transferred and the signal
     *  quality is good. However it might increase slowly and still every frame will be flawless as the driver internally was
     *  able to restore the lost data by re-requesting it from the video signal source again.
     *
     *  \note
     *  This feature is supported by every device driver. If a device does not seem to support this feature (calling \b mvIMPACT::acquire::Component::isValid returns false)
     *  a driver update will fix this.
     */
    PropertyI64 retransmitCount;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A base class that provides access to the most common settings for a device.
/**
 *  Use one of the classes derived from this class to get access to all the available
 *  settings.
 */
class FullSettingsBase
//-----------------------------------------------------------------------------
{
public:
    /// brief Constructs a new \b mvIMPACT::acquire::FullSettingsBase object.
    explicit FullSettingsBase(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : imageProcessing( pDev, settingName ), imageDestination( pDev, settingName ), basedOn()
    {
        DeviceComponentLocator locator( pDev, dltSetting, settingName );
        locator.bindComponent( basedOn, "BasedOn" );
    }
    virtual ~FullSettingsBase() {}
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief Image processing related properties.
    ImageProcessing imageProcessing;
    /// \brief Properties to define the result images format.
    ImageDestination imageDestination;
    /// \brief A string property \b (read-only) containing the name of the setting this setting is based on.
    PropertyS basedOn;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

#ifndef WRAP_ANY
/// \brief \b deprecated. Use the class \b mvIMPACT::acquire::Statistics instead
/**
 *  \deprecated
 *  This class has been declared \b deprecated and might not be available in future releases.
 *  All features of this class are available in \b mvIMPACT::acquire::Statistics as well, so please use
 *  this class instead.
 */
typedef Statistics MVIMPACT_DEPRECATED_CPP( StatisticsBase );
#endif // #ifndef WRAP_ANY

//-----------------------------------------------------------------------------
/// \brief A base class for accessing settings that control the overall behaviour of a device driver.
/**
 *  Instances of this class can't be constructed directly. Use one of the derived types.
 */
class SystemSettings : public ComponentCollection
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::SystemSettings object.
    explicit SystemSettings(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : ComponentCollection( pDev ), requestCount(),
        acquisitionMode(), acquisitionIdleTimeMax_ms(), imageProcessingMode(), imageProcessingMaximumThreadCount(), imageProcessingOptimization(),
        featurePollingEnable(), featurePollingInterval_ms(), methodPollingInterval_ms(), methodPollingMaxRetryCount()
    {
        DeviceComponentLocator locator( pDev, dltSystemSettings );
        m_hRoot = locator.searchbase_id();
        locator.bindComponent( requestCount, "RequestCount" );
        locator.bindComponent( acquisitionMode, "AcquisitionMode" );
        locator.bindComponent( acquisitionIdleTimeMax_ms, "AcquisitionIdleTimeMax_ms" );
        locator.bindComponent( imageProcessingMode, "ImageProcessingMode" );
        locator.bindComponent( imageProcessingMaximumThreadCount, "ImageProcessingMaximumThreadCount" );
        locator.bindComponent( imageProcessingOptimization, "ImageProcessingOptimization" );
        locator.bindComponent( featurePollingEnable, "FeaturePollingEnable" );
        locator.bindComponent( featurePollingInterval_ms, "FeaturePollingInterval_ms" );
        locator.bindComponent( methodPollingInterval_ms, "MethodPollingInterval_ms" );
        locator.bindComponent( methodPollingMaxRetryCount, "MethodPollingMaxRetryCount" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property defining the number of requests allocated by the driver.
    /**
     *  Each request object can be used to capture data into. Multiple requests can be processed
     *  by a device driver as background tasks.
     *
     *  Setting this property to a value at least allowing a driver to capture data for up to 500ms without user interaction (thus 0.5 times the expected frame rate) is highly
     *  recommended. Increasing this value will NOT introduce additional latency to your application. The only drawback will be additional RAM consumption by the driver but
     *  applications that do not need to copy the request buffers can even benefit from that as the overall memory fragmentation is likely to go down then.
     *  Values smaller than 3 most likely result in undesired behaviour and should be avoided unless absolutely needed.
     *
     *  \note For performance reasons this value can be increased at any time(only exception: Working with the interface layout
     *  \b mvIMPACT::acquire::dilGenICam while streaming is active) but can only be
     *  decreased when no request object is currently locked by the application and no requests has been
     *  queued for acquisition. So modifying this value might require the application to call \b mvIMPACT::acquire::FunctionInterface::imageRequestReset
     *  and several calls to \b mvIMPACT::acquire::Request::unlock before.
     *
     *  There are not too many reasons to modify the default request count suggested by the device driver. Good reasons include:
     *
     *  - a single image is huge compared to the overall system memory(e.g. a single image has 200MB while the system itself only
     *  has about 2GB of RAM. Here it might make sense to reduce the number of capture buffers to 1 or 2. Please note that in such a
     *  scenario double buffering or live display when one buffer is constantly blocked by the display engine can become a challenge!
     *  - the frame rate is high(larger than 100 frames per second) and no frames shall be lost. Here it might make sense to set
     *  the number of capture buffers to something like frame rate divided by 2 to 5 as a rule of thumb.
     *
     *  \sa
     *  \b mvIMPACT::acquire::FunctionInterface::requestCount
     */
    PropertyI requestCount;
    /// \brief An enumerated integer property defining the acquisition mode of the device.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAcquisitionMode.
     */
    PropertyIAcquisitionMode acquisitionMode;
    /// \brief An integer property defining the maximum time in ms the driver waits for new requests being queued until streaming by the device will automatically be stopped.
    /**
     *  This property defines the maximum time in milliseconds the driver waits for new \b mvIMPACT::acquire::Request objects being
     *  queued by calling \b mvIMPACT::acquire::FunctionInterface::imageRequestSingle once the driver will automatically send an
     *  acquisition stop command to a streaming device (such as a GigE Vision or USB3 Vision device) when the driver's request queue has run empty (thus the
     *  driver has no more buffers to capture data into).
     *
     *  This property will only be taken into account when \b mvIMPACT::acquire::Device::acquisitionStartStopBehaviour has been set to
     *  \b mvIMPACT::acquire::assbDefault.
     *
     *  \note
     *  This property will not be available for every device. Right now only devices operated through the \a GenTL driver package will support
     *  this feature.
     *
     *  \since 2.4.1
     */
    PropertyI acquisitionIdleTimeMax_ms;
    /// \brief An enumerated integer property influencing the behaviour of the internal image processing pipeline.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TImageProcessingMode.
     *
     *  \note
     *  This property will only be available if \b mvIMPACT::acquire::Device::userControlledImageProcessingEnable has been
     *  set to \b mvIMPACT::acquire::bTrue before the device is opened.
     *
     * \sa
     * \b mvIMPACT::acquire::Device::userControlledImageProcessingEnable \n
     * \b mvIMPACT::acquire::Request::hasProcessingBeenSkipped
     *
     *  \since 2.14.0
     *
     */
    PropertyIImageProcessingMode imageProcessingMode;
    /// \brief An integer property influencing the number of parallel threads used by the internal image processing pipeline.
    /**
     * This property can be used to control the size of the internal thread pool used for image processing tasks. Using
     * a value higher than the number of physical CPU cores usually has a negative impact on the performance. Use with care!
     *
     * \note
     * This property will only be available on some platforms. Always check if this property is available before using it!
     *
     * \sa
     * \b mvIMPACT::acquire::SystemSettings::imageProcessingOptimization \n
     * \b mvIMPACT::acquire::SystemSettings::imageProcessingMode \n
     * \ref ImageProcessing_General_Multithreading
     *
     *  \since 2.41.0
     *
     */
    PropertyI imageProcessingMaximumThreadCount;
    /// \brief An enumerated integer property influencing the behaviour of the internal image processing algorithms.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TImageProcessingOptimization.
     *
     *  \since 2.12.2
     */
    PropertyIImageProcessingOptimization imageProcessingOptimization;
    /// \brief An enumerated integer property defining whether features defining a polling time shall be updated automatically or not.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     * \sa mvIMPACT::acquire::SystemSettings::featurePollingInterval_ms
     */
    PropertyIBoolean featurePollingEnable;
    /// \brief An integer property defining the polling interval in ms the driver waits for each iteration before running through update loop again.
    /**
     *  Some features define a so called \c polling \c time. This is a recommendation by the device/driver stating that this property
     *  might change its value without user interaction act a certain rate (e.g. the device temperature could be one example for a
     *  feature with such a behaviour). When \b mvIMPACT::acquire::SystemSettings::featurePollingEnable is set to
     *  \b mvIMPACT::acquire::bTrue a thread will check every \c featurePollingInterval_ms if features need to be updated. This will
     *  only cause communication with a device for each feature whose polling time has elapsed.
     *
     *  \note
     *  This property will not be available for every device. Right now only devices operated through the \a GenTL driver package will support
     *  this feature.
     *
     *  \since 2.18.3
     */
    PropertyI featurePollingInterval_ms;
    /// \brief An integer property defining the polling interval in ms the driver waits during each iteration before checking a methods execution state again.
    /**
     *  When working with a GenICam compliant device, GenICam method objects need to be checked for their completion status every now
     *  and then. This parameter defines how often this shall be done.
     *
     *  \note
     *  This property will not be available for every device. Right now only devices operated through the \a GenTL driver package will support
     *  this feature.
     *
     *  \since 2.18.3
     */
    PropertyI methodPollingInterval_ms;
    /// \brief An integer property defining the polling interval in ms the driver waits during each iteration before checking a methods execution state again.
    /**
     *  When working with a GenICam compliant device, GenICam method objects need to be checked for their completion status every now
     *  and then. This parameter defines how often this shall be done at all. A method is checked for completion \c
     *  methodPollingMaxRetryCount * \c methodPollingInterval_ms at max. Until then either the device starts to inform the driver
     *  that it needs more time \b OR the execution of the method has completed successfully \b or an error will be generated.
     *
     *  \note
     *  This property will not be available for every device. Right now only devices operated through the \a GenTL driver package will support
     *  this feature.
     *
     *  \since 2.18.3
     */
    PropertyI methodPollingMaxRetryCount;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

#ifndef WRAP_ANY
/// \brief \b deprecated. Use the class \b mvIMPACT::acquire::SystemSettings instead
/**
 *  \deprecated
 *  This class has been declared \b deprecated and might not be available in future releases.
 *  All features of this class are available in \b mvIMPACT::acquire::SystemSettings as well, so please use
 *  this class instead.
 */
typedef SystemSettings MVIMPACT_DEPRECATED_CPP( SystemBase );
#endif // #ifndef WRAP_ANY

/// @}

#ifndef IGNORE_MVDEVICE_SPECIFIC_INTERFACE_DOCUMENTATION

/// \defgroup DeviceSpecificInterface Device specific interface layout
/// \brief Classes and functions that will be available if the device is used in \a device \a specific interface layout.
///
/// This group contains classes and functions that will be available if the device is used
/// in \b mvIMPACT::acquire::dilDeviceSpecific interface layout.
///
/// @{

#if defined(WRAP_JAVA) || defined(BUILD_FOR_JAVA)
typedef EnumPropertyI<int> PropertyIAcquisitionField;
typedef EnumPropertyI<int> PropertyIAutoControlSpeed;
typedef EnumPropertyI<int> PropertyIAutoControlMode;
typedef EnumPropertyI<int> PropertyIAutoExposureControl;
typedef EnumPropertyI<int> PropertyIAutoGainControl;
typedef EnumPropertyI<int> PropertyIAutoOffsetCalibration;
typedef EnumPropertyI<int> PropertyIBlueFOXDigitalInputThreshold;
typedef EnumPropertyI<int> PropertyIBlueFOXFooterMode;
typedef EnumPropertyI<int> PropertyIBlueFOXInfoSensorCapabilities;
typedef EnumPropertyI<int> PropertyIBlueFOXOffsetAutoBlackSpeed;
typedef EnumPropertyI<int> PropertyIBlueFOXSensorTiming;
typedef EnumPropertyI<int> PropertyIBlueFOXTransferSize;
typedef EnumPropertyI<int> PropertyICameraAoiMode;
typedef EnumPropertyI<int> PropertyICameraBinningMode;
typedef EnumPropertyI<int> PropertyICameraDataFormat;
typedef EnumPropertyI<int> PropertyICameraExposeMode;
typedef EnumPropertyI<int> PropertyICameraExternalSyncEdge;
typedef EnumPropertyI<int> PropertyICameraExternalSyncOutput;
typedef EnumPropertyI<int> PropertyICameraFlashMode;
typedef EnumPropertyI<int> PropertyICameraFlashType;
typedef EnumPropertyI<int> PropertyICameraHDRMode;
typedef EnumPropertyI<int> PropertyICameraInterlacedType;
typedef EnumPropertyI<int> PropertyICameraLinkDataValidMode;
typedef EnumPropertyI<int> PropertyICameraPixelClock;
typedef EnumPropertyI<int> PropertyICameraScanMode;
typedef EnumPropertyI<int> PropertyICameraShutterMode;
typedef EnumPropertyI<int> PropertyICameraTapsXGeometry;
typedef EnumPropertyI<int> PropertyICameraTapsYGeometry;
typedef EnumPropertyI<int> PropertyICameraTriggerMode;
typedef EnumPropertyI<int> PropertyICameraTestMode;
typedef EnumPropertyI<int> PropertyICameraSerialPortBaudRate;
typedef EnumPropertyI<int> PropertyICameraTriggerSource;
typedef EnumPropertyI<int> PropertyIClampMode;
typedef EnumPropertyI<int> PropertyIDeviceAdvancedOptions;
typedef EnumPropertyI<int> PropertyIDeviceDigitalOutputMode;
typedef EnumPropertyI<int> PropertyIDeviceEventMode;
typedef EnumPropertyI<int> PropertyIDeviceEventType;
typedef EnumPropertyI<int> PropertyIDeviceImageTrigger;
typedef EnumPropertyI<int> PropertyIDevicePowerMode;
typedef EnumPropertyI<int> PropertyIDeviceScanRateMode;
typedef EnumPropertyI<int> PropertyIDeviceSignalOutputStartEvent;
typedef EnumPropertyI<int> PropertyIDeviceSyncOutMode;
typedef EnumPropertyI<int> PropertyIDeviceTriggerInterface;
typedef EnumPropertyI<int> PropertyIDeviceTriggerMode;
typedef EnumPropertyI<int> PropertyIDigIOState;
typedef EnumPropertyI<int> PropertyIDigitalIOMeasurementMode;
typedef EnumPropertyI<int> PropertyIDigitalIOMeasurementSource;
typedef EnumPropertyI<int> PropertyIDigitalOutputControlMode;
typedef EnumPropertyI<int> PropertyIDigitalSignal;
typedef std::vector<std::pair<std::string, int> > TDigitalSignalTranslationDict;
typedef EnumPropertyI<int> PropertyIFieldGateMode;
typedef EnumPropertyI<int> PropertyII2COperationMode;
typedef EnumPropertyI<int> PropertyII2COperationStatus;
typedef EnumPropertyI<int> PropertyIInfoSensorColorMode;
typedef EnumPropertyI<int> PropertyIInfoSensorType;
typedef EnumPropertyI<int> PropertyIInterlacedMode;
typedef EnumPropertyI<int> PropertyILineCounter;
typedef EnumPropertyI<int> PropertyIMemoryManagerMode;
typedef EnumPropertyI<int> PropertyIMemoryManagerPoolMode;
typedef EnumPropertyI<int> PropertyIOnBoardMemoryMode;
typedef EnumPropertyI<int> PropertyIPulseStartTrigger;
typedef EnumPropertyI<int> PropertyIRTCtrlModes;
typedef EnumPropertyI<int> PropertyIRTProgOpCodes;
typedef EnumPropertyI<int> PropertyIScanClock;
typedef EnumPropertyI<int> PropertyIScanStandard;
typedef EnumPropertyI<int> PropertyITriggerMoment;
typedef EnumPropertyI<int> PropertyIVideoStandard;
typedef EnumPropertyI<int> PropertyIVirtualDeviceImageType;
typedef EnumPropertyI<int> PropertyIVirtualDeviceTestMode;
#else
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TAcquisitionField.
typedef EnumPropertyI<TAcquisitionField> PropertyIAcquisitionField;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TAutoControlSpeed.
typedef EnumPropertyI<TAutoControlSpeed> PropertyIAutoControlSpeed;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TAutoControlMode.
typedef EnumPropertyI<TAutoControlMode> PropertyIAutoControlMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TAutoExposureControl.
typedef EnumPropertyI<TAutoExposureControl> PropertyIAutoExposureControl;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TAutoGainControl.
typedef EnumPropertyI<TAutoGainControl> PropertyIAutoGainControl;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TAutoOffsetCalibration.
typedef EnumPropertyI<TAutoOffsetCalibration> PropertyIAutoOffsetCalibration;

#ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBlueFOXDigitalInputThreshold.
typedef EnumPropertyI<TBlueFOXDigitalInputThreshold> PropertyIBlueFOXDigitalInputThreshold;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBlueFOXFooterMode.
typedef EnumPropertyI<TBlueFOXFooterMode> PropertyIBlueFOXFooterMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBlueFOXInfoSensorCapabilities.
typedef EnumPropertyI<TBlueFOXInfoSensorCapabilities> PropertyIBlueFOXInfoSensorCapabilities;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBlueFOXOffsetAutoBlackSpeed.
typedef EnumPropertyI<TBlueFOXOffsetAutoBlackSpeed> PropertyIBlueFOXOffsetAutoBlackSpeed;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBlueFOXSensorTiming.
typedef EnumPropertyI<TBlueFOXSensorTiming> PropertyIBlueFOXSensorTiming;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TBlueFOXTransferSize.
typedef EnumPropertyI<TBlueFOXTransferSize> PropertyIBlueFOXTransferSize;
#endif // #ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraAoiMode.
typedef EnumPropertyI<TCameraAoiMode> PropertyICameraAoiMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraBinningMode.
typedef EnumPropertyI<TCameraBinningMode> PropertyICameraBinningMode;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraDataFormat.
typedef EnumPropertyI<TCameraDataFormat> PropertyICameraDataFormat;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraExposeMode.
typedef EnumPropertyI<TCameraExposeMode> PropertyICameraExposeMode;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraExternalSyncEdge.
typedef EnumPropertyI<TCameraExternalSyncEdge> PropertyICameraExternalSyncEdge;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraExternalSyncOutput.
typedef EnumPropertyI<TCameraExternalSyncOutput> PropertyICameraExternalSyncOutput;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraFlashMode.
typedef EnumPropertyI<TCameraFlashMode> PropertyICameraFlashMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraFlashType.
typedef EnumPropertyI<TCameraFlashType> PropertyICameraFlashType;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraHDRMode.
typedef EnumPropertyI<TCameraHDRMode> PropertyICameraHDRMode;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraInterlacedType.
typedef EnumPropertyI<TCameraInterlacedType> PropertyICameraInterlacedType;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraLinkDataValidMode.
typedef EnumPropertyI<TCameraLinkDataValidMode> PropertyICameraLinkDataValidMode;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraPixelClock.
typedef EnumPropertyI<TCameraPixelClock> PropertyICameraPixelClock;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraScanMode.
typedef EnumPropertyI<TCameraScanMode> PropertyICameraScanMode;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

#ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraShutterMode.
typedef EnumPropertyI<TCameraShutterMode> PropertyICameraShutterMode;
#endif // #ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraTapsXGeometry.
typedef EnumPropertyI<TCameraTapsXGeometry> PropertyICameraTapsXGeometry;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraTapsYGeometry.
typedef EnumPropertyI<TCameraTapsYGeometry> PropertyICameraTapsYGeometry;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraTriggerMode.
typedef EnumPropertyI<TCameraTriggerMode> PropertyICameraTriggerMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraTestMode.
typedef EnumPropertyI<TCameraTestMode> PropertyICameraTestMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraSerialPortBaudRate.
typedef EnumPropertyI<TCameraSerialPortBaudRate> PropertyICameraSerialPortBaudRate;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TCameraTriggerSource.
typedef EnumPropertyI<TCameraTriggerSource> PropertyICameraTriggerSource;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TClampMode.
typedef EnumPropertyI<TClampMode> PropertyIClampMode;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceAdvancedOptions.
typedef EnumPropertyI<TDeviceAdvancedOptions> PropertyIDeviceAdvancedOptions;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceDigitalOutputMode.
typedef EnumPropertyI<TDeviceDigitalOutputMode> PropertyIDeviceDigitalOutputMode;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceImageTrigger.
typedef EnumPropertyI<TDeviceImageTrigger> PropertyIDeviceImageTrigger;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

#ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDevicePowerMode.
typedef EnumPropertyI<TDevicePowerMode> PropertyIDevicePowerMode;
#endif // #ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceScanRateMode.
typedef EnumPropertyI<TDeviceScanRateMode> PropertyIDeviceScanRateMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceSignalOutputStartEvent.
typedef EnumPropertyI<TDeviceSignalOutputStartEvent> PropertyIDeviceSignalOutputStartEvent;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceSyncOutMode.
typedef EnumPropertyI<TDeviceSyncOutMode> PropertyIDeviceSyncOutMode;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceTriggerInterface.
typedef EnumPropertyI<TDeviceTriggerInterface> PropertyIDeviceTriggerInterface;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDeviceTriggerMode.
typedef EnumPropertyI<TDeviceTriggerMode> PropertyIDeviceTriggerMode;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDigIOState.
typedef EnumPropertyI<TDigIOState> PropertyIDigIOState;

#ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDigitalIOMeasurementMode.
typedef EnumPropertyI<TDigitalIOMeasurementMode> PropertyIDigitalIOMeasurementMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDigitalIOMeasurementSource.
typedef EnumPropertyI<TDigitalIOMeasurementSource> PropertyIDigitalIOMeasurementSource;
#endif // #ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDigitalOutputControlMode.
typedef EnumPropertyI<TDigitalOutputControlMode> PropertyIDigitalOutputControlMode;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TDigitalSignal.
typedef EnumPropertyI<TDigitalSignal> PropertyIDigitalSignal;
typedef std::vector<std::pair<std::string, TDigitalSignal> > TDigitalSignalTranslationDict;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TFieldGateMode.
typedef EnumPropertyI<TFieldGateMode> PropertyIFieldGateMode;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TI2COperationMode.
typedef EnumPropertyI<TI2COperationMode> PropertyII2COperationMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TI2COperationStatus.
typedef EnumPropertyI<TI2COperationStatus> PropertyII2COperationStatus;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TInfoSensorColorMode.
typedef EnumPropertyI<TInfoSensorColorMode> PropertyIInfoSensorColorMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TInfoSensorType.
typedef EnumPropertyI<TInfoSensorType> PropertyIInfoSensorType;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TInterlacedMode.
typedef EnumPropertyI<TInterlacedMode> PropertyIInterlacedMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TLineCounter.
typedef EnumPropertyI<TLineCounter> PropertyILineCounter;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

#if !defined(IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION) || !defined(IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION)
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TMemoryManagerMode.
typedef EnumPropertyI<TMemoryManagerMode> PropertyIMemoryManagerMode;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TMemoryManagerPoolMode.
typedef EnumPropertyI<TMemoryManagerPoolMode> PropertyIMemoryManagerPoolMode;
#endif // #if !defined(IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION) || !defined(IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION)

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TOnBoardMemoryMode.
typedef EnumPropertyI<TOnBoardMemoryMode> PropertyIOnBoardMemoryMode;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TPulseStartTrigger.
typedef EnumPropertyI<TPulseStartTrigger> PropertyIPulseStartTrigger;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TRTCtrlModes.
typedef EnumPropertyI<TRTCtrlModes> PropertyIRTCtrlModes;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TRTProgOpCodes.
typedef EnumPropertyI<TRTProgOpCodes> PropertyIRTProgOpCodes;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TScanClock.
typedef EnumPropertyI<TScanClock> PropertyIScanClock;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TScanStandard.
typedef EnumPropertyI<TScanStandard> PropertyIScanStandard;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TTriggerMoment.
typedef EnumPropertyI<TTriggerMoment> PropertyITriggerMoment;

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TVideoStandard.
typedef EnumPropertyI<TVideoStandard> PropertyIVideoStandard;
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

#ifndef IGNORE_MVVIRTUALDEVICE_SPECIFIC_DOCUMENTATION
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TVirtualDeviceImageType.
typedef EnumPropertyI<TVirtualDeviceImageType> PropertyIVirtualDeviceImageType;
/// \brief Defines a property for values defined by \b mvIMPACT::acquire::TVirtualDeviceTestMode.
typedef EnumPropertyI<TVirtualDeviceTestMode> PropertyIVirtualDeviceTestMode;
#endif // #ifndef IGNORE_MVVIRTUALDEVICE_SPECIFIC_DOCUMENTATION
#endif // #if defined(WRAP_JAVA) || defined(BUILD_FOR_JAVA)

#   ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief An interface class to access DMA memory related properties(\b Device specific interface layout only).
/**
 *  This class can be used to configure the way the device works with DMA memory.
 *  This is an advanced feature and shall only be used if necessary or to
 *  fine tune an application to achieve optimal performance.
 *
 *  All frame grabbers belonging to the mvTITAN, mvGAMMA, mvSIGMA and mvDELTA series use a special,
 *  preallocated block of memory(DMA memory) as target for fast image transfer. The total size of
 *  this block has to be set during driver installation. The memory is claimed from the operating
 *  system during startup and is shared between all installed devices.
 *
 *  The memory size needed to achieve optimal performance depends on the image size to grab, the queue depth
 *  and the mode the memory manager is operated in.
 *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TMemoryManagerMode
 *  and can be selected by modifying the property \b mvIMPACT::acquire::ImageMemoryManager::mode.
 *
 *  \note This class is currently available for frame grabber devices only.
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class ImageMemoryManager : public ComponentCollection
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::ImageMemoryManager object.
    explicit ImageMemoryManager(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : ComponentCollection( pDev ),
        mode(), allocatedDMAMemory_bytes(),
        usedDMAMemory_bytes(), usedBlocks(),
        poolMode(), poolBlockSize_bytes(),
        poolBlockCount()
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        DeviceComponentLocator locator( pDev, dltImageMemoryManager );
        m_hRoot = locator.searchbase_id();
        locator.bindComponent( mode, "Mode" );
        locator.bindComponent( allocatedDMAMemory_bytes, "AllocatedDMAMemory_bytes" );
        locator.bindComponent( usedDMAMemory_bytes, "UsedDMAMemory_bytes" );
        locator.bindComponent( usedBlocks, "UsedBlocks" );
        locator.bindComponent( poolMode, "PoolMode" );
        locator.bindComponent( poolBlockSize_bytes, "PoolBlockSize_bytes" );
        locator.bindComponent( poolBlockCount, "PoolBlockCount" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property containing the mode the memory manager is currently operated in.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TMemoryManagerMode.
     */
    PropertyIMemoryManagerMode mode;
    /// \brief An integer property \b (read-only) containing the size of the allocated DMA memory (in bytes).
    PropertyI allocatedDMAMemory_bytes;
    /// \brief An integer property \b (read-only) containing the size of the DMA memory (in bytes) currently used by the device.
    PropertyI usedDMAMemory_bytes;
    /// \brief An integer property \b (read-only) containing the number of individual blocks of DMA memory currently used by the device.
    PropertyI usedBlocks;
    /// \brief An enumerated integer property containing the mode the memory managers memory pool is currently operated in.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TMemoryManagerPoolMode.
     */
    PropertyIMemoryManagerPoolMode poolMode;
    /// \brief An integer property defining the size (in bytes) to use for each block of DMA memory.
    PropertyI poolBlockSize_bytes;
    /// \brief An integer property \b (read-only) containing the number of individual blocks of DMA memory currently available when using the current pool block size and pool mode.
    PropertyI poolBlockCount;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

#   if !defined(IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION) || !defined(IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION)
//-----------------------------------------------------------------------------
/// \brief A more specific class to query information about a \b mvBlueDevice device and its driver(\b Device specific interface layout only).
/**
 *  This class contains a collection of properties providing various information about
 *  a \b mvBlueDevice device and its driver.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class InfoBlueDevice : public Info
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::InfoBlueDevice object.
    explicit InfoBlueDevice(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : Info( pDev ),
        sensorXRes(), sensorYRes(), sensorColorMode(), sensorType()
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        ComponentLocator locator( m_hRoot, "Camera" );
        locator.bindComponent( sensorXRes, "SensorXRes" );
        locator.bindComponent( sensorYRes, "SensorYRes" );
        locator.bindComponent( sensorColorMode, "SensorColorMode" );
        locator.bindComponent( sensorType, "SensorType" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property \b (read-only) containing the horizontal resolution of the camera sensor.
    /**
     *  If the device has more than one sensor head, and all these sensor heads can be accessed using the current interface,
     *  this property will contain as many values as the devices offers sensor heads.
     */
    PropertyI sensorXRes;
    /// \brief An integer property \b (read-only) containing the vertical resolution of the camera sensor.
    /**
     *  If the device has more than one sensor head, and all these sensor heads can be accessed using the current interface,
     *  this property will contain as many values as the devices offers sensor heads.
     */
    PropertyI sensorYRes;
    /// \brief An enumerated integer property \b (read-only) containing the type of the sensor (color/mono/...)(if known).
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TInfoSensorColorMode.
     *
     *  \note
     *  If nothing is known about this feature, this property will contain \b mvIMPACT::acquire::iscmUnknown.
     *
     *  If the device has more than one sensor head, and all these sensor heads can be accessed using the current interface,
     *  this property will contain as many values as the devices offers sensor heads.
     */
    PropertyIInfoSensorColorMode sensorColorMode;
    /// \brief An enumerated integer property \b (read-only) containing the type of sensor chip of the camera (if known).
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TInfoSensorType.
     *
     *  This usually will either be \b mvIMPACT::acquire::istCCD or \b mvIMPACT::acquire::istCMOS.
     *
     *  If the device has more than one sensor head, and all these sensor heads can be accessed using the current interface,
     *  this property will contain as many values as the devices offers sensor heads.
     */
    PropertyIInfoSensorType sensorType;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #if !defined(IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION) || !defined(IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION)

#   ifndef IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief A more specific class to query information about a \b mvBlueCOUGAR devices and its driver(\b Device specific interface layout only).
/**
 *  This class contains a collection of properties providing various information about
 *  a \b mvBlueCOUGAR devices and its driver.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class InfoBlueCOUGAR : public InfoBlueDevice
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::InfoBlueCOUGAR object.
    explicit InfoBlueCOUGAR(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : InfoBlueDevice( pDev ), deviceFPGAVersion()
    {
        ComponentLocator locator( m_hRoot, "Camera" );
        locator.bindComponent( deviceFPGAVersion, "DeviceFPGAVersion" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief A 64 bit integer property \b (read-only) containing the current FPGA version of this device.
    /**
     *  \note
     *  This feature is only supported by \b mvBlueCOUGAR-S devices.
     */
    PropertyI64 deviceFPGAVersion;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION

#   ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief A more specific class to query information about a \b mvBlueFOX device and its driver(\b Device specific interface layout only).
/**
 *  This class contains a collection of properties providing various information about
 *  a \b mvBlueFOX device and its driver.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class InfoBlueFOX : public InfoBlueDevice
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::InfoBlueFOX object.
    explicit InfoBlueFOX(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : InfoBlueDevice( pDev ), firmwareVersion(), sensorFPGAVersion(), sensorCaps(),
        deviceSensorRevision(), userEEPROMSize(), deviceTemperature()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( firmwareVersion, "FirmwareVersion" );
        locator.bindSearchBase( locator.searchbase_id(), "Camera" );
        locator.bindComponent( sensorFPGAVersion, "SensorFPGAVersion" );
        locator.bindComponent( sensorCaps, "SensorCaps" );
        locator.bindComponent( deviceSensorRevision, "DeviceSensorRevision" );
        locator.bindComponent( userEEPROMSize, "UserEEPROMSize" );
        locator.bindComponent( deviceTemperature, "DeviceTemperature" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property \b (read-only) containing the firmware version of this device.
    PropertyI firmwareVersion;
    /// \brief An integer property \b (read-only) containing the FPGA version of the camera(if known).
    /**
     *  \note
     *  If nothing is known about this feature, this property will contain '-1'.
     */
    PropertyI sensorFPGAVersion;
    /// \brief An integer property \b (read-only) containing a bit mask containing information about the sensors capabilities(if known).
    /**
     *  \note
     *  If nothing is known about this feature, this property will contain '-1'.
     */
    PropertyIBlueFOXInfoSensorCapabilities sensorCaps;
    /// \brief A 64 bit integer property \b (read-only) containing the current revision of the sensor head of this device.
    /**
     *  \note
     *  This feature is currently not supported by all sensors. If a sensor can't provide this information, the value
     *  of this property will remain 0 at all time.
     *
     *  \since 1.12.65
     */
    PropertyI64 deviceSensorRevision;
    /// \brief An integer property \b (read-only) containing the size of the user EEPROM that can be accessed using the I2C access features of \b mvIMPACT::acquire::I2CControl.
    /**
     *  \note
     *  The size may vary depending on the product. Even different products with the same sensor might report
     *  different values here.
     *
     *  \note
     *  The user EEPROM uses a virtual I2C address of 0x1A2 for write access and 0x1A3 for read access.
     */
    PropertyI userEEPROMSize;
    /// \brief A float property \b (read-only) containing the temperature of the selected temperature sensor on the device in degrees Celsius.
    /**
     *  \note
     *  This property will not be available for every mvBlueFOX. Right now this feature is only implemented for
     *  202d version of the mvBlueFOX.
     *
     *  \since 1.12.62
     *
     */
    PropertyF deviceTemperature;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION

//-----------------------------------------------------------------------------
/// \brief A class to represent a digital input pin(\b Device specific interface layout only).
/**
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class DigitalInput
//-----------------------------------------------------------------------------
{
    friend class    IOSubSystem;
    HDRV            m_hDrv;
    PropertyI       m_register;
    int             m_bitNumber;
    std::string     m_description;
    explicit        DigitalInput( HDRV hDrv, PropertyI reg, int bitNumber, const std::string& desc ) : m_hDrv( hDrv ), m_register( reg ), m_bitNumber( bitNumber ), m_description( desc ) {}
public:
    /// \brief Returns the current state of this input pin.
    /**
     *  \return
     *  - true if the current state of this pin is considered as 'logic 1'
     *  - false otherwise
     */
    bool get( void ) const
    {
        const TDMR_ERROR result = DMR_UpdateDigitalInputs( m_hDrv );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        return m_register.read( m_bitNumber ) != 0;
    }
    /// \brief Returns a description for this digital input.
    /**
     *  This might contain connector descriptions or other information like
     *  e.g. 'Trigger-In(J8.4/J8.5)', which means, this is the trigger input
     *  of connector \a J8 pins \a 4 and \a 5.
     */
    std::string getDescription( void ) const
    {
        return m_description;
    }
};

//-----------------------------------------------------------------------------
/// \brief A class to represent a digital output pin(\b Device specific interface layout only).
/**
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class DigitalOutput
//-----------------------------------------------------------------------------
{
    friend class    IOSubSystem;
    PropertyI       m_register;
    int             m_bitNumber;
    std::string     m_description;
    explicit        DigitalOutput( PropertyI reg, int bitNumber, const std::string& desc ) : m_register( reg ), m_bitNumber( bitNumber ), m_description( desc ) {}
public:
    /// \brief Inverts the current state of the digital output and returns the previous state.
    /**
     *  \return
     *  - true if the previous state of this pin was considered as 'logic 1'
     *  - false otherwise
     */
    bool flip( void )
    {
        bool oldState = get();
        m_register.write( !oldState, m_bitNumber );
        return oldState;
    }
    /// \brief Returns the current state of this output pin.
    /**
     *  \return
     *  - true if the current state of this pin is considered as 'logic 1'
     *  - false otherwise
     */
    bool get( void ) const
    {
        return m_register.read( m_bitNumber ) != 0;
    }
    /// \brief Checks if the caller has write/modify access to this digital output.
    /**
     *  Some devices will offer access to digital outputs, but these outputs can't be switched manually.
     *  E.g. a device might offer a digital output that can only be configured to stay either high or
     *  low during frame exposure but can't be switched to high at a certain user defined moment. For
     *  such an output, this function will return false.
     *
     *  If the user calls a function belonging to this class that would modify the state of the
     *  associated digital output, an exception will be raised.
     *
     *  \return
     *  - true if the caller is allowed to call write/modify operation for this component.
     *  - false otherwise.
     */
    bool isWriteable( void ) const
    {
        return m_register.isWriteable();
    }
    /// \brief Sets the output pin to 'logic 1'.
    void set( void )
    {
        m_register.write( 1, m_bitNumber );
    }
    /// \brief Sets the output pin to 'logic 0'.
    void reset( void )
    {
        m_register.write( 0, m_bitNumber );
    }
    /// \brief Returns a description for this digital output.
    /**
     *  This might contain connector descriptions or other information like
     *  e.g. 'CC1(J1)', which means, this is the CameraLink&reg; control
     *  channel 1 of connector \a J1.
     */
    std::string getDescription( void ) const
    {
        return m_description;
    }
};

//-----------------------------------------------------------------------------
/// \brief A class to represent a sync. output pin(\b Device specific interface layout only).
/**
 *  Instances of this class can be used to define and generate sync. signals
 *  at the corresponding outputs of the device.
 *
 *  \note
 *  Instances of this class can't be constructed directly, but must be obtained
 *  via the device specific class derived from \b mvIMPACT::acquire::IOSubSystem.
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class SyncOutput : public ComponentCollection
//-----------------------------------------------------------------------------
{
    friend class IOSubSystem;
    explicit SyncOutput( HLIST hList ) : ComponentCollection( hList ), frequency_Hz(), lowPart_pc()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( frequency_Hz, "Frequency_Hz" );
        locator.bindComponent( lowPart_pc, "LowPart_pc" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief A float property defining the frequency(in Hertz) for the sync. signal generated by this pin.
    PropertyF frequency_Hz;
    /// \brief A float property defining the width in percent the sync. signal stays low during one period. The output signal generated will be a square pulse.
    PropertyF lowPart_pc;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
    /// \brief Returns a description for this sync. output.
    /**
     *  This might contain connector descriptions or other information like
     *  e.g. 'VD-OUT(J9.24)', which means, this is the VD output at connector J9
     *  pin 24.
     */
    std::string getDescription( void ) const
    {
        return ComponentList( m_hRoot ).name();
    }
};

//-----------------------------------------------------------------------------
/// \brief A class to represent one step of a real time control(\b RTCtr) program (\b Device specific interface layout only).
/**
 *  An object of this class represents a single instruction in a program represented
 *  by an \b mvIMPACT::acquire::RTCtrProgram. \b mvIMPACT::acquire::RTCtrProgramStep object can't be constructed
 *  directly, but must be accessed via the function
 *  \b mvIMPACT::acquire::RTCtrProgram::programStep of the program they belong
 *  to.
 *
 *  The instruction this \b mvIMPACT::acquire::RTCtrProgramStep will executed when the program is
 *  executed is defined by the property \b mvIMPACT::acquire::RTCtrProgramStep::opCode. Depending
 *  on the value of this property certain other parameters will influence the
 *  behaviour of this instruction.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class RTCtrProgramStep : public ComponentCollection
//-----------------------------------------------------------------------------
{
    friend class RTCtrProgram;
    explicit RTCtrProgramStep( HOBJ hObj ) : ComponentCollection( hObj ), address(), frameID(), clocks_us(),
        digitalInputs(), digitalOutputs(), sensorHeads(), opCode(), controllerRegister(),
        registerValue()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( address, "Address" );
        locator.bindComponent( frameID, "FrameID" );
        locator.bindComponent( clocks_us, "Clocks_us" );
        locator.bindComponent( digitalInputs, "DigitalInputs" );
        locator.bindComponent( digitalOutputs, "DigitalOutputs" );
        locator.bindComponent( sensorHeads, "SensorHeads" );
        locator.bindComponent( opCode, "OpCode" );
        locator.bindComponent( controllerRegister, "ControllerRegister" );
        locator.bindComponent( registerValue, "RegisterValue" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property, which defines the absolute jump address within this \b mvIMPACT::acquire::RTCtrProgram.
    /**
     *  This property only is taken into account, if \b mvIMPACT::acquire::RTCtrProgramStep::opCode is set to \b mvIMPACT::acquire::rtctrlProgJumpLoc.
     */
    PropertyI address;
    /// \brief An integer property, which defines the frame ID of the triggered image \b mvIMPACT::acquire::RTCtrProgram.
    /**
     *  This property only is taken into account, if \b mvIMPACT::acquire::RTCtrProgramStep::opCode is set to \b mvIMPACT::acquire::rtctrlProgTriggerSet.
     */
    PropertyI frameID;
    /// \brief An integer property, which defines the waiting time \b mvIMPACT::acquire::RTCtrProgram.
    /**
     *  This property only is taken into account, if \b mvIMPACT::acquire::RTCtrProgramStep::opCode is set to \b mvIMPACT::acquire::rtctrlProgWaitClocks.
     */
    PropertyI clocks_us;
    /// \brief An enumerated integer property to define for which digital input state this program step waits for.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDigIOState.
     *
     *  This property only is taken into account, if \b mvIMPACT::acquire::RTCtrProgramStep::opCode is set to \b mvIMPACT::acquire::rtctrlProgWaitDigin.
     */
    PropertyIDigIOState digitalInputs;
    /// \brief An enumerated integer property to define how to set the digital outputs of this device.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDigIOState.
     *
     *  This property only is taken into account, if \b mvIMPACT::acquire::RTCtrProgramStep::opCode is set to \b mvIMPACT::acquire::rtctrlProgSetDigout.
     */
    PropertyIDigIOState digitalOutputs;
    /// \brief An enumerated integer property to define which sensor heads to trigger (for devices with more than one sensor head).
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDigIOState.
     *
     *  This property only is taken into account, if \b mvIMPACT::acquire::RTCtrProgramStep::opCode is set to \b mvIMPACT::acquire::rtctrlProgTriggerSet
     *  or \b mvIMPACT::acquire::rtctrlProgTriggerReset.
     */
    PropertyIDigIOState sensorHeads;
    /// \brief An enumerated integer property defining the general purpose of this \b mvIMPACT::acquire::RTCtrProgramStep object.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TRTProgOpCodes.
     */
    PropertyIRTProgOpCodes opCode;
    /// \brief An integer property, which defines the index of the controller register to refer in this \b mvIMPACT::acquire::RTCtrProgramStep.
    /**
     *  This property only is taken into account, if \b mvIMPACT::acquire::RTCtrProgramStep::opCode is set to
     *  \b mvIMPACT::acquire::rtctrlProgRegisterSet, \b mvIMPACT::acquire::rtctrlProgRegisterAdd,
     *  \b mvIMPACT::acquire::rtctrlProgRegisterSub, \b mvIMPACT::acquire::rtctrlProgJumpLocOnZero
     *  or \b mvIMPACT::acquire::rtctrlProgJumpLocOnNotZero.
     *
     *  \note
     *  This feature will not be available for every device offering a HRTC. It will be available if the translation
     *  dictionary of the property \b mvIMPACT::acquire::RTCtrProgramStep::opCode contains
     *  \b mvIMPACT::acquire::rtctrlProgRegisterSet, \b mvIMPACT::acquire::rtctrlProgRegisterAdd,
     *  \b mvIMPACT::acquire::rtctrlProgRegisterSub, \b mvIMPACT::acquire::rtctrlProgJumpLocOnZero
     *  or \b mvIMPACT::acquire::rtctrlProgJumpLocOnNotZero.
     *
     *  Read the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyIPulseStartTrigger::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyIPulseStartTrigger::getTranslationDictValue.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyIPulseStartTrigger::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     */
    PropertyI controllerRegister;
    /// \brief An integer property, which defines the a value to associate with a register access in this \b mvIMPACT::acquire::RTCtrProgramStep.
    /**
     *  This property only is taken into account, if \b mvIMPACT::acquire::RTCtrProgramStep::opCode is set to
     *  \b mvIMPACT::acquire::rtctrlProgRegisterSet, \b mvIMPACT::acquire::rtctrlProgRegisterAdd
     *  or \b mvIMPACT::acquire::rtctrlProgRegisterSub.
     *
     *  \note
     *  This feature will not be available for every device offering a HRTC. It will be available if the translation
     *  dictionary of the property \b mvIMPACT::acquire::RTCtrProgramStep::opCode contains
     *  \b mvIMPACT::acquire::rtctrlProgRegisterSet, \b mvIMPACT::acquire::rtctrlProgRegisterAdd,
     *  or \b mvIMPACT::acquire::rtctrlProgRegisterSub.
     *
     *  Read the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyIPulseStartTrigger::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyIPulseStartTrigger::getTranslationDictValue.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyIPulseStartTrigger::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     */
    PropertyI registerValue;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A class to represent real time control programs(\b Device specific interface layout only).
/**
 *  Real time control programs can be used to control the way how an when images
 *  are exposed and transmitted to the user.
 *
 *  An \b mvIMPACT::acquire::RTCtrProgram e.g. can be used to achieve a constant frame rate with
 *  a desired frequency. This can be done e.g. by triggering the camera with a constant frequency.
 *
 *  \if DOXYGEN_CPP_DOCUMENTATION
 *  An appropriate signal for triggering the camera can be generated as follows:
 * \code
 *  #include <mvIMPACT_CPP/mvIMPACT_acquire.h>
 *
 *  using namespace mvIMPACT::acquire;
 *
 *  void runAt10Hz( Device* pBF )
 *  {
 *    CameraSettingsBlueFOX bfs( pBF );
 *    IOSubSystemBlueFOX bfIOs( pBF );
 *    // define a HRTC program that results in a define image frequency
 *    // the hardware real time controller shall be used to trigger an image
 *    bfs.triggerSource.write( ctsRTCtrl );
 *    // when the hardware real time controller switches the trigger signal to
 *    // high the exposure of the image shall start
 *    bfs.triggerMode.write( ctmOnRisingEdge );
 *
 *    // error checks
 *    if( bfIOs.RTCtrProgramCount() == 0 )
 *    {
 *      // no HRTC controllers available (this never happens for the mvBlueFOX)
 *      return;
 *    }
 *
 *    RTCtrProgram* pRTCtrlProgram = bfIOs.getRTCtrProgram( 0 );
 *    if( !pRTCtrlProgram )
 *    {
 *      // this only should happen if the system is short of memory
 *      return;
 *    }
 *
 *    // start of the program
 *
 *    // we need 5 steps for the program
 *    pRTCtrlProgram->setProgramSize(5);
 *
 *    // wait a certain amount of time to achieve the desired frequency
 *    int progStep = 0;
 *    RTCtrProgramStep* pRTCtrlStep = 0;
 *    pRTCtrlStep = pRTCtrlProgram->programStep( progStep++ );
 *    pRTCtrlStep->opCode.write( rtctrlProgWaitClocks );
 *    pRTCtrlStep->clocks_us.write( 99900 );
 *
 *    // trigger an image
 *    pRTCtrlStep = pRTCtrlProgram->programStep( progStep++ );
 *    pRTCtrlStep->opCode.write( rtctrlProgTriggerSet );
 *
 *    // high time for the trigger signal (should not be smaller than 100 us)
 *    pRTCtrlStep = pRTCtrlProgram->programStep( progStep++ );
 *    pRTCtrlStep->opCode.write( rtctrlProgWaitClocks );
 *    pRTCtrlStep->clocks_us.write( 100 );
 *
 *    // end trigger signal
 *    pRTCtrlStep = pRTCtrlProgram->programStep( progStep++ );
 *    pRTCtrlStep->opCode.write( rtctrlProgTriggerReset );
 *
 *    // restart the program
 *    pRTCtrlStep = pRTCtrlProgram->programStep( progStep++ );
 *    pRTCtrlStep->opCode.write( rtctrlProgJumpLoc );
 *    pRTCtrlStep->address.write( 0 );
 *
 *    // start the program
 *    pRTCtrlProgram->mode.write( rtctrlModeRun );
 *
 *    // Now this camera will deliver images at exactly 10 Hz ( 1 / ( 99900 us + 100us ) )
 *    // when it is constantly feed with image requests.
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  //=============================================================================
 *  public static void runAt10Hz( Device pBF )
 *  //=============================================================================
 *  {
 *    CameraSettingsBlueFOX bfs = new CameraSettingsBlueFOX( pBF );
 *    IOSubSystemBlueFOX bfIOs = new IOSubSystemBlueFOX( pBF );
 *    // define a HRTC program that results in a define image frequency
 *    // the hardware real time controller shall be used to trigger an image
 *    bfs.getTriggerSource().write( TCameraTriggerSource.ctsRTCtrl );
 *    // when the hardware real time controller switches the trigger signal to
 *    // high the exposure of the image shall start
 *    bfs.getTriggerMode().write( TCameraTriggerMode.ctmOnRisingEdge );
 *
 *    // error checks
 *    if( bfIOs.RTCtrProgramCount() == 0 )
 *    {
 *      // no HRTC controllers available (this never happens for the mvBlueFOX)
 *      return;
 *    }
 *
 *    RTCtrProgram pRTCtrlProgram = bfIOs.getRTCtrProgram( 0 );
 *    if( pRTCtrlProgram == null )
 *    {
 *      // this only should happen if the system is short of memory
 *      return;
 *    }
 *
 *    // start of the program
 *
 *    // we need 5 steps for the program
 *    pRTCtrlProgram.setProgramSize(5);
 *
 *    // wait a certain amount of time to achieve the desired frequency
 *    int progStep = 0;
 *    RTCtrProgramStep pRTCtrlStep = null;
 *    pRTCtrlStep = pRTCtrlProgram.programStep( progStep++ );
 *    pRTCtrlStep.getOpCode().write( TRTProgOpCodes.rtctrlProgWaitClocks );
 *    pRTCtrlStep.getClocks_us().write( 99900 );
 *
 *    // trigger an image
 *    pRTCtrlStep = pRTCtrlProgram.programStep( progStep++ );
 *    pRTCtrlStep.getOpCode().write( TRTProgOpCodes.rtctrlProgTriggerSet );
 *
 *    // high time for the trigger signal (should not be smaller than 100 us)
 *    pRTCtrlStep = pRTCtrlProgram.programStep( progStep++ );
 *    pRTCtrlStep.getOpCode().write( TRTProgOpCodes.rtctrlProgWaitClocks );
 *    pRTCtrlStep.getClocks_us().write( 100 );
 *
 *    // end trigger signal
 *    pRTCtrlStep = pRTCtrlProgram.programStep( progStep++ );
 *    pRTCtrlStep.getOpCode().write( TRTProgOpCodes.rtctrlProgTriggerReset );
 *
 *    // restart the program
 *    pRTCtrlStep = pRTCtrlProgram.programStep( progStep++ );
 *    pRTCtrlStep.getOpCode().write( TRTProgOpCodes.rtctrlProgJumpLoc );
 *    pRTCtrlStep.getAddress().write( 0 );
 *
 *    // start the program
 *    pRTCtrlProgram.getMode().write( TRTCtrlModes.rtctrlModeRun );
 *
 *    // Now this camera will deliver images at exactly 10 Hz ( 1 / ( 99900 us + 100us ) )
 *    // when it is constantly feed with image requests.
 *  }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  def runAt10Hz(pBF):
 *     bfs = acquire.CameraSettingsBlueFOX(pBF)
 *     bfIOs = acquire.IOSubSystemBlueFOX(pBF)
 *     # define a HRTC program that results in a define image frequency
 *     # the hardware real time controller shall be used to trigger an image
 *     bfs.triggerSource.write(acquire.ctsRTCtrl)
 *     # when the hardware real time controller switches the trigger signal to
 *     # high the exposure of the image shall start
 *     bfs.triggerMode.write(acquire.ctmOnRisingEdge)
 *
 *     # error checks
 *     if bfIOs.RTCtrProgramCount == 0:
 *         # no HRTC controllers available (this never happens for the mvBlueFOX)
 *         return
 *
 *    pRTCtrlProgram = bfIOs.getRTCtrProgram(0)
 *    if pRTCtrlProgram == None:
 *       # this only should happen if the system is short of memory
 *       return
 *
 *    # start of the program
 *    # we need 5 steps for the program
 *    pRTCtrlProgram.setProgramSize(5)
 *    # wait a certain amount of time to achieve the desired frequency
 *    progStep = 0
 *    pRTCtrlStep = None
 *    pRTCtrlStep = pRTCtrlProgram.programStep(progStep)
 *    pRTCtrlStep.opCode.write(acquire.rtctrlProgWaitClocks)
 *    pRTCtrlStep.clocks_us.write(99900)
 *
 *    # trigger an image
 *    progStep = progStep + 1
 *    pRTCtrlStep = pRTCtrlProgram.programStep(progStep)
 *    pRTCtrlStep.opCode.write(acquire.rtctrlProgTriggerSet)
 *
 *    # high time for the trigger signal (should not be smaller than 100 us)
 *    progStep = progStep + 1
 *    pRTCtrlStep = pRTCtrlProgram.programStep(progStep)
 *    pRTCtrlStep.opCode.write(acquire.rtctrlProgWaitClocks)
 *    pRTCtrlStep.clocks_us.write(100)
 *
 *    # end trigger signal
 *    progStep = progStep + 1
 *    pRTCtrlStep = pRTCtrlProgram.programStep(progStep)
 *    pRTCtrlStep.opCode.write(acquire.rtctrlProgTriggerReset)
 *
 *    # restart the program
 *    progStep = progStep + 1
 *    pRTCtrlStep = pRTCtrlProgram.programStep(progStep)
 *    pRTCtrlStep.opCode.write(acquire.rtctrlProgJumpLoc)
 *    pRTCtrlStep.address.write(0)
 *
 *    # start the program
 *    pRTCtrlProgram.mode.write(acquire.rtctrlModeRun)
 *
 *    # Now this camera will deliver images at exactly 10 Hz (1 / (99900 us + 100us))
 *    # when it is constantly feed with image requests.
 * \endcode
 * \endif
 *
 *  Once this program has been defined it can be executed by setting the \a mode
 *  property to \b mvIMPACT::acquire::rtctrlModeRun. As in this example we do not
 *  wait for an external signal the property \b triggerMode
 *  must be set to a value demanding an external signal
 *  (e.g. \b mvIMPACT::acquire::ctmOnHighLevel ; You will find a summary of the valid
 *  trigger modes in the sensor specific data in the "Sensor data" chapter of the
 *  specific product manual. \b triggerMode must be set to \b mvIMPACT::acquire::ctsRTCtrl
 *  to inform the driver that the signal generate by the real time program shall
 *  be used as the trigger signal.
 *
 *  \note
 *  \b mvIMPACT::acquire::RTCtrProgram objects can't be created directly! To access an \b mvIMPACT::acquire::RTCtrProgram
 *  associated with a certain device create an instance of an object derived from
 *  \b mvIMPACT::acquire::IOSubSystem and then use the function
 *  \b mvIMPACT::acquire::IOSubSystem::RTCtrProgramCount() to find out if there are
 *  hardware real time controller machines available for this device and if so how
 *  many of them can be accessed. Pointers to the machines then can be obtained by calling the
 *  function \b mvIMPACT::acquire::IOSubSystem::getRTCtrProgram() with the number of the
 *  controller (zero based) to be modified.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class RTCtrProgram : public ComponentCollection
//-----------------------------------------------------------------------------
{
    friend class IOSubSystem;
    typedef std::vector<RTCtrProgramStep*> RTCtrlProgramStepVector;
#       ifndef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        HDRV                            m_hDrv;
        mutable RTCtrlProgramStepVector m_programSteps;
        PropertyI                       m_programSize;
        HLIST                           m_hRTCtrList;
        HOBJ                            m_programStepList;
        unsigned int                    m_refCnt;
        explicit ReferenceCountedData( HDRV hDrv, HLIST hList ) : m_hDrv( hDrv ), m_programSteps(), m_programSize(),
            m_hRTCtrList( hList ), m_programStepList(), m_refCnt( 1 ) {}
        ~ReferenceCountedData()
        {
            RTCtrlProgramStepVector::size_type vSize = m_programSteps.size();
            for( RTCtrlProgramStepVector::size_type i = 0; i < vSize; i++ )
            {
                delete m_programSteps[i];
            }
        }
    }* m_pRefData;
#       endif // #ifdef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    void bindPublicProperties( HLIST hList )
    //-----------------------------------------------------------------------------
    {
        ComponentLocator locator( hList );
        locator.bindComponent( mode, "Mode" );
        locator.bindComponent( filename, "Filename" );
        locator.bindComponent( programState, "ProgramState" );
    }
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    //-----------------------------------------------------------------------------
    void updateProgram( void ) const
    //-----------------------------------------------------------------------------
    {
        RTCtrlProgramStepVector::size_type vSize = m_pRefData->m_programSteps.size();
        unsigned int lSize = ComponentList( m_pRefData->m_programStepList ).size();
        if( lSize < vSize )
        {
            // steps have been deleted somewhere...
            for( unsigned int i = lSize; i < vSize; i++ )
            {
                delete m_pRefData->m_programSteps[i];
            }
            m_pRefData->m_programSteps.resize( lSize );
        }
        else if( lSize > vSize )
        {
            // new steps have been created
            Component iter( m_pRefData->m_programStepList );
            iter = iter.firstChild();
            // move to the next valid end point
            for( unsigned int i = 0; i < vSize; i++ )
            {
                ++iter;
            }

            while( iter.isValid() )
            {
                m_pRefData->m_programSteps.push_back( new RTCtrProgramStep( iter ) );
                ++iter;
            }
        }
    }
    //-----------------------------------------------------------------------------
    explicit RTCtrProgram( HDRV hDrv, HLIST hList ) : ComponentCollection( hList ),
        m_pRefData( new ReferenceCountedData( hDrv, hList ) ), mode(), filename(), programState()
        //-----------------------------------------------------------------------------
    {
        ComponentLocator locator( hList );
        locator.bindComponent( m_pRefData->m_programSize, "ProgramSize" );
        bindPublicProperties( m_pRefData->m_hRTCtrList );
        m_pRefData->m_programStepList = locator.findComponent( "RTCtrProgram" );
        updateProgram();
    }
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::RTCtrProgram from an existing one.
    RTCtrProgram(
        /// [in] A constant reference to the \b mvIMPACT::acquire::RTCtrProgram object, this object shall be created from
        const RTCtrProgram& src ) : ComponentCollection( src.m_hRoot ), m_pRefData( src.m_pRefData ), mode( src.mode ),
        filename( src.filename ), programState( src.programState )
    {
        ++( m_pRefData->m_refCnt );
    }
    /// \brief Class destructor.
    ~RTCtrProgram()
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::RTCtrProgram objects.
    RTCtrProgram& operator=( const RTCtrProgram& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            // inc. the NEW reference count
            ++m_pRefData->m_refCnt;
            bindPublicProperties( m_pRefData->m_hRTCtrList );
        }
        return *this;
    }
    /// \brief A function to define the number of instructions this program should consist of.
    void setProgramSize(
        /// [in] The new number of program instructions
        int newSize )
    {
        m_pRefData->m_programSize.write( newSize );
        updateProgram();
    }
    /// \brief Returns the number of program instructions for this program.
    /**
     *  \return The number of program instructions for this program.
     */
    int getProgramSize( void ) const
    {
        return m_pRefData->m_programSize.read();
    }
    /// \brief Returns a pointer to a program instruction of the program.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \return A pointer to a program instruction of the program.
     */
    RTCtrProgramStep* programStep(
        /// [in] The index of the program instruction to obtain.
        unsigned int nr ) const
    {
        updateProgram();
        return m_pRefData->m_programSteps.at( nr );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the current state this program is into.
    /**
     *  In order to affect the behaviour of the image acquisition an \b mvIMPACT::acquire::RTCtrProgram must be in
     *  running mode. Apart from that the property \b triggerSource must be set
     *  appropriately.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TRTCtrlModes.
     */
    PropertyIRTCtrlModes mode;
    /// \brief A string property storing the filename for this program.
    /**
     *  \b mvIMPACT::acquire::RTCtrProgram s can be stored and loaded from/to XML files.
     *  To do this, this property must be set to the desired filename.
     *  \sa
     *  \b mvIMPACT::acquire::RTCtrProgram::load, \n \b mvIMPACT::acquire::RTCtrProgram::save
     */
    PropertyS filename;
    /// \brief A string property \b (read-only) containing information about the current state of the program.
    PropertyS programState;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
    /// \brief Loads an existing program specified by the property \b mvIMPACT::acquire::RTCtrProgram::fileName.
    /**
     *  The default file extension for these programs is '*.rtp'. If the user doesn't
     *  specify this file extension, it is appended automatically. Only
     *  files of this type can be loaded by this function.
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int load( void )
    {
        return DMR_LoadRTCtrProgram( m_pRefData->m_hDrv, m_pRefData->m_hRTCtrList );
    }
    /// \brief Stores the current state of the program under the name specified by the property \b mvIMPACT::acquire::RTCtrProgram::filename.
    /**
     *  The default file extension for files stored using this function is '*.rtp'. If
     *  the user doesn't specify this file extension, it is appended automatically. Only
     *  files of this type can be loaded by the function \b mvIMPACT::acquire::RTCtrProgram::load.
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int save( void )
    {
        return DMR_SaveRTCtrProgram( m_pRefData->m_hDrv, m_pRefData->m_hRTCtrList );
    }
};

//-----------------------------------------------------------------------------
/// \brief A class to configure the creation of digital signals passed to one or more of the digital outputs of a device(\b Device specific interface layout only).
/**
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class PulseStartConfiguration : public ComponentCollection
//-----------------------------------------------------------------------------
{
    friend class IOSubSystem;
    explicit PulseStartConfiguration( HLIST hList, int nr ) : ComponentCollection( hList ), m_nr( nr ),
        pulseStartTrigger(), digitalSignal(), divider(), frequency_Hz(), triggerMoment()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( pulseStartTrigger, "PulseStartTrigger" );
        locator.bindComponent( digitalSignal, "DigitalSignal" );
        locator.bindComponent( divider, "Divider" );
        locator.bindComponent( frequency_Hz, "Frequency_Hz" );
        locator.bindComponent( triggerMoment, "TriggerMoment" );
    }
    int m_nr;
public:
    /// \brief Returns the internal number associated with this pulse start configuration.
    int number( void ) const
    {
        return m_nr;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property that will define how/when a digital signal is generated by the device.
    /**
     *  When certain digital output signals
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TPulseStartTrigger.
     *
     *  \note
     *  Not every device will offer the same options.
     *  Check for valid modes by reading the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyIPulseStartTrigger::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyIPulseStartTrigger::getTranslationDictValue.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyIPulseStartTrigger::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     */
    PropertyIPulseStartTrigger pulseStartTrigger;
    /// \brief An enumerated property to define one or more signals that will trigger the creation of the associated output signals.
    /**
     *  This property will be visible and thus active when \b mvIMPACT::acquire::PulseStartConfiguration::digitalSignal is switched
     *  to \b mvIMPACT::acquire::pstDigitalSignal.
     *
     *  Depending on the device one or more signals can be defined as 'active for output signal creation'. When more than one signal can be
     *  defined, calling \b mvIMPACT::acquire::PropertyIDigitalSignal::allowsValueCombinations will return true.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDigitalSignal.
     *
     *  \b mvHYPERION \b specific:
     *  Currently when more than one signal can be defined here, these signals will have an 'or relationship', which means that when any of these
     *  signals is detected, it will trigger the creation of the associated output signals.
     *
     *  The following signals are defined:
     *  <table width="100%">
     *  <tr>
     *    <th>enum Value</th>
     *    <th>Associated signal</th>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal1</td>
     *    <td>Line Valid(J1)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal2</td>
     *    <td>Line Valid(J2)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal3</td>
     *    <td>Frame Valid(J1)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal4</td>
     *    <td>Frame Valid(J2)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal5</td>
     *    <td>Trigger-In(J3.4/J3.5)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal6</td>
     *    <td>Sync-In(J3.6/J3.7)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal7</td>
     *    <td>Trigger-In(J4.4/J4.5)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal8</td>
     *    <td>Sync-In(J4.6/J4.7)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal9</td>
     *    <td>DigIn0(J6.9)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal10</td>
     *    <td>DigIn1(J6.10)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal11</td>
     *    <td>DigIn2(J6.11)</td>
     *  </tr>
     *  <tr>
     *    <td>mvIMPACT::acquire::dsSignal12</td>
     *    <td>DigIn3(J6.12)</td>
     *  </tr>
     *  </table>
     */
    PropertyIDigitalSignal digitalSignal;
    /// \brief An integer property defining a factor by which the external input signal shall divided.
    /**
     *  Every \a divider-value pulse will be used then. All others will be skipped.
     */
    PropertyI divider;
    /// \brief A float property defining the frequency in Hz. for the creation of the output signals associated with configuration.
    /**
     *  This property will be visible and thus active when \b mvIMPACT::acquire::PulseStartConfiguration::digitalSignal is switched
     *  to \b mvIMPACT::acquire::pstPeriodically.
     */
    PropertyF frequency_Hz;
    /// \brief An enumerated integer property defining the exact moment when this pulse start configuration shall be triggered.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TTriggerMoment.
     */
    PropertyITriggerMoment triggerMoment;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A base class to handle digital inputs and outputs(\b Device specific interface layout only).
/**
 *  This class can't be instantiated by the user, but acts as a base class for
 *  hardware specific classes. Please use a device specific class suitable for the device
 *  you are working with instead. The documentation of the device specific class will also
 *  contain some example code.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class IOSubSystem
//-----------------------------------------------------------------------------
{
protected:
#   if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
    typedef std::vector<RTCtrProgram*> RTCtrProgramVector;
    typedef std::vector<DigitalInput*> DigitalInputVector;
    typedef std::vector<DigitalOutput*> DigitalOutputVector;
    typedef std::vector<SyncOutput*> SyncOutputVector;
    typedef std::vector<PulseStartConfiguration*> PulseStartConfigurationVector;
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        HDRV                          m_hDrv;
        DigitalInputVector            m_vInputs;
        DigitalOutputVector           m_vOutputs;
        SyncOutputVector              m_vHDOutputs;
        SyncOutputVector              m_vVDOutputs;
        mutable RTCtrProgramVector    m_RTCtrPrograms;
        PulseStartConfigurationVector m_PulseStartConfigurations;
        unsigned int                  m_refCnt;
        explicit ReferenceCountedData( HDRV hDrv ) : m_hDrv( hDrv ), m_vInputs(), m_vOutputs(),
            m_vHDOutputs(), m_vVDOutputs(), m_RTCtrPrograms(), m_PulseStartConfigurations(), m_refCnt( 1 ) {}
        ~ReferenceCountedData()
        {
            DigitalInputVector::size_type vInputsSize = m_vInputs.size();
            for( DigitalInputVector::size_type i = 0; i < vInputsSize; i++ )
            {
                delete m_vInputs[i];
            }

            DigitalOutputVector::size_type vOutputsSize = m_vOutputs.size();
            for( DigitalOutputVector::size_type j = 0; j < vOutputsSize; j++ )
            {
                delete m_vOutputs[j];
            }

            SyncOutputVector::size_type vSyncOutputsSize = m_vHDOutputs.size();
            for( SyncOutputVector::size_type k = 0; k < vSyncOutputsSize; k++ )
            {
                delete m_vHDOutputs[k];
            }

            vSyncOutputsSize = m_vVDOutputs.size();
            for( SyncOutputVector::size_type l = 0; l < vSyncOutputsSize; l++ )
            {
                delete m_vVDOutputs[l];
            }

            RTCtrProgramVector::size_type vRTCProgSize = m_RTCtrPrograms.size();
            for( RTCtrProgramVector::size_type m = 0; m < vRTCProgSize; m++ )
            {
                delete m_RTCtrPrograms[m];
            }

            PulseStartConfigurationVector::size_type vPulseStartConfigurationsSize = m_PulseStartConfigurations.size();
            for( PulseStartConfigurationVector::size_type n = 0; n < vPulseStartConfigurationsSize; n++ )
            {
                delete m_PulseStartConfigurations[n];
            }
        }
    }* m_pRefData;
    //-----------------------------------------------------------------------------
    explicit IOSubSystem( Device* pDev ) : m_pRefData( 0 )
        //-----------------------------------------------------------------------------
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        if( !pDev->isOpen() )
        {
            pDev->open();
        }
        m_pRefData = new ReferenceCountedData( pDev->hDrv() );
    }
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    void registerAllRTCtrPrograms( HDRV hDrv, HLIST hList )
    {
        if( hList != INVALID_ID )
        {
            unsigned int cnt = ComponentList( hList ).size();
            for( unsigned int k = 0; k < cnt; k++ )
            {
                if( DMR_FindList( hDrv, 0, dmltRTCtr, k, &hList ) == DMR_NO_ERROR )
                {
                    registerRTCtrProgram( hDrv, hList );
                }
            }
        }
    }
    void registerDigitalInput( HDRV hDrv, PropertyI reg, int nr, const std::string& desc )
    {
        m_pRefData->m_vInputs.push_back( new DigitalInput( hDrv, reg, nr, desc ) );
    }
    void registerDigitalOutput( PropertyI reg, int nr, const std::string& desc )
    {
        m_pRefData->m_vOutputs.push_back( new DigitalOutput( reg, nr, desc ) );
    }
    void registerHDOutput( HLIST hList )
    {
        m_pRefData->m_vHDOutputs.push_back( new SyncOutput( hList ) );
    }
    void registerRTCtrProgram( HDRV hDrv, HLIST hList )
    {
        m_pRefData->m_RTCtrPrograms.push_back( new RTCtrProgram( hDrv, hList ) );
    }
    void registerPulseStartConfiguration( HLIST hList )
    {
        m_pRefData->m_PulseStartConfigurations.push_back( new PulseStartConfiguration( hList, static_cast<int>( m_pRefData->m_PulseStartConfigurations.size() ) ) );
    }
    void registerVDOutput( HLIST hList )
    {
        m_pRefData->m_vVDOutputs.push_back( new SyncOutput( hList ) );
    }
#   endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::IOSubSystem from an existing one.
    IOSubSystem(
        /// [in] A constant reference to the \b mvIMPACT::acquire::IOSubSystem object, this object shall be created from
        const IOSubSystem& src ) : m_pRefData( src.m_pRefData )
    {
        ++( m_pRefData->m_refCnt );
    }
    virtual ~IOSubSystem()
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::IOSubSystem objects.
    IOSubSystem& operator=( const IOSubSystem& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            // inc. the NEW reference count
            ++m_pRefData->m_refCnt;
        }
        return *this;
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::PulseStartConfiguration associated with this device.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     */
    PulseStartConfiguration* getPulseStartConfiguration(
        /// [in] The number of the pulse start configuration to return
        unsigned int nr ) const
    {
        return m_pRefData->m_PulseStartConfigurations.at( nr );
    }
    /// \brief Returns the number of \b mvIMPACT::acquire::PulseStartConfiguration objects available for the \b mvIMPACT::acquire::Device associated with this object.
    unsigned int getPulseStartConfigurationCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_PulseStartConfigurations.size() );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::RTCtrProgram associated with this device.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     */
    RTCtrProgram* getRTCtrProgram(
        /// [in] The number of the real time controller program to return
        unsigned int nr ) const
    {
        return m_pRefData->m_RTCtrPrograms.at( nr );
    }
    /// \brief Returns the number of \b mvIMPACT::acquire::RTCtrProgram s available for the \b mvIMPACT::acquire::Device associated with this object.
    unsigned int RTCtrProgramCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_RTCtrPrograms.size() );
    }
    /// \brief Returns the number of \b mvIMPACT::acquire::DigitalInput s available for the \b mvIMPACT::acquire::Device associated with this object.
    unsigned int getInputCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_vInputs.size() );
    }
    /// \brief Returns the current state of the digital input register.
    /**
     *  This function can be used to read all digital inputs as a single value. Each
     *  bit represents the status of one digital output pin.
     *
     *  \b EXAMPLE
     *
     *  A value of '3' returned by this function means that digital inputs 0 and 1 are
     *  currently have a voltage considered as logical '1' applied to them.
     */
    virtual unsigned int readInputRegister( void ) const = 0;
    /// \brief Returns a const pointer to a \b mvIMPACT::acquire::DigitalInput object.
    /**
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr references an invalid pin an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \note
     *  The possibility to access the digital inputs of a device as single objects is
     *  just provided for convenience. The same thing can be achieved by calling the
     *  function \b mvIMPACT::acquire::IOSubSystem::readInputRegister.
     */
    const DigitalInput* input(
        /// [in] The number of the digital input.
        unsigned int nr ) const
    {
        return m_pRefData->m_vInputs.at( nr );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::DigitalOutput object.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr references an invalid pin an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \note
     *  The possibility to access the digital outputs of a device as single objects is
     *  just provided for convenience. The same thing can be achieved by calling the function
     *  \b mvIMPACT::acquire::IOSubSystem::writeOutputRegister with the corresponding bit mask.
     */
    DigitalOutput* output(
        /// [in] The number of the digital output.
        unsigned int nr ) const
    {
        return m_pRefData->m_vOutputs.at( nr );
    }
    /// \brief Returns the number of digital outputs available for the \b mvIMPACT::acquire::Device associated with this object.
    unsigned int getOutputCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_vOutputs.size() );
    }
    /// \brief Returns the current state of the digital output register.
    /**
     *  This function can be used to read all digital outputs as a single value. Each
     *  bit represents the status of one digital output pin.
     *
     *  \b EXAMPLE
     *
     *  A value of '3' returned by this function means that digital output 0 and 1 are
     *  currently set to high.
     */
    virtual unsigned int readOutputRegister( void ) const = 0;
    /// \brief Alters the state of the digital output register.
    /**
     *  This function can be used to alter the state of certain (or all) digital outputs
     *  with a single function call. By working with the parameter \a mask certain bits
     *  can remain unaffected.
     *
     *  \b EXAMPLE
     *
     *  If the previous state of a digital output register was '5', which means that outputs
     *  0 and 2 are set to high a call to
     *  \b mvIMPACT::acquire::IOSubSystem::writeOutputRegister with
     *  \a value set to 2 and \a mask set to 3 would result in '6' as the new value for the
     *  output register. Pin 2 will remain unaffected, as \a mask states just to modify
     *  pin 0 and 1 ( 3 = 00000011 binary ).
     *
     * \code
     *  currentValue = 5, mask = 3, value = 2
     *  ( currentValue & ~mask ) | value -> new Value
     *  ( 00000101b(current value) & 11111100(~mask) ) | 00000010(value) -> 0000110(new value of the register)
     * \endcode
     */
    virtual void writeOutputRegister(
        /// [in] The value to be applied to the output register
        unsigned int value,
        /// [in] The mask to specify which pins to modify. A bit
        /// set to '1' in this parameter means that the
        /// state of this output has to adopt its style according to
        /// the value in \a value.
        unsigned int mask = UINT_MAX ) = 0;
};

#   ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief A class to handle the digital inputs and outputs for \b mvBlueFOX USB cameras(\b Device specific interface layout only).
/**
 *  \if DOXYGEN_CPP_DOCUMENTATION
 *  A sample to show how to work with this class and the mvBlueFOX (Creating and instance
 *  of this class for another device might raise an exception):
 *
 * \code
 *  #include <iostream>
 *  #include <mvIMPACT_CPP/mvIMPACT_acquire.h>
 *
 *  using namespace std;
 *  using namespace mvIMPACT::acquire;
 *
 *  void doSomeIOStuff( Device* pBF )
 *  {
 *    IOSubSystemBlueFOX bfIOs( pBF );
 *    cout << "output 0 was " << bfIOs.output(0)->get() << " and is now(after flipping) ";
 *    bfIOs.output(0)->flip();
 *    cout << bfIOs.output(0)->get() << endl;
 *    cout << "input threshold(" << bfIOs.digitalInputThreshold.readS() << ") set to " << bfdit10V << endl;
 *    if( bfIOs.digitalInputThreshold.isWriteable() ) // mvBlueFOX-M doesn't support modifying the input threshold
 *    {
 *      bfIOs.digitalInputThreshold.write( bfdit10V );
 *      cout << "input threshold is now " << bfIOs.digitalInputThreshold.readS() << endl;
 *    }
 *    cout << "input 0 is " << bfIOs.input(0)->get() << endl;
 *    cout << "press ENTER." << endl;
 *    cin.get();
 *    cout << "input 0 is " << bfIOs.input(0)->get() << endl;
 *    cout << "press ENTER." << endl;
 *    cin.get();
 *    cout << "input 0 is " << bfIOs.input(0)->get() << endl;
 *    // switch on digital out 0 and 1 ( 3 = 00000011 binary )
 *    bfIOs.writeOutputRegister( 3 );
 *    cout << "outputs: " << bfIOs.readOutputRegister() << ", inputs: " << bfIOs.readInputRegister();
 *    // the next line will reset bit 0 only, resulting in output 1 to remain high
 *    // as the mask parameter of '1' defines that only the LSB of the register will be
 *    // affected by the first parameter of the function call
 *    bfIOs.writeOutputRegister( 0, 1 );
 *    cout << "outputs: " << bfIOs.readOutputRegister() << ", inputs " << bfIOs.readInputRegister() << endl;
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *   public static void doSomeIOStuff( Device pBF )
 *   {
 *     IOSubSystemBlueFOX bfIOs = new mvIMPACT.acquire.IOSubSystemBlueFOX( pBF );
 *     System.out.println( "output 0 was " + bfIOs.output(0).get() + " and is now(after flipping) ");
 *     bfIOs.output(0).flip();
 *     System.out.println( bfIOs.output(0).get() );
 *     System.out.println( "input threshold(" + bfIOs.getDigitalInputThreshold().readS() + ") set to " + TBlueFOXDigitalInputThreshold .bfdit10V );
 *     if( bfIOs.getDigitalInputThreshold().isWriteable() ) // mvBlueFOX-M doesn't support modifying the input threshold
 *     {
 *       bfIOs.getDigitalInputThreshold().write( TBlueFOXDigitalInputThreshold .bfdit10V );
 *       System.out.println( "input threshold is now " + bfIOs.getDigitalInputThreshold().readS() );
 *     }
 *     System.out.println( "input 0 is " + bfIOs.input(0).get());
 *     System.out.println( "press ENTER." );
 *     waitForENTER();
 *     System.out.println( "input 0 is " + bfIOs.input(0).get() );
 *     System.out.println( "press ENTER." );
 *     waitForENTER();
 *     System.out.println( "input 0 is " + bfIOs.input(0).get() );
 *     // switch on digital out 0 and 1 ( 3 = 00000011 binary )
 *     bfIOs.writeOutputRegister( 3 );
 *     System.out.println( "outputs: " + bfIOs.readOutputRegister() + ", inputs: " + bfIOs.readInputRegister());
 *     // the next line will reset bit 0 only, resulting in output 1 to remain high
 *     // as the mask parameter of '1' defines that only the LSB of the register will be
 *     // affected by the first parameter of the function call
 *     bfIOs.writeOutputRegister( 0, 1 );
 *     System.out.println( "outputs: " + bfIOs.readOutputRegister() + ", inputs " + bfIOs.readInputRegister() );
 *   }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  def doSomeIOStuff(pBF):
 *    bfIOs = acquire.IOSubSystemBlueFOX(pBF)
 *    print("output 0 was " + str(bfIOs.getOutput(0).get()) + " and is now(after flipping) ")
 *    bfIOs.getOutput(0).flip()
 *    print(bfIOs.getOutput(0).get())
 *    print("input threshold(" + bfIOs.digitalInputThreshold.readS() + ") set to " + str(acquire.bfdit10V))
 *    if(bfIOs.digitalInputThreshold.isWriteable): # mvBlueFOX-M doesn't support modifying the input threshold
 *      bfIOs.digitalInputThreshold.write(acquire.bfdit10V)
 *      print("input threshold is now " + bfIOs.digitalInputThreshold.readS())
 *
 *    print("input 0 is " + str(bfIOs.getInput(0).get()))
 *    time.sleep(5) # wait for 5 seconds
 *    print("input 0 is " + str(bfIOs.getInput(0).get()))
 *    time.sleep(5) # wait for 5 seconds
 *    print("input 0 is " + str(bfIOs.getInput(0).get()))
 *    # switch on digital out 0 and 1 (3 = 00000011 binary)
 *    bfIOs.writeOutputRegister(3)
 *    print("outputs: " + str(bfIOs.readOutputRegister()) + ", inputs: " + str(bfIOs.readInputRegister()))
 *    # the next line will reset bit 0 only, resulting in output 1 to remain high
 *    # as the mask parameter of '1' defines that only the LSB of the register will be
 *    # affected by the first parameter of the function call
 *    bfIOs.writeOutputRegister(0, 1)
 *    print("outputs: " + str(bfIOs.readOutputRegister()) + ", inputs " + str(bfIOs.readInputRegister()))
 * \endcode
 * \endif
 *
 *  \note
 *  The \b mvBlueFOX defines an additional property \b mvIMPACT::acquire::CameraSettingsBlueFOX::flashMode.
 *  This might affect the state of the digital outputs as well.
 *
 *  If a digital output is defined to be 'logic 0' but the flash mode is switched on
 *  for the same digital output, the output will be high during the expose time of
 *  the camera sensor. If a digital output is defined to be 'logic 1' the output will
 *  be high all the time.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class IOSubSystemBlueFOX : public IOSubSystem
//-----------------------------------------------------------------------------
{
private:
    unsigned int readRegister( const PropertyI& reg ) const
    {
        std::vector<int> v;
        reg.read( v );
        std::vector<int>::size_type vSize = v.size();
        unsigned int result = 0;
        for( std::vector<int>::size_type i = 0; i < vSize; i++ )
        {
            result |= ( ( v[i] & 1 ) << i );
        }
        return result;
    }
    unsigned int readRegisterAtomic( const PropertyI& reg ) const
    {
        std::vector<int> v;
        reg.read( v, true );
        std::vector<int>::size_type vSize = v.size();
        unsigned int result = 0;
        for( std::vector<int>::size_type i = 0; i < vSize; i++ )
        {
            result |= ( ( v[i] & 1 ) << i );
        }
        return result;
    }
    PropertyI m_inputRegister;
    PropertyI m_outputRegister;
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::IOSubSystemBlueFOX object.
    explicit IOSubSystemBlueFOX(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : IOSubSystem( pDev ), m_inputRegister(), m_outputRegister(), digitalInputThreshold()
    {
        DeviceComponentLocator locator( pDev, dltIOSubSystem );
        locator.bindComponent( digitalInputThreshold, "DigitalInputThreshold" );
        locator.bindComponent( m_inputRegister, "DigitalInputs" );
        locator.bindComponent( m_outputRegister, "DigitalOutputs" );

        // register all input pins
        unsigned int pinCount = m_inputRegister.valCount();
        for( unsigned int i = 0; i < pinCount; i++ )
        {
            std::ostringstream oss;
            oss << "DigitialInput" << i;
            registerDigitalInput( pDev->hDrv(), m_inputRegister, i, oss.str() );
        }

        // register all output pins
        pinCount = m_outputRegister.valCount();
        for( unsigned int j = 0; j < pinCount; j++ )
        {
            std::ostringstream oss;
            oss << "DigitalOutput" << j;
            registerDigitalOutput( m_outputRegister, j, oss.str() );
        }

        registerAllRTCtrPrograms( pDev->hDrv(), locator.findComponent( "HardwareRealTimeController" ) );
    }
    /// \brief Returns the current state of the digital input register.
    /**
     *  This function can be used to read all digital inputs as a single value. Each
     *  bit represents the status of one digital output pin.
     *
     *  \b EXAMPLE
     *
     *  A value of '3' returned by this function means that digital inputs 0 and 1 are
     *  currently have a voltage considered as logical '1' applied to them.
     */
    virtual unsigned int readInputRegister( void ) const
    {
        const TDMR_ERROR result = DMR_UpdateDigitalInputs( m_pRefData->m_hDrv );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        return readRegister( m_inputRegister );
    }
    /// \brief Returns the current state of the digital input register.
    /**
     *  This function can be used to read all digital inputs as a single value \b at the same time. Each
     *  bit represents the status of one digital output pin.
     *
     *  \b EXAMPLE
     *
     *  A value of '3' returned by this function means that digital inputs 0 and 1 are
     *  currently have a voltage considered as logical '1' applied to them.
     */
    unsigned int readInputRegisterAtomic( void ) const
    {
        const TDMR_ERROR result = DMR_UpdateDigitalInputs( m_pRefData->m_hDrv );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
        return readRegisterAtomic( m_inputRegister );
    }
    /// \brief Returns the current state of the digital output register.
    /**
     *  This function can be used to read all digital outputs as a single value. Each
     *  bit represents the status of one digital output pin.
     *
     *  \b EXAMPLE
     *
     *  A value of '3' returned by this function means that digital output 0 and 1 are
     *  currently set to high.
     */
    virtual unsigned int readOutputRegister( void ) const
    {
        return readRegister( m_outputRegister );
    }
    /// \brief Returns the current state of the digital output register.
    /**
     *  This function can be used to read all digital outputs as a single value \b at the same time. Each
     *  bit represents the status of one digital output pin.
     *
     *  \b EXAMPLE
     *
     *  A value of '3' returned by this function means that digital output 0 and 1 are
     *  currently set to high.
     */
    unsigned int readOutputRegisterAtomic( void ) const
    {
        return readRegisterAtomic( m_outputRegister );
    }
    /// \brief Alters the state of the digital output register.
    /**
     *  This function can be used to alter the state of certain (or all) digital outputs
     *  with a single function call. By working with the parameter \a mask certain bits
     *  can remain unaffected.
     *
     *  \b EXAMPLE
     *
     *  If the previous state of a digital output register was '5', which means that outputs
     *  0 and 2 are set to high a call to
     *  \b mvIMPACT::acquire::IOSubSystem::writeOutputRegister with
     *  \a value set to 2 and \a mask set to 3 would result in '6' as the new value for the
     *  output register. Pin 2 will remain unaffected, as \a mask states just to modify
     *  pin 0 and 1 ( 3 = 00000011 binary ).
     */
    void writeOutputRegister(
        /// [in] The value to be applied to the output register
        unsigned int value,
        /// [in] The mask to specify which pins to modify. A bit
        /// set to '1' in this parameter means that the
        /// state of this output has to adopt its style according to
        /// the value in \a value.
        unsigned int mask = UINT_MAX )
    {
        unsigned int newVal = ( readRegister( m_outputRegister ) & ~mask ) | ( mask & value );
        DigitalOutputVector::size_type vSize = m_pRefData->m_vOutputs.size();
        std::vector<int> v( vSize );
        for( std::vector<int>::size_type i = 0; i < vSize; i++ )
        {
            v[i] = ( ( newVal & ( 1 << i ) ) != 0 );
        }
        m_outputRegister.write( v );
    }
    /// \brief Alters the state of the digital output register.
    /**
     *  This function can be used to alter the state of certain (or all) digital outputs
     *  with a single function call \b at the same time. By working with the parameter \a mask
     *  certain bits can remain unaffected.
     *
     *  \b EXAMPLE
     *
     *  If the previous state of a digital output register was '5', which means that outputs
     *  0 and 2 are set to high a call to
     *  \b mvIMPACT::acquire::IOSubSystem::writeOutputRegister with
     *  \a value set to 2 and \a mask set to 3 would result in '6' as the new value for the
     *  output register. Pin 2 will remain unaffected, as \a mask states just to modify
     *  pin 0 and 1 ( 3 = 00000011 binary ).
     */
    void writeOutputRegisterAtomic(
        /// [in] The value to be applied to the output register
        unsigned int value,
        /// [in] The mask to specify which pins to modify. A bit
        /// set to '1' in this parameter means that the
        /// state of this output has to adopt its style according to
        /// the value in \a value.
        unsigned int mask = UINT_MAX )
    {
        unsigned int newVal = ( readRegister( m_outputRegister ) & ~mask ) | ( mask & value );
        DigitalOutputVector::size_type vSize = m_pRefData->m_vOutputs.size();
        std::vector<int> v( vSize );
        for( std::vector<int>::size_type i = 0; i < vSize; i++ )
        {
            v[i] = ( ( newVal & ( 1 << i ) ) != 0 );
        }
        m_outputRegister.write( v, true );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the threshold for the digital inputs in Volt.
    /**
     *  If a voltage applied to the digital input lies above the threshold this pin
     *  will be considered as 'logic 1' otherwise it will be considered as 'logic 0'.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBlueFOXDigitalInputThreshold.
     *
     *  \note
     *  This property is \b read-only for \b mvBlueFOX-M devices and will always be 2V.
     */
    PropertyIBlueFOXDigitalInputThreshold digitalInputThreshold;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #  ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION

#   if !defined(IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION) || !defined(IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION)
//-----------------------------------------------------------------------------
/// \brief A base class to handle the digital inputs and outputs for devices (\b Device specific interface layout only).
/**
 *  This class provides a convenient basic access to the digital inputs and
 *  outputs of almost every device supported by this interface.
 *
 *  \note
 *  This class may \b NOT be used for mvBlueFOX devices.
 *
 *  \note
 *  The number of digital inputs and outputs available will vary significantly
 *  from device to device. Some devices might not even have digital inputs and/or
 *  digital outputs. Therefore it's crucial to check for available pins before
 *  using them. The corresponding functions to do that can be found in the
 *  base class \b mvIMPACT::acquire::IOSubSystem.
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  #include <mvIMPACT_CPP/mvIMPACT_acquire.h>
 *  #include <iostream>
 *
 *  using namespace std;
 *  using namespace mvIMPACT::acquire;
 *
 *  // lists all available digital inputs and outputs and their description
 *  void listIOPins( Device* pDev )
 *  {
 *    IOSubSystemCommon io( pDev );
 *    unsigned int iCnt = io.getInputCount();
 *    cout << "available digital inputs: " << iCnt << endl;
 *    for( unsigned int d=0; d<iCnt; d++ )
 *    {
 *      out << io.input(d)->getDescription() << endl;
 *    }
 *    unsigned int oCnt = io.getOutputCount();
 *    cout << "available digital outputs: " << oCnt << endl;
 *    for( unsigned int e=0; e<oCnt; e++ )
 *    {
 *      DigitalOutput* pOutput = io.output(e);
 *      out << "setting " << pOutput->getDescription() << " to high" << endl;
 *      // set this output to logic '1'
 *      pOutput->set();
 *    }
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  import mvIMPACT.acquire.*;
 *
 *  //-----------------------------------------------------------------------------
 *  public class CameraDescriptionManagerExample
 *  //-----------------------------------------------------------------------------
 *  {
 *    //=============================================================================
 *    //=== Static member functions =================================================
 *    //=============================================================================
 *    static
 *    {
 *      try
 *      {
 *        System.loadLibrary( "mvIMPACT_Acquire.java" );
 *      }
 *      catch( UnsatisfiedLinkError e )
 *      {
 *        System.err.println( "Native code library failed to load. Make sure the 'mvIMPACT_Acquire.java' library can be found in the systems search path.\n" + e );
 *        System.exit( 1 );
 *      }
 *    }
 *
 *    //-----------------------------------------------------------------------------
 *    public static void main( String[] args )
 *    //-----------------------------------------------------------------------------
 *    {
 *      DeviceManager devMgr = new DeviceManager();
 *      Device pDev = mvIMPACT.acquire.examples.helper.DeviceAccess.getDeviceFromUserInput( devMgr );
 *      if( pDev == null )
 *      {
 *        System.out.print( "Unable to continue!" );
 *        mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *        System.exit( 1 );
 *      }
 *
 *      System.out.println( "Initialising the device. This might take some time..." );
 *      try
 *      {
 *        pDev.open();
 *      }
 *      catch( ImpactAcquireException e )
 *      {
 *        // this e.g. might happen if the same device is already opened in another process...
 *        System.out.println( "An error occurred while opening device " + pDev.getSerial().read() +
 *                            "(error code: " + e.getMessage() + ")." );
 *        mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *        System.exit( 1 );
 *      }
 *
 *      try
 *      {
 *        // the next line will raise an exception if this device is not a frame grabber
 *        IOSubSystemFrameGrabber io = new IOSubSystemFrameGrabber( pDev );
 *        final long iCnt = io.getInputCount();
 *        System.out.println( String.format( "Available digital inputs: %d", iCnt ) );
 *        for( long d=0; d<iCnt; d++ )
 *        {
 *          System.out.println( io.input( d ).getDescription() );
 *        }
 *        final long oCnt = io.getOutputCount();
 *        System.out.println( String.format( "Available digital outputs: %d", oCnt ) );
 *        // set all available digital outputs to high
 *        for( long e=0; e<oCnt; e++ )
 *        {
 *          DigitalOutput pOutput = io.output( e );
 *          System.out.println( "setting " + pOutput.getDescription() + " to high" );
 *          pOutput.set();
 *        }
 *      }
 *      catch( ImpactAcquireException e )
 *      {
 *        System.out.println( "An error occurred: " + e.getMessage() + "." );
 *        mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *        System.exit( 1 );
 *      }
 *    }
 *  }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  def listIOPins(pDev):
 *    io = acquire.IOSubSystemCommon(pDev)
 *    iCnt = io.getInputCount()
 *    print("available digital inputs: " + str(iCnt))
 *    for d in range(iCnt):
 *        print(io.getInput(d).getDescription())
 *
 *    oCnt = io.getOutputCount()
 *    print("available digital outputs: " + str(oCnt))
 *    for e in range(oCnt):
 *        pOutput = io.getOutput(e)
 *        print("setting " + pOutput.getDescription() + " to high")
 *        # set this output to logic '1'
 *        pOutput.state = True
 * \endcode
 * \endif
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class IOSubSystemCommon : public IOSubSystem
//-----------------------------------------------------------------------------
{
    ComponentList m_inputs;
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::IOSubSystemCommon object.
    explicit IOSubSystemCommon(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : IOSubSystem( pDev ), m_inputs()
    {
        DeviceComponentLocator locator( pDev, dltIOSubSystem );
        HOBJ hObj = locator.findComponent( "PulseStartConfigurations" );
        if( hObj != INVALID_ID )
        {
            Component itPulseConfigs( hObj );
            itPulseConfigs = itPulseConfigs.firstChild();
            while( itPulseConfigs.isValid() )
            {
                registerPulseStartConfiguration( itPulseConfigs.hObj() );
                ++itPulseConfigs;
            }
        }

        locator.bindComponent( m_inputs, "DigitalInputs", 0, 1 );
        if( m_inputs.isValid() )
        {
            Component it( m_inputs );
            it = it.firstChild();
            while( it.isValid() )
            {
                registerDigitalInput( pDev->hDrv(), PropertyI( it ), 0, it.name() );
                ++it;
            }
        }

        ComponentList outputs;
        locator.bindComponent( outputs, "DigitalOutputs", 0, 1 );
        if( outputs.isValid() )
        {
            Component it( outputs );
            it = it.firstChild();
            while( it.isValid() )
            {
                if( it.isList() )
                {
                    ComponentLocator outputStateLocator( it );
                    registerDigitalOutput( PropertyI( outputStateLocator.findComponent( "State" ) ), 0, it.name() );
                }
                ++it;
            }
        }

        registerAllRTCtrPrograms( pDev->hDrv(), locator.findComponent( "HardwareRealTimeController" ) );
    }
    /// \brief Returns the current state of the digital input register.
    /**
     *  This function can be used to read all digital inputs as a single value. Each
     *  bit represents the status of one digital output pin.
     *
     *  \b EXAMPLE
     *
     *  A value of '3' returned by this function means that digital inputs 0 and 1 are
     *  currently have a voltage considered as logical '1' applied to them.
     *
     *  \return The current state of the digital inputs where bit 0 in the result represents
     *  the state of digital input 0, bit 1 the state of digital input 1 a.s.o.
     */
    virtual unsigned int readInputRegister( void ) const
    {
        DMR_UpdateDigitalInputs( m_pRefData->m_hDrv );
        if( !m_inputs.isValid() )
        {
            return 0;
        }
        unsigned int result = 0;
        Component it( m_inputs );
        int i = 0;
        it = it.firstChild();
        while( it.isValid() )
        {
            PropertyI input( it );
            result |= ( ( input.read() & 1 ) << i );
            ++it;
            ++i;
        }
        return result;
    }
    /// \brief Returns the current state of the digital output register.
    /**
     *  This function can be used to read all digital outputs as a single value. Each
     *  bit represents the status of one digital output pin.
     *
     *  \b EXAMPLE
     *
     *  A value of '3' returned by this function means that digital output 0 and 1 are
     *  currently set to high.
     *
     *  \return The current state of the digital outputs where bit 0 in the result represents
     *  the state of digital output 0, bit 1 the state of digital output 1 a.s.o.
     */
    virtual unsigned int readOutputRegister( void ) const
    {
        unsigned int result = 0;
        DigitalOutputVector::size_type vSize = m_pRefData->m_vOutputs.size();
        for( DigitalOutputVector::size_type i = 0; i < vSize; i++ )
        {
            result |= ( ( m_pRefData->m_vOutputs[i]->get() & 1 ) << i );
        }
        return result;
    }
    /// \brief Alters the state of the digital output register.
    /**
     *  This function can be used to alter the state of certain (or all) digital outputs
     *  with a single function call. By working with the parameter \a mask certain bits
     *  can remain unaffected.
     *
     *  \b EXAMPLE
     *
     *  If the previous state of a digital output register was '5', which means that outputs
     *  0 and 2 are set to high a call to
     *  \b mvIMPACT::acquire::IOSubSystem::writeOutputRegister with
     *  \a value set to 2 and \a mask set to 3 would result in '6' as the new value for the
     *  output register. Pin 2 will remain unaffected, as \a mask states just to modify
     *  pin 0 and 1 ( 3 = 00000011 binary ).
     */
    void writeOutputRegister(
        /// [in] The value to be applied to the output register
        unsigned int value,
        /// [in] The mask to specify which pins to modify. A bit
        /// set to '1' in this parameter means that the
        /// state of this output has to adopt its style according to
        /// the value in \a value.
        unsigned int mask = UINT_MAX )
    {
        DigitalOutputVector::size_type vSize = m_pRefData->m_vOutputs.size();
        for( DigitalOutputVector::size_type i = 0; i < vSize; i++ )
        {
            if( mask & ( 1 << i ) )
            {
                if( value & ( 1 << i ) )
                {
                    m_pRefData->m_vOutputs[i]->set();
                }
                else
                {
                    m_pRefData->m_vOutputs[i]->reset();
                }
            }
        }
    }
};
#   endif // #i f !defined(IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION) || !defined(IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION)

#   ifndef IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION
/// \brief A class to create complex digital output signals(\b Device specific interface layout only).
/**
 *  Instances of this class can be used to create more complex digital output
 *  related signals like a single pulse or sequence of pulses on a certain pin
 *  as a reaction on a signal on one of the digital inputs of a device.
 *
 *  The availability of the features provided by this class heavily depends on the
 *  used capture device. Therefore it's crucial to check if a desired feature is available
 *  at all. This class either provides the functions needed for these checks or its
 *  functions will return appropriate error codes.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class OutputSignalGeneratorBlueDevice
//-----------------------------------------------------------------------------
{
#       ifndef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    struct OutputProperties
    //-----------------------------------------------------------------------------
    {
        PropertyIDeviceDigitalOutputMode mode;
        PropertyIBoolean inverter;
        explicit OutputProperties( HLIST hOutput ) : mode()
        {
            ComponentLocator locator( hOutput );
            locator.bindComponent( mode, "Mode" );
            locator.bindComponent( inverter, "Inverter" );
        }
    };
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        std::map<std::string, OutputProperties*> m_mOutputs;
        unsigned int                             m_refCnt;
        explicit ReferenceCountedData() : m_mOutputs(), m_refCnt( 1 ) {}
        ~ReferenceCountedData()
        {
            std::map<std::string, OutputProperties*>::iterator itEnd = m_mOutputs.end();
            std::map<std::string, OutputProperties*>::iterator it = m_mOutputs.begin();
            while( it != itEnd )
            {
                delete it->second;
                ++it;
            }
        }
    }* m_pRefData;
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    //-----------------------------------------------------------------------------
    OutputProperties* getOutputProperties( DigitalOutput* pOutput ) const
    //-----------------------------------------------------------------------------
    {
        if( pOutput )
        {
            std::map<std::string, OutputProperties*>::iterator it = m_pRefData->m_mOutputs.find( pOutput->getDescription() );
            if( it != m_pRefData->m_mOutputs.end() )
            {
                return it->second;
            }
        }
        return 0;
    }
#       endif // #ifdef DOXYGEN_SHOULD_SKIP_THIS
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::OutputSignalGeneratorBlueDevice object.
    explicit OutputSignalGeneratorBlueDevice(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : m_pRefData( 0 )
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        m_pRefData = new ReferenceCountedData();
        DeviceComponentLocator locator( pDev, dltIOSubSystem );
        ComponentList outputs;
        locator.bindComponent( outputs, "DigitalOutputs" );
        if( outputs.isValid() )
        {
            Component it( outputs.hObj() );
            it = it.firstChild();
            while( it.isValid() )
            {
                if( it.isList() )
                {
                    m_pRefData->m_mOutputs.insert( std::pair<std::string, OutputProperties*>( it.name(), new OutputProperties( it ) ) );
                }
                ++it;
            }
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::OutputSignalGeneratorBlueDevice from and existing one.
    explicit OutputSignalGeneratorBlueDevice(
        /// [in] A constant reference to the \b mvIMPACT::acquire::OutputSignalGeneratorBlueDevice object, this object shall be created from
        const OutputSignalGeneratorBlueDevice& src ) : m_pRefData( src.m_pRefData )
    {
        ++( m_pRefData->m_refCnt );
    }
    /// \brief Class destructor.
    ~OutputSignalGeneratorBlueDevice()
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::OutputSignalGeneratorBlueDevice objects.
    OutputSignalGeneratorBlueDevice& operator=( const OutputSignalGeneratorBlueDevice& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            // inc. the NEW reference count
            ++m_pRefData->m_refCnt;
        }
        return *this;
    }
    /// \brief Removes the signal definition from the specified output pin.
    /**
     *  Whenever a signal has been defined for a a certain digital output
     *  pin, this pin can no longer controlled using the corresponding functions
     *  in the class \b mvIMPACT::acquire::DigitalOutput. This function removes the
     *  signal definition and hands back manual control of that digital output to the user.
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int undefineSignal(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemCommon
        /// for this device.
        DigitalOutput* pOutput )
    {
        if( !pOutput )
        {
            return DMR_INVALID_PARAMETER;
        }
        OutputProperties* p = getOutputProperties( pOutput );
        if( p )
        {
            p->mode.write( ddomManual );
            return DMR_NO_ERROR;
        }
        return DMR_FEATURE_NOT_AVAILABLE;
    }
    /// \brief Checks whether the specified output can be used to create an inverted expose active signal.
    bool canCreateExposeActiveSignal(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemCommon
        /// for this device.
        DigitalOutput* pOutput ) const
    {
        OutputProperties* p = getOutputProperties( pOutput );
        if( !p || !p->mode.isValid() )
        {
            return false;
        }
        unsigned int dictSize = p->mode.dictSize();
        for( unsigned int i = 0; i < dictSize; i++ )
        {
            if( p->mode.getTranslationDictValue( i ) == ddomExposureActive )
            {
                return true;
            }
        }
        return false;
    }
    /// \brief Checks whether the specified output can be used to create an inverted version of a certain signal.
    bool canInvertSignal(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemCommon
        /// for this device.
        DigitalOutput* pOutput ) const
    {
        OutputProperties* p = getOutputProperties( pOutput );
        return ( p && p->inverter.isValid() );
    }
    /// \brief Returns the current mode a digital output is operated in.
    ///
    /// If the mode is not selectable for the current output an exception will be raised.
    TDeviceDigitalOutputMode getOutputMode(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemCommon
        /// for this device.
        DigitalOutput* pOutput ) const
    {
        OutputProperties* p = getOutputProperties( pOutput );
        if( !p )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, DMR_FEATURE_NOT_AVAILABLE, "Unsupported feature query(Could not obtain pointer to output properties)" );
        }
        return static_cast<TDeviceDigitalOutputMode>( p->mode.read() );
    }
    /// \brief Checks whether the specified output is currently operated in a certain mode.
    bool isOutputModeActive(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemCommon
        /// for this device.
        DigitalOutput* pOutput,
        /// [in] The mode the specified output shall be checked for.
        TDeviceDigitalOutputMode mode ) const
    {
        OutputProperties* p = getOutputProperties( pOutput );
        return ( p && p->mode.isValid() && ( p->mode.read() == mode ) );
    }
    /// \brief Checks whether the specified output will currently invert a certain internal signal.
    bool isSignalInverted(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemCommon
        /// for this device.
        DigitalOutput* pOutput ) const
    {
        OutputProperties* p = getOutputProperties( pOutput );
        return ( p && p->mode.isValid() && p->inverter.isValid() && ( p->inverter.read() == bTrue ) );
    }
    /// \brief This function will configure the digital output to operate in a certain mode.
    /**
     *  After calling this function the digital output will be operated in the mode specified by
     *  \a mode.
     *
     *  Valid values for \a constant are defined by the enum \b mvIMPACT::acquire::TDeviceDigitalOutputMode.
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int setOutputMode(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemCommon
        /// for this device.
        DigitalOutput* pOutput,
        /// [in] The mode the specified output shall be operated in. If the mode passed to the
        /// function is not available for the output or the device an exception will be raised.
        TDeviceDigitalOutputMode mode,
        /// [in] Set this parameter to true, to invert the exposure signal
        bool boInverted = false )
    {
        if( !pOutput )
        {
            return DMR_INVALID_PARAMETER;
        }
        OutputProperties* p = getOutputProperties( pOutput );
        if( p && p->mode.isValid() )
        {
            p->mode.write( mode );
            if( p->inverter.isValid() )
            {
                p->inverter.write( boInverted ? bTrue : bFalse );
            }
            else if( boInverted )
            {
                return DMR_FEATURE_NOT_AVAILABLE;
            }
            return DMR_NO_ERROR;
        }
        return DMR_FEATURE_NOT_AVAILABLE;
    }
};
#   endif // #ifndef IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION

#   ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief A class to handle the digital inputs and outputs for frame grabber devices(\b Device specific interface layout only).
/**
 *  This class provides a convenient basic access to the digital inputs and
 *  outputs of a frame grabber device.
 *
 *  \note
 *  The number of digital inputs and outputs available will vary significantly
 *  from device to device. Some devices might not even have digital inputs and/or
 *  digital outputs. Therefore it's crucial to check for available pins before
 *  using them. The corresponding functions to do that can be found in the
 *  base class \b mvIMPACT::acquire::IOSubSystem.
 *
 *  To create more complex digital output related signals the class
 *  \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber should be used.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class IOSubSystemFrameGrabber : public IOSubSystemCommon
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::IOSubSystemFrameGrabber object.
    explicit IOSubSystemFrameGrabber(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : IOSubSystemCommon( pDev ), syncOutputMode()
    {
        DeviceComponentLocator locator( pDev, dltIOSubSystem );
        Component itSyncs;
        locator.bindComponent( itSyncs, "SyncOutputs", 0, 1 );
        if( itSyncs.isValid() && itSyncs.firstChild().isValid() )
        {
            locator.bindSearchBase( locator.searchbase_id(), "SyncOutputs" );
            locator.bindComponent( syncOutputMode, "Mode" );
            itSyncs = itSyncs.firstChild();
            while( itSyncs.isValid() )
            {
                if( itSyncs.isList() )
                {
                    std::string name = itSyncs.name();
                    if( name.substr( 0, 3 ) == "VD-" )
                    {
                        registerVDOutput( itSyncs );
                    }
                    else if( name.substr( 0, 3 ) == "HD-" )
                    {
                        registerHDOutput( itSyncs );
                    }
                    else
                    {
                        ; // type not recognized?!
                    }
                }
                ++itSyncs;
            }
        }
    }
    /// \brief Returns the number of available HD output pins for the \b mvIMPACT::acquire::Device associated with this object.
    unsigned int getHDOutputCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_vHDOutputs.size() );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::SyncOutput object that represents a HD output for this device.
    /**
     *  \a nr \b MUST be a valid number ( larger or equal than 0 and smaller than the
     *  value returned by \b mvIMPACT::acquire::IOSubSystemFrameGrabber::getHDOutputCount.
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr references an invalid pin an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \return A pointer to a \b mvIMPACT::acquire::SyncOutput object.
     */
    SyncOutput* HDOutput(
        /// [in] The number of the HD output to return.
        unsigned int nr ) const
    {
        return m_pRefData->m_vHDOutputs.at( nr );
    }
    /// \brief Returns the number of available VD output pins for the \b mvIMPACT::acquire::Device associated with this object.
    unsigned int getVDOutputCount( void ) const
    {
        return static_cast<unsigned int>( m_pRefData->m_vVDOutputs.size() );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::SyncOutput object that represents a VD output for this device.
    /**
     *  \a nr \b MUST be a valid number ( larger or equal than 0 and smaller than the
     *  value returned by \b mvIMPACT::acquire::IOSubSystemFrameGrabber::getVDOutputCount.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr references an invalid pin an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \return A pointer to a \b mvIMPACT::acquire::SyncOutput object.
     */
    SyncOutput* VDOutput(
        /// [in] The number of the VD output to return.
        unsigned int nr ) const
    {
        return m_pRefData->m_vVDOutputs.at( nr );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the current mode for sync. signal creation.
    /**
     *  Sometimes it's desired to create a signal to sync. cameras connected to a capture device.
     *  E.g. when capturing 3 monochrome cameras in parallel these should be synchronized. Therefore
     *  some devices can create HD and VD signals that synchronize the connected cameras.
     *
     *  To create sync. signals this property must be set either to \b mvIMPACT::acquire::dsomNonInterlaced
     *  or \b mvIMPACT::acquire::dsomInterlaced.
     *
     *  In interlaced mode only the frequency of the VD signals can be modified, while in non-interlaced
     *  mode the width (in percent) the signal stays low can be modified as well.
     *
     *  Now e.g. to sync. two or more CCIR compliant cameras connected to a capture device that can
     *  create sync. signals, the HD signals must be generated with a CCIR compliant frequency.
     *  The function \b mvIMPACT::acquire::IOSubSystemFrameGrabber::HDOutput can be used to access the
     *  desired output pin. Then its property \b mvIMPACT::acquire::SyncOutput::frequency_Hz is
     *  set to 15625 Hz (CCIR standard). The remaining values can be left untouched. The capture device
     *  will no generate HD signals with the desired frequency and VD outputs with the frequency
     *  stored by the property \b mvIMPACT::acquire::SyncOutput::frequency_Hz belonging to the
     *  pointer to the object returned by a call to \b mvIMPACT::acquire::IOSubSystemFrameGrabber::VDOutput.
     */
    PropertyIDeviceSyncOutMode syncOutputMode;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A class to create complex digital output signals(\b Device specific interface layout only).
/**
 *  Instances of this class can be used to create more complex digital output
 *  related signals like a single pulse or sequence of pulses on a certain pin
 *  as a reaction on a signal on one of the digital inputs of a device.
 *
 *  The availability of the features provided by this class heavily depends on the
 *  used capture device. Therefore it's crucial to check if a desired feature is available
 *  at all. This class either provides the functions needed for these checks or its
 *  functions will return appropriate error codes.
 *
 *  \note
 *  If the property \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::controlMode
 *  is not available \b NO feature of this class can be used.
 *
 *  \note
 *  If the translation dictionary of \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::controlMode
 *  does not contain \b mvIMPACT::acquire::docmRTC the function
 *  \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::defineLineScanPulse will \b NOT
 *  be available.
 *
 *  \note
 *  Calling unsupported functions or accessing unsupported features will raise an exception.
 *
 *  Pointers to \b mvIMPACT::acquire::DigitalOutput objects \b MUST be obtained
 *  by an instance to a \b mvIMPACT::acquire::IOSubSystemFrameGrabber object of the
 *  same device.
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  #include <mvIMPACT_CPP/mvIMPACT_acquire.h>
 *  #include <iostream>
 *  #include <vector>
 *
 *  using namespace std;
 *  using namespace mvIMPACT::acquire;
 *
 *  //-----------------------------------------------------------------------------
 *  int main( int argc, char* argv[] )
 *  //-----------------------------------------------------------------------------
 *  {
 *    DeviceManager devMgr;
 *    Device* pDev = getValidDevicePointerFromSomewhere( devMgr );
 *    // The next line will raise an exception if the device is not operated
 *    // in interface layout 'dilDeviceSpecific' or is not a frame grabber! This
 *    // should therefore be wrapped in an exception handler if in doubt!
 *    IOSubSystemFrameGrabber io( pDev );
 *    unsigned int iCnt = io.getInputCount();
 *    cout << "available digital inputs: " << iCnt << endl;
 *    for( unsigned int d=0; d<iCnt; d++ )
 *    {
 *      cout << io.input( d )->getDescription() << endl;
 *    }
 *    unsigned int oCnt = io.getOutputCount();
 *    cout << "available digital outputs: " << oCnt << endl;
 *    // set all available digital outputs to high
 *    for( unsigned int e=0; e<oCnt; e++ )
 *    {
 *      DigitalOutput* pOutput = io.output( e );
 *      cout << "setting " << pOutput->getDescription() << " to high" << endl;
 *      pOutput->set();
 *    }
 *
 *    // check there is at least one digital output
 *    if( oCnt > 0 )
 *    {
 *      OutputSignalGeneratorFrameGrabber osg( pDev );
 *      // check if this device supports enhanced signal creation at all
 *      if( osg.controlMode.isValid() )
 *      {
 *        // define a simple pulse on the first digital output detected.
 *        // this pulse will be low after 100 us for
 *        // 200us and then switches back to high.
 *        osg.definePulse( io.output( 0 ), 0, 100, 200 );
 *
 *        // define a more complex pulse
 *        vector<int> v;
 *        v.push_back( 100 );
 *        v.push_back( 299 );
 *        v.push_back( 666 );
 *        osg.definePulseSequence( io.output( 0 ), 0, v );
 *        osg.controlMode.write( docmSoftware );
 *        osg.imageTrigger.write( ditAfterDigOutSignals );
 *
 *        // check if line scan pulse creation is supported by this device
 *        vector<pair<string, TDigitalOutputControlMode> > dict;
 *        osg.controlMode.getTranslationDict( dict );
 *        unsigned int dictSize = osg.controlMode.dictSize();
 *        for( unsigned int i=0; i<dictSize; i++ )
 *        {
 *          if( dict[i].second == docmRTC )
 *          {
 *            // supported -> define some signal
 *            cout << "checkGrabberInterface: This device supports RTC control signal creation." << endl;
 *            osg.controlMode.write( docmRTC );
 *            osg.defineLineScanPulse( io.output( 0 ), dsosePeriodically, 100, 100, 1, 1 );
 *          }
 *        }
 *      }
 *    }
 *    return 0;
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  import mvIMPACT.acquire.*;
 *
 *  //-----------------------------------------------------------------------------
 *  public class OutputSignalGeneratorExample
 *  //-----------------------------------------------------------------------------
 *  {
 *    //=============================================================================
 *    //=== Static member functions =================================================
 *    //=============================================================================
 *    static
 *    {
 *      try
 *      {
 *        System.loadLibrary( "mvIMPACT_Acquire.java" );
 *      }
 *      catch( UnsatisfiedLinkError e )
 *      {
 *        System.err.println( "Native code library failed to load. Make sure the 'mvIMPACT_Acquire.java' library can be found in the systems search path.\n" + e );
 *        System.exit( 1 );
 *      }
 *    }
 *
 *    //-----------------------------------------------------------------------------
 *    public static void main( String[] args )
 *    //-----------------------------------------------------------------------------
 *    {
 *      DeviceManager devMgr = new DeviceManager();
 *      Device pDev = mvIMPACT.acquire.examples.helper.DeviceAccess.getDeviceFromUserInput( devMgr );
 *      if( pDev == null )
 *      {
 *        System.out.print( "Unable to continue!" );
 *        mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *        System.exit( 1 );
 *      }
 *
 *      System.out.println( "Initialising the device. This might take some time..." );
 *      try
 *      {
 *        pDev.open();
 *      }
 *      catch( ImpactAcquireException e )
 *      {
 *        // this e.g. might happen if the same device is already opened in another process...
 *        System.out.println( "An error occurred while opening device " + pDev.getSerial().read() +
 *                            "(error code: " + e.getMessage() + ")." );
 *        mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *        System.exit( 1 );
 *      }
 *
 *      try
 *      {
 *        IOSubSystemFrameGrabber io = new IOSubSystemFrameGrabber( pDev );
 *        final long iCnt = io.getInputCount();
 *        System.out.println( String.format( "Available digital inputs: %d", iCnt ) );
 *        for( long d=0; d<iCnt; d++ )
 *        {
 *          System.out.println( io.input( d ).getDescription() );
 *        }
 *        final long oCnt = io.getOutputCount();
 *        System.out.println( String.format( "Available digital outputs: %d", oCnt ) );
 *        // set all available digital outputs to high
 *        for( long e=0; e<oCnt; e++ )
 *        {
 *          DigitalOutput pOutput = io.output( e );
 *          System.out.println( "setting " + pOutput.getDescription() + " to high" );
 *          pOutput.set();
 *        }
 *
 *        // check there is at least one digital output
 *        if( oCnt > 0 )
 *        {
 *          OutputSignalGeneratorFrameGrabber osg = new OutputSignalGeneratorFrameGrabber( pDev );
 *          // check if this device supports enhanced signal creation at all
 *          if( osg.getControlMode().isValid() )
 *          {
 *            // define a simple pulse on the first digital output detected.
 *            // this pulse will be low after 100 us for
 *            // 200us and then switches back to high.
 *            osg.definePulse( io.output( 0 ), 0, 100, 200 );
 *
 *            // define a more complex pulse
 *            IntVector v = new IntVector();
 *            v.add( 100 );
 *            v.add( 299 );
 *            v.add( 666 );
 *            osg.definePulseSequence( io.output( 0 ), 0, v );
 *            osg.getControlMode().write( TDigitalOutputControlMode.docmSoftware );
 *            osg.getImageTrigger().write( TDeviceImageTrigger.ditAfterDigOutSignals );
 *
 *            // check if line scan pulse creation is supported by this device
 *            StringIntVector dict = new StringIntVector();
 *            osg.getControlMode().getTranslationDict( dict );
 *            final long dictSize = osg.getControlMode().dictSize();
 *            for( long i=0; i<dictSize; i++ )
 *            {
 *              if( dict.get( ( int )i ).getSecond() == TDigitalOutputControlMode.docmRTC )
 *              {
 *                // supported -> define some signal
 *                System.out.println( "checkGrabberInterface: This device supports RTC control signal creation." );
 *                osg.getControlMode().write( TDigitalOutputControlMode.docmRTC );
 *                osg.defineLineScanPulse( io.output( 0 ), TDeviceSignalOutputStartEvent.dsosePeriodically, 100, 100, 1, 1 );
 *              }
 *            }
 *          }
 *        }
 *      }
 *      catch( ImpactAcquireException e )
 *      {
 *        System.out.println( "An error occurred: " + e.getMessage() + ")." );
 *        mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *        System.exit( 1 );
 *      }
 *    }
 *  }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  def setUpIOs(pDev):
 *     # The next line will raise an exception if the device is not operated
 *     # in interface layout 'dilDeviceSpecific' or is not a frame grabber! This
 *     # should therefore be wrapped in an exception handler if in doubt!
 *     io = acquire.IOSubSystemFrameGrabber(pDev)
 *     iCnt = io.getInputCount()
 *     print("available digital inputs: " + str(iCnt))
 *     for x in range(iCnt):
 *       print(io.getInput(d).getDescription())
 *
 *     oCnt = io.getOutputCount()
 *     print("available digital outputs: " + str(oCnt))
 *     # set all available digital outputs to high
 *     for e in range(oCnt):
 *       pOutput = io.getOutput(e)
 *       print("setting " + pOutput.getDescription() + " to high")
 *       pOutput.state = True
 *
 *     # check there is at least one digital output
 *     if oCnt > 0:
 *       osg = acquire.OutputSignalGeneratorFrameGrabber(pDev)
 *       # check if this device supports enhanced signal creation at all
 *       if osg.controlMode.isValid:
 *         # define a simple pulse on the first digital output detected.
 *         # this pulse will be low after 100 us for
 *         # 200us and then switches back to high.
 *         osg.definePulse(io.getOutput(0), 0, 100, 200)
 *
 *         # define a more complex pulse
 *         v = []
 *         v[0] = 100
 *         v[1] = 299
 *         v[1] = 666
 *         osg.definePulseSequence(io.getOutput(0), 0, v)
 *         osg.controlMode.write(acquire.docmSoftware)
 *         osg.imageTrigger.write(acquire.ditAfterDigOutSignals)
 *
 *         # check if line scan pulse creation is supported by this device
 *         dict = {None:None}
 *         osg.controlMode.getTranslationDict(dict)
 *         dictSize = osg.controlMode.dictSize
 *         for i in range(dictSize):
 *             if dict[i].second == acquire.docmRTC:
 *             # supported -> define some signal
 *                 print("checkGrabberInterface: This device supports RTC control signal creation.")
 *                 osg.controlMode.write(acquire.docmRTC)
 *                 osg.defineLineScanPulse(io.getOutput(0), acquire.dsosePeriodically, 100, 100, 1, 1)
 * \endcode
 * \endif
 *
 *  Whenever a signal has been defined for a a certain digital output
 *  pin, this pin can no longer controlled using the corresponding functions
 *  in the class \b mvIMPACT::acquire::DigitalOutput. In order to do that
 *  the pin in question must be released using the function
 *  \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::undefineSignal.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class OutputSignalGeneratorFrameGrabber
//-----------------------------------------------------------------------------
{
#       ifndef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    struct OutputProperties
    //-----------------------------------------------------------------------------
    {
        PropertyIDeviceDigitalOutputMode mode;
        PropertyI polarity;
        PropertyI delay_us;
        PropertyI width_us;
        PropertyI width_pclk;
        PropertyI startLevel;
        PropertyI polaritySwitchAfter_us;
        PropertyIDigitalSignal digitalSignal;
        PropertyI pulseStartConfiguration;
        explicit OutputProperties( HLIST hOutput ) : mode(), polarity(), delay_us(), width_us(),
            width_pclk(), startLevel(), polaritySwitchAfter_us(), digitalSignal(),
            pulseStartConfiguration()
        {
            ComponentLocator locator( hOutput );
            locator.bindComponent( mode, "Mode" );
            locator.bindComponent( polarity, "Polarity" );
            locator.bindComponent( delay_us, "Delay_us" );
            locator.bindComponent( width_us, "Width_us" );
            locator.bindComponent( width_pclk, "Width_pclk" );
            locator.bindComponent( startLevel, "StartLevel" );
            locator.bindComponent( polaritySwitchAfter_us, "PolaritySwitchAfter_us" );
            locator.bindComponent( digitalSignal, "DigitalSignal" );
            locator.bindComponent( pulseStartConfiguration, "PulseStartConfiguration" );
        }
    };
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        ComponentList                            m_outputs;
        PropertyIDeviceSignalOutputStartEvent    m_pulseStartEventLineScan;
        PropertyI                                m_softwareSignalPeriod_pclk;
        PropertyI                                m_output;
        PropertyI                                m_width_pclk;
        PropertyI                                m_polarity;
        PropertyI                                m_divider;
        std::map<std::string, OutputProperties*> m_mOutputs;
        unsigned int                             m_refCnt;
        explicit ReferenceCountedData() : m_outputs(), m_pulseStartEventLineScan(),
            m_softwareSignalPeriod_pclk(), m_output(), m_width_pclk(),
            m_polarity(), m_divider(), m_mOutputs(), m_refCnt( 1 ) {}
        ~ReferenceCountedData()
        {
            std::map<std::string, OutputProperties*>::iterator itEnd = m_mOutputs.end();
            std::map<std::string, OutputProperties*>::iterator it = m_mOutputs.begin();
            while( it != itEnd )
            {
                delete it->second;
                ++it;
            }
        }
    }* m_pRefData;
    //-----------------------------------------------------------------------------
    void bindPublicProperties( HLIST hList )
    //-----------------------------------------------------------------------------
    {
        ComponentLocator locator( hList );
        locator.bindComponent( controlMode, "ControlMode" );
        locator.bindComponent( pulseStartEvent, "PulseStartEvent" );
        locator.bindComponent( imageTrigger, "ImageTrigger" );
    }
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    //-----------------------------------------------------------------------------
    OutputProperties* getOutputProperties( DigitalOutput* pOutput ) const
    //-----------------------------------------------------------------------------
    {
        if( pOutput )
        {
            std::map<std::string, OutputProperties*>::iterator it = m_pRefData->m_mOutputs.find( pOutput->getDescription() );
            if( it != m_pRefData->m_mOutputs.end() )
            {
                return it->second;
            }
        }
        return 0;
    }
#       endif // #ifdef DOXYGEN_SHOULD_SKIP_THIS
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber object.
    explicit OutputSignalGeneratorFrameGrabber(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : m_pRefData( 0 ), controlMode(), pulseStartEvent(), imageTrigger()
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        m_pRefData = new ReferenceCountedData();
        DeviceComponentLocator locator( pDev, dltIOSubSystem );
        locator.bindComponent( m_pRefData->m_outputs, "DigitalOutputs" );
        locator.bindSearchBase( m_pRefData->m_outputs.hObj() );
        bindPublicProperties( m_pRefData->m_outputs.hObj() );
        locator.bindComponent( m_pRefData->m_pulseStartEventLineScan, "PulseStartEvent(LineScan)" );
        locator.bindComponent( m_pRefData->m_softwareSignalPeriod_pclk, "SoftwareSignalPeriod_pclk" );
        locator.bindComponent( m_pRefData->m_output, "Output" );
        locator.bindComponent( m_pRefData->m_width_pclk, "Width_pclk" );
        locator.bindComponent( m_pRefData->m_polarity, "Polarity" );
        locator.bindComponent( m_pRefData->m_divider, "Divider" );
        if( m_pRefData->m_outputs.isValid() )
        {
            Component it( m_pRefData->m_outputs.hObj() );
            it = it.firstChild();
            while( it.isValid() )
            {
                if( it.isList() )
                {
                    m_pRefData->m_mOutputs.insert( std::pair<std::string, OutputProperties*>( it.name(), new OutputProperties( it ) ) );
                }
                ++it;
            }
        }
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber from an existing one.
    OutputSignalGeneratorFrameGrabber(
        /// [in] A constant reference to the \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber object, this object shall be created from
        const OutputSignalGeneratorFrameGrabber& src ) : m_pRefData( src.m_pRefData ),
        controlMode( src.controlMode ), pulseStartEvent( src.pulseStartEvent ), imageTrigger( src.imageTrigger )
    {
        ++( m_pRefData->m_refCnt );
    }
    /// \brief Class destructor.
    ~OutputSignalGeneratorFrameGrabber()
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber objects.
    OutputSignalGeneratorFrameGrabber& operator=( const OutputSignalGeneratorFrameGrabber& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            // inc. the NEW reference count
            ++m_pRefData->m_refCnt;
            bindPublicProperties( m_pRefData->m_outputs.hObj() );
        }
        return *this;
    }
    /// \brief Assigns a single pulse to a digital output.
    /**
     *  Whenever a single pulse of a certain duration and polarity shall be generated
     *  on a digital output as a reaction on a trigger signal that was either generated by one of
     *  digital inputs of the device or software this is the right function to use.
     *
     *  When the signal is generated can be defined by the properties
     *  \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::pulseStartEvent and
     *  \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::imageTrigger.
     *
     *  \sa
     *  \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::undefineSignal
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int definePulse(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemFrameGrabber
        /// for this device.
        DigitalOutput* pOutput,
        /// [in] The polarity of the pulse to generate.
        ///
        /// - 0: The pulse will be low for \a width_pclk and high otherwise
        /// - 1: The pulse will be high for \a width_pclk and high otherwise
        int polarity,
        /// [in] The delay after the trigger event before a signal generation starts
        int delay,
        /// [in] The width of the pulse to generate
        int width,
        /// [in] The pulse start configuration to be used for this pulse sequence.
        /// Not every device will support the use of pulse start configurations. Valid objects that
        /// can be passed to this function can be obtained from a call to \b mvIMPACT::acquire::IOSubSystem::getPulseStartConfiguration,
        /// and \b mvIMPACT::acquire::IOSubSystem::getPulseStartConfigurationCount. If objects of these type are
        /// not supported, pass 0 or ignore this parameter. In that case the property
        /// \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::imageTrigger will define the start condition
        /// for the signal output.
        PulseStartConfiguration* pPulseStartConfiguration = 0 )
    {
        if( !pOutput )
        {
            return DMR_INVALID_PARAMETER;
        }
        OutputProperties* p = getOutputProperties( pOutput );
        if( p )
        {
            p->mode.write( ddomPulse );
            p->polarity.write( polarity );
            p->delay_us.write( delay );
            p->width_us.write( width );
            if( pPulseStartConfiguration )
            {
                p->pulseStartConfiguration.write( pPulseStartConfiguration->number() );
            }
            return DMR_NO_ERROR;
        }
        return DMR_FEATURE_NOT_AVAILABLE;
    }
    /// \brief Assigns a complex signal to a digital output.
    /**
     *  This function can be used when a complex signal shall be generated
     *  on a digital output as a reaction on a trigger signal that was either generated by one of
     *  digital inputs of the device or software.
     *
     *  When the signal is generated can be defined by the properties
     *  \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::pulseStartEvent and
     *  \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::imageTrigger.
     *
     *  \sa
     *  \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::undefineSignal
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int definePulseSequence(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemFrameGrabber
        /// for this device.
        DigitalOutput* pOutput,
        /// [in] The start level of the generated signal.
        ///
        /// - 0: The signal will start with 'low'
        /// - 1: The signal will start with 'high'
        int startLevel,
        /// [in] An array of integer values. Each values defines a switch in polarity
        /// of the signal after 'x' us.
        /// An array containing '1000', '2000' therefore will describe a signal
        /// starting with \a startLevel, switches polarity after 1000 us and then
        /// again switches polarity after 2000 us.
        const std::vector<int>& sequence,
        /// [in] The pulse start configuration to be used for this pulse sequence.
        /// Not every device will support the use of pulse start configurations. Valid objects that
        /// can be passed to this function can be obtained from a call to \b mvIMPACT::acquire::IOSubSystem::getPulseStartConfiguration,
        /// and \b mvIMPACT::acquire::IOSubSystem::getPulseStartConfigurationCount. If objects of these type are
        /// not supported, pass 0 or ignore this parameter. In that case the property
        /// \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::imageTrigger will define the start condition
        /// for the signal output.
        PulseStartConfiguration* pPulseStartConfiguration = 0 )
    {
        if( !pOutput )
        {
            return DMR_INVALID_PARAMETER;
        }
        OutputProperties* p = getOutputProperties( pOutput );
        if( p )
        {
            p->mode.write( ddomUser );
            p->startLevel.write( startLevel );
            p->polaritySwitchAfter_us.write( sequence );
            if( pPulseStartConfiguration )
            {
                p->pulseStartConfiguration.write( pPulseStartConfiguration->number() );
            }
            return DMR_NO_ERROR;
        }
        return DMR_FEATURE_NOT_AVAILABLE;
    }
    /// \brief Receives a list of valid signals that can be passed directly to a certain digital output pin.
    /**
     *  Whenever it is necessary to output a certain signal (e.g. a digital input signal connected to the device or
     *  an internal digital signal like e.g. a frame valid signal) to a digital output of the device this can be done
     *  by a call to the function \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::definePassThroughSignal
     *
     *  As the type of signals that a device can send to a digital output depends heavily on the device and even on the
     *  digital output as well, this function will return a list of strings and a numerical representation for each signal
     *  that can be sent to this digital output.
     *
     *  \note
     *  This function is much more efficient than calling
     *  \b OutputSignalGeneratorFrameGrabber::getValidPassThroughSignalValue and
     *  \b OutputSignalGeneratorFrameGrabber::getValidPassThroughSignalString and
     *  therefore this function should be called whenever all entries are required.
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int getValidSignalsForPassThroughModes(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemFrameGrabber
        /// for this device.
        DigitalOutput* pOutput,
        /// [out] A reference to a vector that will receive the list of allowed digital signals
        /// for this particular digital output pin.
        TDigitalSignalTranslationDict& sequence ) const
    {
        if( !pOutput )
        {
            return DMR_INVALID_PARAMETER;
        }
        OutputProperties* p = getOutputProperties( pOutput );
        if( p && p->digitalSignal.isValid() && p->digitalSignal.hasDict() )
        {
            p->digitalSignal.getTranslationDict( sequence );
            return DMR_NO_ERROR;
        }
        return DMR_FEATURE_NOT_AVAILABLE;
    }
    /// \brief Returns the number of signals that can be used for pass through signal definitions for a certain digital output pin of this device.
    unsigned int getValidPassThroughSignalCount(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemFrameGrabber
        /// for this device.
        DigitalOutput* pOutput ) const
    {
        OutputProperties* p = getOutputProperties( pOutput );
        if( p && p->digitalSignal.isValid() && p->digitalSignal.hasDict() )
        {
            return p->digitalSignal.dictSize();
        }
        return 0;
    }
    /// \brief Receives a valid signal that can be passed directly to a certain digital output pin.
    /**
     *  Whenever it is necessary to output a certain signal (e.g. a digital input signal connected to the device or
     *  an internal digital signal like e.g. a frame valid signal) to a digital output of the device this can be done
     *  by a call to the function \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::definePassThroughSignal
     *
     *  As the type of signals that a device can send to a digital output depends heavily on the device and even on the
     *  digital output as well, this function together with the function \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::getValidPassThroughSignalString
     *  can be used to query a list of strings and a numerical representation for each signal
     *  that can be sent to this digital output.
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::getValidSignalsForPassThroughModes
     *  to obtain this information.
     *  \endif
     */
    TDigitalSignal getValidPassThroughSignalValue(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemFrameGrabber
        /// for this device.
        DigitalOutput* pOutput,
        /// [in] The index of the entry to read from the property. The find out the last valid value for this parameter
        /// call \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::getValidPassThroughSignalCount
        int index = 0 ) const
    {
        OutputProperties* p = getOutputProperties( pOutput );
        if( !p || !p->digitalSignal.isValid() || !p->digitalSignal.hasDict() )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, DMR_FEATURE_NOT_AVAILABLE, "Unsupported feature query" );
        }
        return p ? static_cast<TDigitalSignal>( p->digitalSignal.getTranslationDictValue( index ) ) : dsNone;
    }
    /// \brief Receives a valid string representation of a signal that can be passed directly to a certain digital output pin.
    /**
     *  Whenever it is necessary to output a certain signal (e.g. a digital input signal connected to the device or
     *  an internal digital signal like e.g. a frame valid signal) to a digital output of the device this can be done
     *  by a call to the function \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::definePassThroughSignal
     *
     *  As the type of signals that a device can send to a digital output depends heavily on the device and even on the
     *  digital output as well, this function together with the function \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::getValidPassThroughSignalString
     *  can be used to query a list of strings and a numerical representation for each signal
     *  that can be sent to this digital output.
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::getValidSignalsForPassThroughModes
     *  to obtain this information.
     *  \endif
     */
    std::string getValidPassThroughSignalString(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemFrameGrabber
        /// for this device.
        DigitalOutput* pOutput,
        /// [in] The index of the entry to read from the property. The find out the last valid value for this parameter
        /// call \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::getValidPassThroughSignalCount
        int index = 0 ) const
    {
        OutputProperties* p = getOutputProperties( pOutput );
        if( !p || !p->digitalSignal.isValid() || !p->digitalSignal.hasDict() )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, DMR_FEATURE_NOT_AVAILABLE, "Unsupported feature query" );
        }
        return p->digitalSignal.getTranslationDictString( index );
    }
    /// \brief Assigns a certain signal to a digital output.
    /**
     *  Some digital input signals or even some internal signals can be passed directly to one or more
     *  digital outputs.
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int definePassThroughSignal(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemFrameGrabber
        /// for this device.
        DigitalOutput* pOutput,
        /// [in] The digital signal that shall be passed to the digital output.
        /// Valid values for this parameter will be obtained by a call to the function
        /// \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::getValidSignalsForPassThroughModes.
        TDigitalSignal digitalSignal,
        /// [in] If set to \a true, the signal will be inverted internally before being passed to the output.
        bool boInverted = false )
    {
        if( !pOutput )
        {
            return DMR_INVALID_PARAMETER;
        }
        OutputProperties* p = getOutputProperties( pOutput );
        if( p && p->digitalSignal.isValid() )
        {
            p->mode.write( boInverted ? ddomDigitalSignalPassThroughInv : ddomDigitalSignalPassThrough );
            p->digitalSignal.write( digitalSignal );
            return DMR_NO_ERROR;
        }
        else
        {
            return DMR_FEATURE_NOT_AVAILABLE;
        }
    }
    /// \brief Assigning a certain signal to a digital output.
    /**
     *  Some digital input signals or even some internal signals can be passed directly to one or more
     *  digital outputs.
     *
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int definePassThroughSignal(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemFrameGrabber
        /// for this device.
        DigitalOutput* pOutput,
        /// [in] The string representation of the digital output that shall be passed to the digital output.
        /// Valid values for this parameter will be obtained by a call to the function
        /// \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::getValidSignalsForPassThroughModes.
        const std::string& digitalSignal,
        /// [in] If set to \a true, the signal will be inverted internally before being passed to the output.
        bool boInverted = false )
    {
        if( !pOutput )
        {
            return DMR_INVALID_PARAMETER;
        }
        OutputProperties* p = getOutputProperties( pOutput );
        if( p && p->digitalSignal.isValid() )
        {
            p->mode.write( boInverted ? ddomDigitalSignalPassThroughInv : ddomDigitalSignalPassThrough );
            p->digitalSignal.writeS( digitalSignal );
            return DMR_NO_ERROR;
        }
        return DMR_FEATURE_NOT_AVAILABLE;
    }
    /// \brief Removes the signal definition from the specified output pin.
    /**
     *  Whenever a signal has been defined for a a certain digital output
     *  pin, this pin can no longer controlled using the corresponding functions
     *  in the class \b mvIMPACT::acquire::DigitalOutput. This function removes the
     *  signal definition and hands back manual control of that digital output to the user.
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int undefineSignal(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemFrameGrabber
        /// for this device.
        DigitalOutput* pOutput )
    {
        if( !pOutput )
        {
            return DMR_INVALID_PARAMETER;
        }
        OutputProperties* p = getOutputProperties( pOutput );
        if( p )
        {
            p->mode.write( ddomManual );
            return DMR_NO_ERROR;
        }
        return DMR_FEATURE_NOT_AVAILABLE;
    }
    /// \brief Defines a pulse to trigger line scan cameras.
    /**
     *  Calling this function without setting \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::controlMode
     *  to \b mvIMPACT::acquire::docmRTC will have \b NO effect.
     *
     *  \note
     *  Not every frame grabber will offer the \b mvIMPACT::acquire::docmRTC
     *  mode. Check is the mode is available by reading the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyIDigitalOutputControlMode::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyIDigitalOutputControlMode::getTranslationDictValue. The detailed description
     *  of this class might contain source code examples for the language you are working with.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyIDigitalOutputControlMode::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     *
     *  \sa
     *  \b mvIMPACT::acquire::OutputSignalGeneratorFrameGrabber::undefineSignal
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR otherwise.
     */
    int defineLineScanPulse(
        /// [in] A pointer to a \b mvIMPACT::acquire::DigitalOutput object
        /// obtained from an instance of the class \b mvIMPACT::acquire::IOSubSystemFrameGrabber
        /// for this device.
        DigitalOutput* pOutput,
        /// [in] Defines the start event for the signal generation. Valid values for this parameter
        /// are defined by \b mvIMPACT::acquire::TDeviceSignalOutputStartEvent.
        TDeviceSignalOutputStartEvent pulseStartEventValue,
        /// [in] Defines the frequency for a continuously generated signal if
        /// \a pulseStartEventValue is \b mvIMPACT::acquire::dsoseSyncInRisingEdge
        /// or \b mvIMPACT::acquire::dsoseSyncInFallingEdge and is
        /// ignored otherwise.
        int softwareSignalPeriod_pclk,
        /// [in] The width of the signal to generate if \a pulseStartEventValue is \b mvIMPACT::acquire::dsoseSyncInRisingEdge,
        /// \b mvIMPACT::acquire::dsosePeriodically or
        /// \b mvIMPACT::acquire::dsoseSyncInFallingEdge and is
        /// ignored otherwise.
        int width_pclk,
        /// [in] The polarity of the signal to generate if \a pulseStartEventValue is \b mvIMPACT::acquire::dsoseSyncInRisingEdge,
        /// \b mvIMPACT::acquire::dsosePeriodically or
        /// \b mvIMPACT::acquire::dsoseSyncInFallingEdge and is
        /// ignored otherwise.
        ///
        /// - 0: The signal will be low for \a width_pclk and high otherwise
        /// - 1: The signal will be high for \a width_pclk and high otherwise
        int polarity,
        /// [in] Defines the divider value if \a pulseStartEventValue is
        /// \b mvIMPACT::acquire::dsosePeriodically
        unsigned int divider )
    {
        if( !pOutput )
        {
            return DMR_INVALID_PARAMETER;
        }
        OutputProperties* p = getOutputProperties( pOutput );
        if( p )
        {
            m_pRefData->m_pulseStartEventLineScan.write( pulseStartEventValue );
            m_pRefData->m_output.writeS( pOutput->getDescription() );
            switch( pulseStartEventValue )
            {
            case dsoseSyncInRisingEdge:
            case dsoseSyncInFallingEdge:
                m_pRefData->m_width_pclk.write( width_pclk );
                m_pRefData->m_polarity.write( polarity );
                m_pRefData->m_divider.write( divider );
                break;
            case dsosePeriodically:
                m_pRefData->m_softwareSignalPeriod_pclk.write( softwareSignalPeriod_pclk );
                m_pRefData->m_width_pclk.write( width_pclk );
                m_pRefData->m_polarity.write( polarity );
                break;
            default:
                // nothing to do
                break;
            }
            return DMR_NO_ERROR;
        }
        return DMR_FEATURE_NOT_AVAILABLE;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the general method used to create output signals.
    /**
     *  This setting always applies to every signal defined. Modifying this property will also
     *  change the behaviour of signals already defined.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDigitalOutputControlMode.
     *
     *  When switching to \b mvIMPACT::acquire::docmRTC mode
     *  only one signal can be created currently.
     *
     *  \note
     *  Not every frame grabber will offer the \b mvIMPACT::acquire::docmRTC
     *  mode. Check if the mode is available by reading the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyIDigitalOutputControlMode::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyIDigitalOutputControlMode::getTranslationDictValue.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyIDigitalOutputControlMode::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     *
     *  Some devices will offer a more flexible way to define this behaviour. In this case, this property won't be available (a call to the function
     *  \b mvIMPACT::acquire::Component::isValid will return false). However then calls to \b mvIMPACT::acquire::IOSubSystem::getPulseStartConfigurationCount
     *  and \b mvIMPACT::acquire::IOSubSystem::getPulseStartConfiguration will succeed and the objects returned by
     *  \b mvIMPACT::acquire::IOSubSystem::getPulseStartConfiguration (\b mvIMPACT::acquire::PulseStartConfiguration) will
     *  provide a more sophisticated way to define the signal output behaviour of a device.
     */
    PropertyIDigitalOutputControlMode controlMode;
    /// \brief An enumerated integer property defining the general behaviour of created output signals.
    /**
     *  This setting always applies to every signal defined. Modifying this property will also
     *  change the behaviour of signals already defined.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceSignalOutputStartEvent.
     */
    PropertyIDeviceSignalOutputStartEvent pulseStartEvent;
    /// \brief An enumerated integer property defining the general behaviour of created output signals.
    /**
     *  This setting always applies to every signal defined. Modifying this property will also
     *  change the behaviour of signals already defined.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceImageTrigger.
     */
    PropertyIDeviceImageTrigger imageTrigger;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

//-----------------------------------------------------------------------------
/// \brief A class describing how a video signal source(e.g. a camera or image sensor) is connected to a video signal sink(e.g. a frame grabber)(\b Device specific interface layout only).
/**
 *  With an instance of this class the user can define on which input channels the
 *  video signal source used for this setting is connected to the video signal sink and how(in which format) the
 *  video signal source transmits its data.
 *
 *  Video signal source and video signal sink can both belong to the same physical piece
 *  of hardware. This e.g. might apply to a digital camera that doesn't need a
 *  frame grabber (e.g. a GigE Vision&trade;, USB3 Vision&trade; or USB camera). In such a scenario
 *  certain properties belonging to this class might be read-only or may only allow
 *  a single enumeration value.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class Connector : public ComponentCollection
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::Connector object.
    explicit Connector(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : ComponentCollection( pDev ), cameraOutputUsed(),
        videoChannel(), pinDescription()
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        DeviceComponentLocator locator( pDev, dltSetting, settingName );
        if( locator.findComponent( "Connector" ) != INVALID_ID )
        {
            locator.bindSearchBase( locator.searchbase_id(), "Connector" );
            m_hRoot = locator.searchbase_id();
            locator.bindComponent( cameraOutputUsed, "CameraOutputUsed" );
            locator.bindComponent( videoChannel, "VideoChannel" );
            locator.bindComponent( pinDescription, "PinDescription" );
        }
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the video signal output of the video signal source used for the connection to the video signal sink.
    /**
     *  \note
     *  Not every video signal sink will support every possible value defined for this property.
     *  For example a CameraLink&reg; frame grabber will not offer to use an SVideo connector.
     *  Therefore the translation dictionary of this property should be used to find out, which connector types are available.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraOutput.
     *
     *  \note
     *  This property might not be supported by every device. Therefore always call the function
     *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyICameraOutput cameraOutputUsed;
    /// \brief An integer property containing the video channel the camera belonging to the current setting is connected to.
    /**
     *  The maximum possible video channel might change when the property
     *  \b mvIMPACT::acquire::Connector::cameraOutputUsed is modified as the different
     *  ways to transmit a video signal require more or less video input channels. While e.g. a composite
     *  video signal can be transmitted via a single wire, an RGB signal requires either 3 or 4 wires
     *  (depending on whether the sync. signal is transmitted on a separate wire or not).
     *
     *  The first channel will always have the number 0. The limits (max/min values) can be queried
     *  by calling the function \b mvIMPACT::acquire::PropertyI::getMinValue or
     *  \b mvIMPACT::acquire::PropertyI::getMaxValue.
     *
     *  \note
     *  This property might not be supported by every device. Therefore always call the function
     *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyI videoChannel;
    /// \brief A string property \b (read-only) containing a description for the video channel currently selected by the property \b mvIMPACT::acquire::Connector::videoChannel.
    /**
     *  The description string contains information about the connector pins belonging to this video
     *  input of the video signal sink as well as the corresponding name of this video input.
     *
     *  \note
     *  This property might not be supported by every device. Therefore always call the function
     *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyS pinDescription;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A base class for camera related settings(\b Device specific interface layout only).
/**
 * This class acts as a base class for camera related settings. It only contains
 * settings that are available for every device!
 *
 * \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 * \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class BasicDeviceSettingsWithAOI : public BasicDeviceSettings
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::BasicDeviceSettingsWithAOI object.
    explicit BasicDeviceSettingsWithAOI(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : BasicDeviceSettings( pDev, settingName ), aoiHeight(),
        aoiStartX(), aoiStartY(), aoiWidth()
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        ComponentLocator locator( m_hRoot );
        if( locator.findComponent( "Aoi" ) != INVALID_ID )
        {
            locator.bindSearchBase( locator.searchbase_id(), "Aoi" );
            locator.bindComponent( aoiHeight, "H" );
            locator.bindComponent( aoiStartX, "X" );
            locator.bindComponent( aoiStartY, "Y" );
            locator.bindComponent( aoiWidth, "W" );
        }
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property defining the number of lines to capture.
    PropertyI aoiHeight;
    /// \brief An integer property defining the X-offset for each capture line.
    /**
     *  Example: When setting this property to 5 the first pixel in each line of
     *  the resulting image will be pixel number 5 of each line transmitted by
     *  the camera.
     */
    PropertyI aoiStartX;
    /// \brief An integer property defining the Y-offset.
    /**
     *  Example: When setting this property to 5 the first line of
     *  the resulting image will be line number 5 of the image transmitted by
     *  the camera.
     */
    PropertyI aoiStartY;
    /// \brief An integer property defining the number of pixels to capture per line.
    PropertyI aoiWidth;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A base class for camera related settings(\b Device specific interface layout only).
/**
 * This class acts as a base class for camera related settings. It only contains
 * settings that are available for almost every device!
 *
 * \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 * \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraSettingsBase : public BasicDeviceSettingsWithAOI
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::CameraSettingsBase object.
    explicit CameraSettingsBase(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : BasicDeviceSettingsWithAOI( pDev, settingName ), pixelFormat()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( pixelFormat, "PixelFormat" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the pixel format used to transfer the image data into the target systems host memory.
    /**
     *  Support for this property has been added in version 1.11.0 of mvIMPACT Acquire thus old driver versions will
     *  raise an exception if an application accesses the property without checking if the property is present.
     *
     *  By default this property will be set to \b mvIMPACT::acquire::ibpfAuto. This will result in the previous driver
     *  behaviour where depending on the various post processing steps that are enabled or disabled the driver will decide
     *  which transfer format will be used. However sometimes this could result in a transfer format, which is not ideal
     *  for the application (e.g. when a post processing step of the application needs RGBx888Packed but the systems bandwidth
     *  is limited the application might want to transfer the data in YUV422 packed and then use the fast format conversion
     *  algorithm in the driver). This can be achieved by explicitly setting \b mvIMPACT::acquire::CameraSettingsBase::pixelFormat to
     *  \b mvIMPACT::acquire::ibpfYUV422Packed and \b mvIMPACT::acquire::ImageDestination::pixelFormat to
     *  \b mvIMPACT::acquire::ibpfRGBx888Packed.
     *
     *  \note
     *  Selecting a defined transfer format can in some cases result in certain filters (e.g. dark current, ...) to be switched
     *  of as then the filters themselves can no longer influence the transfer format, which is sometimes necessary as not every
     *  filter does support every input format. Also this property will contain only pixel formats, which are actually supported
     *  by the capture device, thus in most of the cases this will be a subset of the pixel formats defined by the enumeration defining this property.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TImageBufferPixelFormat.
     */
    PropertyIImageBufferPixelFormat pixelFormat;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

#   ifndef IGNORE_MVVIRTUALDEVICE_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief \b mvVirtualDevice related camera settings(\b Device specific interface layout only).
/**
 *  \note
 *  As this is a device driver meant for testing the interface an allowing to
 *  start the integration of mvIMPACT Acquire into an application, this class
 *  might change at ANY time! Changes in the virtual device driver might not
 *  be backward compatible!
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraSettingsVirtualDevice : public CameraSettingsBase
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::CameraSettingsVirtualDevice object.
    explicit CameraSettingsVirtualDevice(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : CameraSettingsBase( pDev, settingName ),
        bufferPartCount(), aoiMode(), gain_dB(), testMode(), channelBitDepth(), paddingX(), tapsXGeometry(), tapsYGeometry(),
        frameDelay_us(), imageDirectory(), imageType(), bayerMosaicParity(), testImageBarWidth(), userData()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( bufferPartCount, "BufferPartCount" );
        locator.bindComponent( aoiMode, "AoiMode" );
        locator.bindComponent( gain_dB, "Gain_dB" );
        locator.bindComponent( testMode, "TestMode" );
        locator.bindComponent( channelBitDepth, "ChannelBitDepth" );
        locator.bindComponent( paddingX, "PaddingX" );
        locator.bindComponent( tapsXGeometry, "TapsXGeometry" );
        locator.bindComponent( tapsYGeometry, "TapsYGeometry" );
        locator.bindComponent( frameDelay_us, "FrameDelay_us" );
        locator.bindComponent( imageDirectory, "ImageDirectory" );
        locator.bindComponent( imageType, "ImageType" );
        locator.bindComponent( bayerMosaicParity, "BayerMosaicParity" );
        locator.bindComponent( testImageBarWidth, "TestImageBarWidth" );
        locator.bindComponent( userData, "UserData" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property defining the number of buffer part to transmit in each request.
    /**
     *  This property is meant to test the multi-part buffer feature of mvIMPACT Acquire mainly. When
     *  set to 0 multi-part buffer handling is switched off. When set to a value greater than 0 the
     *  virtual device will transmit data in multi-part mode, meaning that <b>mvIMPACT::acquire::Request::getBufferPartCount()</b>
     *  will return a value larger than zero. Only when this is the case the properties belonging to the
     *  individual buffer parts are guaranteed to contain up to date data while then all properties whose name
     *  starts with \c image within that request might not.
     *
     *  \since 2.20.0
     */
    PropertyI bufferPartCount;
    /// \brief An enumerated integer property defining the used AOI mode for the image capture.
    /**
     *  This feature will only be visible, when the property \b mvIMPACT::acquire::CameraSettingsVirtualDevice::testMode
     *  is set to \b mvIMPACT::acquire::vdtmImageDirectory. Then this property will allow to enforce a certain image dimension
     *  ( \b mvIMPACT::acquire::camUser ) or to capture every image file in its original dimensions ( \b mvIMPACT::acquire::camFull ).
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraAoiMode.
     *
     *  \since 2.11.9
     */
    PropertyICameraAoiMode aoiMode;
    /// \brief A float property defining the gain in dB to be applied to the test image.
    /**
     * The formula for given \c gain_dB is
     * \code
     * gain_x= 10 ^ (gain_dB/20)
     * \endcode
     *
     * \b Example:
     *
     * \code
     * gain_x = 10 ^ (6/20) = 1.995
     * \endcode
     *
     * I.e. increasing the gain setting by 6dB corresponds to factor of 2.
     *
     * The formula for given gain_x is
     * \code
     * gain_dB = 20*log(gain_x) dB
     * \endcode
     *
     * Where: \n
     * \c gain_dB: MATRIX VISION gain value (logarithmic) \n
     * \c gain_x: multiplicative gain \n
     * \c ^: power function \n
     */
    PropertyF gain_dB;
    /// \brief An enumerated integer property defining the test mode use to generate the dummy images.
    /**
     *  When \b mvIMPACT::acquire::CameraSettingsBase::pixelFormat is \b NOT set to \b mvIMPACT::acquire::ibpfAuto, this
     *  this property will become invisible.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TVirtualDeviceTestMode.
     */
    PropertyIVirtualDeviceTestMode testMode;
    /// \brief An integer property defining the channel bit depth for certain test image generation modes.
    /**
     *  When \b mvIMPACT::acquire::CameraSettingsBase::pixelFormat is \b NOT set to \b mvIMPACT::acquire::ibpfAuto, this
     *  this property will become invisible.
     *
     *  When \b mvIMPACT::acquire::CameraSettingsVirtualDevice::testMode is set to \b mvIMPACT::acquire::vdtmMovingMonoRamp,
     *  \b mvIMPACT::acquire::vdtmMovingBayerDataRamp or \b mvIMPACT::acquire::vdtmBayerWhiteBalanceTestImage this property
     *  will allow to define the pixel format for the test image.
     */
    PropertyI channelBitDepth;
    /// \brief An integer property defining the padding(in bytes) in X-direction for certain test image generation modes.
    /**
     *  When \b mvIMPACT::acquire::CameraSettingsVirtualDevice::testMode is set to a mono format(not the weird packed ones!),
     *  \b mvIMPACT::acquire::vdtmMovingBayerDataRamp or \b mvIMPACT::acquire::vdtmBayerWhiteBalanceTestImage this property
     *  will allow to define the padding in bytes for each line. This will result in images where the line pitch differs from
     *  the width multiplied by the bytes per pixel value. E.g. a padding of 1 in X-direction and a width of 5 for a 16 bit mono
     *  format will result in a line pitch of 11 bytes(5*2 + 1).
     */
    PropertyI paddingX;
    /// \brief An enumerated integer property defining the way this camera transmits the pixel data in X direction.
    /**
     *  Within the virtual device driver, modifying this property internally will only attach the corresponding
     *  attribute to the request buffer, thus might result in the tap sort filter to process the data. This is mainly
     *  meant for testing purposes.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraTapsXGeometry.
     * \since 2.5.2
     */
    PropertyICameraTapsXGeometry tapsXGeometry;
    /// \brief An enumerated integer property defining the way this camera transmits the pixel data in Y direction.
    /**
     *  Within the virtual device driver, modifying this property internally will only attach the corresponding
     *  attribute to the request buffer, thus might result in the tap sort filter to process the data. This is mainly
     *  meant for testing purposes.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraTapsYGeometry.
     * \since 2.5.2
     */
    PropertyICameraTapsYGeometry tapsYGeometry;
    /// \brief An integer property defining a delay in us before the 'captured' image is returned to the user.
    PropertyI frameDelay_us;
    /// \brief A string property defining the directory to capture images from.
    /**
     *  This feature will only be visible, when the property \b mvIMPACT::acquire::CameraSettingsVirtualDevice::testMode
     *  is set to \b mvIMPACT::acquire::vdtmImageDirectory.
     *
     *  See \b mvIMPACT::acquire::CameraSettingsVirtualDevice::imageType to find out how to configure what kind of images shall be captured from disc.
     */
    PropertyS imageDirectory;
    /// \brief An enumerated integer property defining what images shall be captured from hard disk.
    /**
     *  This feature will only be visible, when the property \b mvIMPACT::acquire::CameraSettingsVirtualDevice::testMode
     *  is set to \b mvIMPACT::acquire::vdtmImageDirectory.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TVirtualDeviceImageType.
     */
    PropertyIVirtualDeviceImageType imageType;
    /// \brief An enumerated integer property defining the Bayer attribute assigned to the generated test image.
    /**
     *  When images are acquired via a directory, or a Bayer test pattern is generated this can be used to specify the Bayer parity.
     *  \b mvIMPACT::acquire::bmpUndefined will set the buffers Bayer attribute thus will result in a grey(mono) buffer being returned.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBayerMosaicParity.
     */
    PropertyIBayerMosaicParity bayerMosaicParity;
    /// \brief An integer property defining the width (in pixels) of the different bars in certain test modes.
    PropertyI testImageBarWidth;
    /// \brief A string property that will be copied into the user data property of each request.
    /**
     *  This e.g. can be used to assign a certain identifier to each image request.
     */
    PropertyS userData;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVVIRTUALDEVICE_SPECIFIC_DOCUMENTATION

#   ifndef IGNORE_MVV4L2_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief \b mvV4L2 related camera settings(\b Device specific interface layout only).
/**
 *  \note UNDER CONSTRUCTION! Subject to change.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraSettingsV4L2Device : public BasicDeviceSettingsWithAOI
//-----------------------------------------------------------------------------
{
    Component        m_customFeatureIterator;
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::CameraSettingsV4L2Device object.
    explicit CameraSettingsV4L2Device(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : BasicDeviceSettingsWithAOI( pDev, settingName ),
        m_customFeatureIterator(), imageWidth(), imageHeight(), videoStandard(), pixelFormat(),
        brightness(), contrast(), saturation(), hue(), blackLevel(), autoWhiteBalance(), redBalance(),
        blueBalance(), gamma(), exposure(), autoGain(), gain(), HFlip(), VFlip(), powerLineFrequency(),
        hueAuto(), whiteBalanceTemperature(), sharpness(), backlightCompensation()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( imageWidth, "ImageWidth" );
        locator.bindComponent( imageHeight, "ImageHeight" );
        locator.bindComponent( videoStandard, "VideoStandard" );
        locator.bindComponent( pixelFormat, "PixelFormat" );
        locator.bindComponent( brightness, "Brightness" );
        locator.bindComponent( contrast, "Contrast" );
        locator.bindComponent( saturation, "Saturation" );
        locator.bindComponent( hue, "Hue" );
        locator.bindComponent( blackLevel, "BlackLevel" );
        locator.bindComponent( autoWhiteBalance, "AutoWhiteBalance" );
        locator.bindComponent( redBalance, "RedBalance" );
        locator.bindComponent( blueBalance, "BlueBalance" );
        locator.bindComponent( gamma, "Gamma" );
        locator.bindComponent( exposure, "Exposure" );
        locator.bindComponent( autoGain, "AutoGain" );
        locator.bindComponent( gain, "Gain" );
        locator.bindComponent( HFlip, "HFlip" );
        locator.bindComponent( VFlip, "VFlip" );
        locator.bindComponent( powerLineFrequency, "PowerLineFrequency" );
        locator.bindComponent( hueAuto, "HueAuto" );
        locator.bindComponent( whiteBalanceTemperature, "WhiteBalanceTemperature" );
        locator.bindComponent( sharpness, "Sharpness" );
        locator.bindComponent( backlightCompensation, "BacklightCompensation" );
        m_customFeatureIterator = Component( pixelFormat.hObj() );
        m_customFeatureIterator = m_customFeatureIterator.firstSibling();
    }
    /// \brief Returns an iterator to for iterating inside a device specific feature list.
    /**
     *  This can be useful a device offers custom features that are not defined in the V4L2 standard and thus
     *  can't be known at compile time.
     *
     *  It allows to write code like this:
     *
     * \if DOXYGEN_CPP_DOCUMENTATION
     * \code
     *  CameraSettingsV4L2Device cs( getDevicePointerFromSomewhere() );
     *  Component it( cs.getCustomFeatureIterator() );
     *  std::map<std::string, std::string> m;
     *  while( it.isValid() )
     *  {
     *    // collect all entries that are properties and store their current name and value in a map
     *    if( it.isProp() && it.isVisible() )
     *    {
     *      Property prop( it );
     *      m.insert( std::make_pair( prop.name(), prop.readS() );
     *    }
     *    ++it;
     *  }
     * \endcode
     * \elseif DOXYGEN_JAVA_DOCUMENTATION
     * \code
     *  import java.util.Hashtable;
     *
     *  // ...
     *
     *  CameraSettingsV4L2Device cs = new CameraSettingsV4L2Device( getDevicePointerFromSomewhere() );
     *  Component it = cs.getCustomFeatureIterator();
     *  Hashtable<String, String> m = new Hashtable<String, String>();
     *  while( it.isValid() )
     *  {
     *    // collect all entries that are properties and store their current name and value in a hash table
     *    if( it.isProp() && it.isVisible() )
     *    {
     *       Property prop = new Property( it.hObj() );
     *       m.put( prop.name(), prop.readS() );
     *    }
     *    it = it.nextSibling();
     *  }
     * \endcode
     * \elseif DOXYGEN_PYTHON_DOCUMENTATION
     * \code
     *   cs = acquire.CameraSettingsV4L2Device(pDev)
     *   it = acquire.Component(cs.getCustomFeatureIterator())
     *   m = {}
     *   while it.isValid:
     *     # collect all entries that are properties and store their current name and value in a map
     *     if it.isProp and it.isVisible:
     *       prop = acquire.Property(it);
     *       m[prop.name()] = prop.readS()
     *     it = it.nextSibling()
     * \endcode
     * \endif
     */
    Component getCustomFeatureIterator( void ) const
    {
        return m_customFeatureIterator;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property defining the width of the image supplied by the V4L2 device.
    /**
     *  \sa V4L2 API at http://v4l2spec.bytesex.org/spec-single/v4l2.html
     */
    PropertyI imageWidth;
    /// \brief An integer property defining the height of the image supplied by the V4L2 device.
    /**
     *  \sa V4L2 API at http://v4l2spec.bytesex.org/spec-single/v4l2.html
     */
    PropertyI imageHeight;
    /// \brief An integer property defining the video standard.
    /**
     *  Use this property to configure the V4L2-device corresponding to the connected video source.
     *  Available video standards depend on the V4L2-device and conform to \b v4l2_std_id
     *  \sa V4L2 API at http://v4l2spec.bytesex.org/spec-single/v4l2.html
     */
    PropertyI videoStandard;
    /// \brief An integer property defining the pixel format of captured frames.
    /**
     *  Use this property to set the pixel format within the image buffer supplied by the V4L2-device.
     *  Available pixel formats depend on the V4L2-device and conform to \b v4l2_fourcc()
     *  \sa V4L2 API at http://v4l2spec.bytesex.org/spec-single/v4l2.html
     */
    PropertyI pixelFormat;
    /// \brief An integer property to adjust the brightness.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI brightness;
    /// \brief An integer property to adjust the contrast.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI contrast;
    /// \brief An integer property to adjust the saturation.
    /**
     *  This property represents a V4L2-control ID.
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI saturation;
    /// \brief An integer property to adjust the hue.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI hue;
    /// \brief An integer property to adjust the black level.
    /**
     *  This property represents a V4L2-control ID.
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI blackLevel;
    /// \brief An enumerated integer property to switch on/off the auto white balance function of the V4L2-device.
    /**
     *  This property represents a boolean-valued V4L2-control ID. Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIBoolean autoWhiteBalance;
    /// \brief An integer property to adjust the red balance.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI redBalance;
    /// \brief An integer property to adjust the blue balance.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI blueBalance;
    /// \brief An integer property to adjust the gamma.
    /**
     *  This property represents a V4L2-control ID
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a min-value, a max-value and step-width are defined. Thus, invalid values may be tuned after writing to fit within the limits.
     */
    PropertyI gamma;
    /// \brief An integer property to adjust the exposure.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI exposure;
    /// \brief An enumerated integer property to switch on/off the auto gain.
    /**
     *  This property represents a boolean-valued V4L2-control ID. Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIBoolean autoGain;
    /// \brief An integer property to adjust the gain.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI gain;
    /// \brief An enumerated integer property to mirror the frames horizontally.
    /**
     *  This property represents a boolean-valued V4L2-control ID. Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIBoolean HFlip;
    /// \brief An integer property to mirror the frames vertically.
    /**
     *  This property represents a boolean-valued V4L2-control ID. Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIBoolean VFlip;
    /// \brief An enumerated integer property to enable power line frequency filter.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *
     *  If supported, possible values conform to V4L2 API:
     *  <table>
     *  <tr><td class="header">string representation</td><td class="header">numerical representation</td></tr>
     *  <tr><td class="indexvalue">V4L2_CID_POWER_LINE_FREQUENCY_DISABLED</td><td class="indexvalue">0</td></tr>
     *  <tr><td class="indexvalue">V4L2_CID_POWER_LINE_FREQUENCY_50HZ</td><td class="indexvalue">1</td></tr>
     *  <tr><td class="indexvalue">V4L2_CID_POWER_LINE_FREQUENCY_60HZ</td><td class="indexvalue">2</td></tr>
     *  </table>
     */
    PropertyI powerLineFrequency;
    /// \brief An enumerated integer property to switch on/off auto hue.
    /**
     *  This property represents a boolean-valued V4L2-control ID. Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIBoolean hueAuto;
    /// \brief An integer property to adjust white balance temperature.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI whiteBalanceTemperature;
    /// \brief An integer property to adjust the sharpness.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI sharpness;
    /// \brief An integer property to adjust the backlight compensation.
    /**
     *  This property represents a V4L2-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a min-value, a max-value and step-width are defined. Thus, invalid values may be tuned after writing to fit within the limits.
     */
    PropertyI backlightCompensation;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVV4L2_SPECIFIC_DOCUMENTATION

#   if !defined(IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION) || !defined(IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION)
//-----------------------------------------------------------------------------
/// \brief A class to control the automatic control parameters of a device(\b Device specific interface layout only).
/**
 * Currently this class provides access to the properties, which control the way the
 * AGC(\b A utomatic \b G ain \b C ontrol) and the AEC
 * (\b A utomatic \b E xpose \b C ontrol) operates.
 *
 * The values used to capture the image, which are directly influenced by this properties
 * (e.g. the gain or the exposure time) will be returned as part of the result of the
 * image request.
 *
 * \note
 * Not every device will offer the features provided in this class. Before accessing any members
 * and/or properties call the function \b mvIMPACT::acquire::AutoControlParameters::isAvailable.
 * If this function returns false, no other member or function call in this class will return valid
 * results.
 *
 * \note
 * Instances of these class can't be constructed directly. Its parameters can
 * be accessed via an instance of the class \b mvIMPACT::acquire::CameraSettingsBlueDevice.
 *
 * \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 * \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class AutoControlParameters : public ComponentCollection
//-----------------------------------------------------------------------------
{
    friend class CameraSettingsBlueDevice;
    bool m_boAvailable;
    explicit AutoControlParameters( HOBJ hObj ): m_boAvailable( false ), aoiHeight(),
        aoiStartX(), aoiStartY(), aoiWidth(), aoiMode(), desiredAverageGreyValue(),
        controllerSpeed(), controllerGain(), controllerIntegralTime_ms(), controllerDerivativeTime_ms(),
        controllerDelay_Images(), gainLowerLimit_dB(),
        gainUpperLimit_dB(), exposeLowerLimit_us(), exposeUpperLimit_us()
    {
        ComponentLocator locator( hObj );
        HOBJ hRoot = locator.findComponent( "AutoControlParameters" );
        if( hRoot != INVALID_ID )
        {
            m_hRoot = hRoot;
            locator.bindSearchBase( locator.searchbase_id(), "AutoControlParameters" );
            locator.bindComponent( aoiMode, "AoiMode" );
            locator.bindComponent( desiredAverageGreyValue, "DesiredAverageGreyValue" );
            locator.bindComponent( controllerSpeed, "ControllerSpeed" );
            locator.bindComponent( controllerDelay_Images, "ControllerDelay_Images" );
            locator.bindComponent( gainLowerLimit_dB, "GainLowerLimit_dB" );
            locator.bindComponent( gainUpperLimit_dB, "GainUpperLimit_dB" );
            locator.bindComponent( exposeLowerLimit_us, "ExposeLowerLimit_us" );
            locator.bindComponent( exposeUpperLimit_us, "ExposeUpperLimit_us" );
            if( locator.findComponent( "ControllerParameter" ) != INVALID_ID )
            {
                locator.bindSearchBase( hRoot, "ControllerParameter" );
                locator.bindComponent( controllerGain, "ControllerGain" );
                locator.bindComponent( controllerIntegralTime_ms, "IntegralTime_ms" );
                locator.bindComponent( controllerDerivativeTime_ms, "DerivativeTime_ms" );
            }
            locator.bindSearchBase( hRoot );
            if( locator.findComponent( "Aoi" ) != INVALID_ID )
            {
                locator.bindSearchBase( hRoot, "Aoi" );
                locator.bindComponent( aoiHeight, "H" );
                locator.bindComponent( aoiStartX, "X" );
                locator.bindComponent( aoiStartY, "Y" );
                locator.bindComponent( aoiWidth, "W" );
            }
            m_boAvailable = true;
        }
    }
public:
    /// \brief This function should be called to check if this device offers auto control parameters.
    /**
     *  \return
     *  - true if the device offers the features defined by this object.
     *  - false otherwise
     */
    bool isAvailable( void ) const
    {
        return m_boAvailable;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property defining the height of the rectangle used for the parameter calculation.
    PropertyI aoiHeight;
    /// \brief An integer property defining the X-offset of the rectangle used for the parameter calculation.
    /**
     *  Example: When setting this property to 5 the first pixel in each line of
     *  the resulting rectangle used for the calculation will be pixel number 5
     *  of each line transmitted by the camera.
     */
    PropertyI aoiStartX;
    /// \brief An integer property defining the Y-offset of the rectangle used for the parameter calculation.
    /**
     *  Example: When setting this property to 5 the first line of
     *  the resulting rectangle used for the calculation will be line number 5 of the
     *  image transmitted by the camera.
     */
    PropertyI aoiStartY;
    /// \brief An integer property defining the width of the rectangle.
    PropertyI aoiWidth;
    /// \brief An enumerated integer property defining the which area of the image is used for the calculation of the parameters.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAoiMode.
     */
    PropertyIAoiMode aoiMode;
    /// \brief An integer property defining the average grey value to be reached within the AOI in the image by the control circuit.
    /**
     *  For multi-byte pixel formats like e.g. \b mvIMPACT::acquire::ibpfMono10 this value will refer to
     *  the 8 most significant bits of the pixel data, thus e.g a value of 128 for this property will result
     *  it the controller trying reach an average grey value of 512 (0x200).
     */
    PropertyI desiredAverageGreyValue;
    /// \brief An enumerated integer property defining the speed the control circuit will be operated in.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAutoControlSpeed.
     *
     *  Once the controller started to react and adapt itself to a new situation, this property will
     *  define how long this adaption will take, while \b AutoControlParameters::controllerDelay_Images
     *  defines the number of images to wait from a detected change to the actual start of the
     *  adaption to this new situation.
     */
    PropertyIAutoControlSpeed controllerSpeed;
    /// \brief The \b P fraction of the controller.
    /**
     *  This feature will only be visible when \b mvIMPACT::acquire::AutoControlParameters::controllerSpeed
     *  is set to \b mvIMPACT::acquire::acsUserDefined.
     */
    PropertyF controllerGain;
    /// \brief The \b I fraction of the controller.
    /**
     *  This feature will only be visible when \b mvIMPACT::acquire::AutoControlParameters::controllerSpeed
     *  is set to \b mvIMPACT::acquire::acsUserDefined.
     */
    PropertyF controllerIntegralTime_ms;
    /// \brief The \b D fraction of the controller.
    /**
     *  This feature will only be visible when \b mvIMPACT::acquire::AutoControlParameters::controllerSpeed
     *  is set to \b mvIMPACT::acquire::acsUserDefined.
     */
    PropertyF controllerDerivativeTime_ms;
    /// \brief An integer property to influence the speed the AGC and/or AEC control circuit will react and adapt to changes.
    /**
     *  While \b AutoControlParameters::controllerSpeed influences the overall time
     *  needed to adjust the controller to a new situation, this property can be used to define a
     *  delay when the controller shall start to adapt to a changed situation.
     */
    PropertyI controllerDelay_Images;
    /// \brief A float property defining the lower limit for the cameras gain(in dB).
    /**
     *  When the AGC is active this value defines the minimum value for the cameras gain.
     *  Even if the controller can reach the desired average grey value, the gain will
     *  never fall below this value.
     */
    PropertyF gainLowerLimit_dB;
    /// \brief A float property defining the upper limit for the cameras gain(in dB).
    /**
     *  When the AGC is active this value defines the maximum value for the cameras gain.
     *  Even if the controller can reach the desired average grey value, the gain will
     *  never exceed this value.
     */
    PropertyF gainUpperLimit_dB;
    /// \brief A float property defining the lower limit for the sensors expose time(in us).
    /**
     *  When the AEC is active this value defines the minimum value for the sensors expose time(in us).
     *  Even if the controller can reach the desired average grey value, the expose time will
     *  never fall below this value.
     */
    PropertyI exposeLowerLimit_us;
    /// \brief An integer property defining the upper limit for the sensors expose time in us.
    /**
     *  When the AEC is active this value defines the maximum value for the sensors expose time(in us).
     *  Even if the controller can reach the desired average grey value, the expose time will
     *  never exceed this value.
     */
    PropertyI exposeUpperLimit_us;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A base class for camera related settings belonging to the mvBlueXXX-series (\b Device specific interface layout only).
/**
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraSettingsBlueDevice : public CameraSettingsBase
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::CameraSettingsBlueDevice object.
    explicit CameraSettingsBlueDevice(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : CameraSettingsBase( pDev, settingName ),
        autoControlMode(), autoGainControl(), autoExposeControl(), gain_dB(),
        offset_pc(), pixelClock_KHz(), exposeMode(), expose_us(),
        binningMode(), testMode(), triggerMode(), frameDelay_us(), autoControlParameters( m_hRoot )
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( autoControlMode, "AutoControlMode" );
        locator.bindComponent( autoGainControl, "AutoGainControl" );
        locator.bindComponent( autoExposeControl, "AutoExposeControl" );
        locator.bindComponent( gain_dB, "Gain_dB" );
        locator.bindComponent( offset_pc, "Offset_pc" );
        locator.bindComponent( pixelClock_KHz, "PixelClock_KHz" );
        locator.bindComponent( exposeMode, "ExposeMode" );
        locator.bindComponent( expose_us, "Expose_us" );
        locator.bindComponent( binningMode, "BinningMode" );
        locator.bindComponent( testMode, "TestMode" );
        locator.bindComponent( triggerMode, "TriggerMode", 0, 0 );
        locator.bindComponent( frameDelay_us, "FrameDelay_us" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the auto control mode the device is operated in.
    /**
     *  This property can be used to control the overall behaviour of the algorithms used for performing AEC
     *  (\b A utomatic \b E xpose \b C ontrol) or AGC (\b A utomatic \b G ain \b C ontrol).
     *  This could be done by the device itself thus e.g. even in the analog domain or e.g. by a software
     *  process in the driver. Each method will offer certain advantages and disadvantages and depending on the
     *  application the correct method can be selected.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAutoControlMode.
     *
     *  Every device or even different models belonging to the same device family may support different auto control modes,
     *  thus it's crucial to query the valid modes for each device by reading the properties translation dictionary BEFORE trying
     *  to assign a certain value to this property.
     */
    PropertyIAutoControlMode autoControlMode;
    /// \brief An enumerated integer property, which represents the current mode the AGC (\b A utomatic \b G ain \b C ontrol) is operated in.
    /**
     *  The values used to capture the image, which are directly influenced by an activated AGC or AEC
     *  (e.g. the gain or the exposure time) will be returned as part of the result of the
     *  image request.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAutoGainControl.
     *
     *  \note
     *  This property is not supported by every device. Therefore always call the function
     *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIAutoGainControl autoGainControl;
    /// \brief An enumerated integer property, which represents the current mode the AEC (\b A utomatic \b E xpose \b C ontrol) is operated in.
    /**
     *  The values used to capture the image, which are directly influenced by an activated AGC or AEC
     *  (e.g. the gain or the exposure time) will be returned as part of the result of the
     *  image request.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAutoExposureControl.
     *
     *  \note
     *  This property might not be supported by every device. Therefore always call the function
     *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIAutoExposureControl autoExposeControl;
    /// \brief A float property defining the gain in dB.
    /**
     * The formula for given \c gain_dB is
     * \code
     * gain_x= 10 ^ (gain_dB/20)
     * \endcode
     *
     * \b Example:
     *
     * \code
     * gain_x = 10 ^ (6/20) = 1.995
     * \endcode
     *
     * I.e. increasing the gain setting by 6dB corresponds to factor of 2.
     *
     * The formula for given gain_x is
     * \code
     * gain_dB = 20*log(gain_x) dB
     * \endcode
     *
     * Where: \n
     * \c gain_dB: MATRIX VISION gain value (logarithmic) \n
     * \c gain_x: multiplicative gain \n
     * \c ^: power function \n
     */
    PropertyF gain_dB;
    /// \brief A float property defining the analogue sensor offset in percent of the allowed range (sensor specific).
    /**
     *  This property influences the average grey level when no light reaches the sensor.
     *
     */
#       ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
    /** \b mvBlueFOX \b specific:
     *  Changing its value will have no effect if \b mvIMPACT::acquire::CameraSettingsBlueFOX::offsetAutoCalibration is set to
     *  \b mvIMPACT::acquire::aocOn.
     *
     *  By default
     *  this value will be around 10 (if \b mvIMPACT::acquire::CameraSettingsBlueFOX::offsetAutoCalibration if set
     *  to \b mvIMPACT::acquire::aocOn). This means the average grey value for an image
     *  taken in a completely dark environment will be around 10. When setting
     *  \b mvIMPACT::acquire::CameraSettingsBlueFOX::offsetAutoCalibration to \b mvIMPACT::acquire::aocOff
     *  \b mvIMPACT::acquire::CameraSettingsBlueFOX::offset_pc can be used to modify this value.
     */
#       endif // #ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
    /**
     *  \image html Offset_pc.png
     *  The valid range for this property lies between -100% and +100%, whereas negative values
     *  will shifts the black level towards 0 and positive values to 255.
     *
     *  \note
     *  This property might not be supported by every device. Therefore always call the function
     *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyF offset_pc;
    /// \brief An enumerated integer property defining the pixel clock of the camera sensor in KHz.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraPixelClock.
     *
     *  \note
     *  Changing the pixel clock at runtime will have major impact on the overall behaviour of the
     *  camera. The pixel clock should therefore not be modified constantly during the execution
     *  of the application code. Whenever this property is changed, the next images captured should
     *  be skipped if a device works with an active auto offset calibration controller circuit as then the
     *  control circuits on the camera might need one to three images until all control loops are
     *  locked again.
     *
     *  Every device or even different models belonging to the same device family may support different pixel clocks,
     *  thus it's crucial to query the valid clock modes for each sensor by reading the properties translation dictionary.
     */
    PropertyICameraPixelClock pixelClock_KHz;
    /// \brief An enumerated integer property defining the exposure mode the camera sensor is operated in.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraExposeMode.
     *
     *  \note
     *  Not every device will offer the same options.
     *  Check for valid modes by reading the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyICameraExposeMode::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyICameraExposeMode::getTranslationDictValue.
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyICameraExposeMode::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     */
    PropertyICameraExposeMode exposeMode;
    /// \brief An integer property which defines the exposure time for an image in us.
    /**
     *  \image html Expose_us.png
     *
     */
    PropertyI expose_us;
    /// \brief An enumerated integer property defining the binning mode the camera is operated in.
    /**
     *  By default the no binning will be performed.
     *  \note
     *  Not every camera will support every binning mode. To find out which binning modes
     *  are supported by your camera you can query the properties translation table with
     *  the functions \b mvIMPACT::acquire::PropertyICameraBinningMode::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyICameraBinningMode::getTranslationDictValue
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyICameraBinningMode::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraBinningMode.
     */
    PropertyICameraBinningMode binningMode;
    ///  \brief An enumerated integer property defining the image transmission mode of the camera.
    /**
     *  If this property is set to \b mvIMPACT::acquire::ctmOff the 'normal' image
     *  captured by the cameras sensor will be transmitted. This is the default.
     *  To ensure correct operation the camera might define several test modes where
     *  some kind of well defined pattern will be transmitted.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraTestMode. No every
     *  test mode will be supported by every device.
     */
    PropertyICameraTestMode testMode;
    /// \brief An enumerated integer property which defines what kind of trigger mode shall be used for an image acquisition.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraTriggerMode.
     *
     *  \note
     *  Not every device will support every trigger mode. To find out which trigger modes are supported by a specific
     *  device at runtime the properties translation dictionary should be queried.
     *
     *  \note
     *  Also the sensor specific part of this manual will contain a list of trigger modes that are available for
     *  this specific image sensor.
     */
    PropertyICameraTriggerMode triggerMode;
    /// \brief An integer property defining the delay in us between an external trigger event an the begin of the sensor exposure.
    /**
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyI frameDelay_us;
    /// \brief Provides access to the control parameters for AGC and AEC.
    /**
     *  \note
     *  These settings will only affect the image if \b mvIMPACT::acquire::CameraSettingsBlueDevice::autoGainControl,
     *  \b mvIMPACT::acquire::CameraSettingsBlueDevice::autoExposeControl or both are set to active.
     */
    AutoControlParameters autoControlParameters;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
#ifndef WRAP_JAVA
    /// \brief Provides access to the control parameters for AGC and AEC.
    /**
     *  \note
     *  These settings will only affect the image if \b mvIMPACT::acquire::CameraSettingsBlueDevice::autoGainControl,
     *  \b mvIMPACT::acquire::CameraSettingsBlueDevice::autoExposeControl or both are set to active.
     */
    AutoControlParameters& getAutoControlParameters( void )
    {
        return autoControlParameters;
    }
#endif // #ifndef WRAP_JAVA
};
#   endif // #if !defined(IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION) || !defined(IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION)

#   if !defined(IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION) || !defined(IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION)
//-----------------------------------------------------------------------------
/// \brief A class to configure a HDR (<b>H</b>igh <b>D</b>ynamic <b>R</b>ange) knee point (\b Device specific interface layout only).
/**
 *  \note
 *  Not every device will offer the features provided in this class. Before accessing properties call
 *  the function \b mvIMPACT::acquire::Component::isValid. Right now only the mvBlueFOX-x00wx types
 *  will support the features defined by this class.
 *
 *  \note
 *  Instances of these class can't be constructed directly. Its parameters can
 *  be accessed via an instance of the class \b mvIMPACT::acquire::CameraSettingsBlueFOX or
 *  \b mvIMPACT::acquire::CameraSettingsBlueCOUGAR.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class HDRKneePoint : public ComponentCollection
//-----------------------------------------------------------------------------
{
    friend class HDRControl;
    explicit HDRKneePoint( HOBJ hObj ): ComponentCollection( hObj )
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( HDRControlVoltage_mV, "HDRControlVoltage_mV" );
        locator.bindComponent( HDRExposure_ppm, "HDRExposure_ppm" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property that can be used to define the control voltage in mV for this knee point.
    PropertyI HDRControlVoltage_mV;
    /// \brief An enumerated integer property that can be used to define the exposure time in ppm of the overall exposure time for this knee point.
    PropertyI HDRExposure_ppm;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A class to control the HDR (<b>H</b>igh <b>D</b>ynamic <b>R</b>ange) parameters of a device (\b Device specific interface layout only).
/**
 *  \note
 *  Not every device will offer the features provided in this class. Before accessing properties call
 *  the function \b mvIMPACT::acquire::Component::isValid. Right now only the mvBlueFOX-x00wx, mvBlueFOX-x02dx and
 *  mvBlueCOUGAR-x00wx as well as mvBlueCOUGAR-x02dx types will support the features defined by this class.
 *
 *  \note
 *  Instances of these class can't be constructed directly. Its parameters can
 *  be accessed via an instance of the class \b mvIMPACT::acquire::CameraSettingsBlueFOX or
 *  \b mvIMPACT::acquire::CameraSettingsBlueCOUGAR.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class HDRControl : public ComponentCollection
//-----------------------------------------------------------------------------
{
    friend class CameraSettingsBlueCOUGAR;
    friend class CameraSettingsBlueFOX;
    typedef std::vector<HDRKneePoint*> HDRKneePointContainer;
#       ifndef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        bool                             m_boAvailable;
        HDRKneePointContainer            m_KneePoints;
        HOBJ                             m_HDRControlRoot;
        unsigned int                     m_refCnt;
        explicit ReferenceCountedData() : m_boAvailable( false ), m_KneePoints(), m_HDRControlRoot( INVALID_ID ), m_refCnt( 1 ) {}
        ~ReferenceCountedData()
        {
            const HDRKneePointContainer::size_type HDRKneePointCnt = m_KneePoints.size();
            for( HDRKneePointContainer::size_type h = 0; h < HDRKneePointCnt; h++ )
            {
                delete m_KneePoints[h];
            }
        }
    }* m_pRefData;
#       endif // #ifdef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    //-----------------------------------------------------------------------------
    void bindPublicProperties( void )
    //-----------------------------------------------------------------------------
    {
        if( m_pRefData->m_HDRControlRoot != INVALID_ID )
        {
            ComponentLocator locator( m_pRefData->m_HDRControlRoot );
            locator.bindComponent( HDREnable, "HDREnable" );
            locator.bindComponent( HDRMode, "HDRMode" );
            locator.bindComponent( HDRKneePointCount, "HDRKneePointCount" );
        }
    }
    //-----------------------------------------------------------------------------
    explicit HDRControl( HOBJ hObj ): ComponentCollection( hObj ), m_pRefData( new ReferenceCountedData() )
        //-----------------------------------------------------------------------------
    {
        ComponentLocator locator( m_hRoot );
        HOBJ hRoot = locator.findComponent( "HDRControl" );
        if( hRoot != INVALID_ID )
        {
            m_hRoot = hRoot;
            m_pRefData->m_HDRControlRoot = m_hRoot;
            bindPublicProperties();
            locator.bindSearchBase( locator.searchbase_id(), "HDRControl" );
            // create the HDR knee point objects for this setting
            Component it;
            locator.bindComponent( it, "HDRKneePoints" );
            if( it.isValid() )
            {
                it = it.firstChild();
                while( it.isValid() )
                {
                    m_pRefData->m_KneePoints.push_back( new HDRKneePoint( it.hObj() ) );
                    ++it;
                }
            }
            m_pRefData->m_boAvailable = true;
        }
    }
public:
    /// \brief Copy constructor.
    /**
     *  Creates a new object from an existing device object. Keep in mind that this new object
     *  will provide access to the very same hardware and therefore you might as well use the original
     *  reference. This constructor is only provided for internal reference counting to guarantee correct operation of the
     *  objects of this class under all platforms and languages.
     */
    explicit HDRControl( const HDRControl& src ) : ComponentCollection( src.m_hRoot ), m_pRefData( src.m_pRefData ), HDREnable( src.HDREnable ),
        HDRMode( src.HDRMode ), HDRKneePointCount( src.HDRKneePointCount )
    {
        ++( m_pRefData->m_refCnt );
    }
    ~HDRControl()
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::HDRControl objects.
    HDRControl& operator=( const HDRControl& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            // inc. the NEW reference count
            ++( m_pRefData->m_refCnt );
            bindPublicProperties();
        }
        return *this;
    }
    /// \brief This function should be called to check if this device offers HDR (<b>H</b>igh <b>D</b>ynamic <b>R</b>ange) control parameters.
    /**
     *  \return
     *  - true if the device offers the features defined by this object.
     *  - false otherwise
     */
    bool isAvailable( void ) const
    {
        return m_pRefData->m_boAvailable;
    }
    /// \brief Returns a reference to a set of user definable parameters to configure a HDR (<b>H</b>igh <b>D</b>ynamic <b>R</b>ange) knee point.
    /**
     *  Use the property \b mvIMPACT::acquire::HDRControl::HDRKneePointCount to find out how many knee points are available
     *  or to change the number of knee points.
     *
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr is invalid(too large) an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \return A reference to a set of user definable parameters to configure a HDR (<b>H</b>igh <b>D</b>ynamic <b>R</b>ange) knee point.
     */
    HDRKneePoint& getHDRKneePoint(
        /// [in] The number of the knee point to be returned
        unsigned int nr ) const
    {
        return *( m_pRefData->m_KneePoints.at( nr ) );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property which can be used to enable/disable HDR (<b>H</b>igh <b>D</b>ynamic <b>R</b>ange) mode.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean HDREnable;
    /// \brief An enumerated integer property which can be used to configure the HDR (<b>H</b>igh <b>D</b>ynamic <b>R</b>ange) mode to work with.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraHDRMode.
     */
    PropertyICameraHDRMode HDRMode;
    /// \brief An integer property to define the number of knee points to work with when \b mvIMPACT::acquire::HDRControl::HDRMode is set to \b mvIMPACT::acquire::cHDRmUser.
    PropertyI HDRKneePointCount;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #if !defined(IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION) || !defined(IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION)

#   ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief \b mvBlueFOX related camera settings(\b Device specific interface layout only).
/**
 *  This class contains properties to control the way the image sensor of the
 *  \b mvBlueFOX behaves.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraSettingsBlueFOX : public CameraSettingsBlueDevice
//-----------------------------------------------------------------------------
{
    HDRControl HDRControl_;
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::CameraSettingsBlueFOX object.
    explicit CameraSettingsBlueFOX(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : CameraSettingsBlueDevice( pDev, settingName ), HDRControl_( m_hRoot ),
        offsetAutoCalibration(), offsetCorrection_pc(), offsetAutoBlackLevel(),
        offsetAutoBlackSpeed(), lineDelay_clk(), advancedOptions(),
        flashToExposeDelay_us(), flashMode(), flashType(), shutterMode(),
        triggerSource(), sensorTimingMode()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( offsetAutoCalibration, "OffsetAutoCalibration" );
        locator.bindComponent( offsetCorrection_pc, "OffsetCorrection_pc" );
        locator.bindComponent( offsetAutoBlackLevel, "OffsetAutoBlackLevel" );
        locator.bindComponent( offsetAutoBlackSpeed, "OffsetAutoBlackSpeed" );
        locator.bindComponent( lineDelay_clk, "LineDelay_clk" );
        locator.bindComponent( advancedOptions, "AdvancedOptions" );
        locator.bindComponent( flashToExposeDelay_us, "FlashToExposeDelay_us" );
        locator.bindComponent( flashMode, "FlashMode" );
        locator.bindComponent( flashType, "FlashType" );
        locator.bindComponent( shutterMode, "ShutterMode" );
        locator.bindComponent( triggerSource, "TriggerSource" );
        locator.bindComponent( sensorTimingMode, "SensorTimingMode" );
    }
    /// \brief Returns the \b mvIMPACT::acquire::HDRControl object associated with this setting.
    HDRControl& getHDRControl( void )
    {
        return HDRControl_;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the offset calibration mode.
    /**
     *  If this property is set to \b mvIMPACT::acquire::aocOff
     *  the offset can be adjusted manually by modifying the \b mvIMPACT::acquire::CameraSettingsBlueFOX::offset_pc and
     *  mvIMPACT::acquire::CameraSettingsBlueFOX::offsetCorrection_pc properties.
     *
     *  If set to \b mvIMPACT::acquire::aocOn the offset is approx. 10. That means,
     *  that the medium pixel count is 10, in case no light is falling on the sensor.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAutoOffsetCalibration.
     */
    PropertyIAutoOffsetCalibration offsetAutoCalibration;
    /// \brief A float property defining and \b additional analogue sensor offset in percent of the allowed range (sensor specific) \b per \b color \b channel.
    /**
     *  Together with value of the property \b mvIMPACT::acquire::CameraSettingsBlueDevice::offset_pc this property influences the average grey level
     *  when no light reaches the sensor.
     *
     *  This property stores 4 values.
     *  - The value at index 0 applies to the green component of the red-green rows of the bayer pattern
     *  - The value at index 1 applies to the red component of the bayer pattern
     *  - The value at index 2 applies to the green component of the blue-green rows of the bayer pattern
     *  - The value at index 3 applies to the blue component of the bayer pattern
     *
     *  \note
     *  This property might not be supported by every device. Therefore always call the function
     *  \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  In addition to that this property must be enabled explicitly by setting the advanced option bit
     *  \b mvIMPACT::acquire::daoEnablePerChannelOffsetCorrection of the property
     *  \b mvIMPACT::acquire::CameraSettingsBlueFOX::advancedOptions.
     *  \sa
     *  \b mvIMPACT::acquire::CameraSettingsBlueDevice::offset_pc
     */
    PropertyF offsetCorrection_pc;
    /// \brief An integer property defining the digital value assumed as black.
    /**
     *  Modifying this property in rare cases might be useful to achieve a higher dynamic range for noise close to the black
     *  level.
     *
     *  \note
     *  As the \b mvBlueFOX internally works with a 10 bit analog to digital conversion increasing this
     *  value by 4 will result in a black level increased by about 1 in the resulting 8 bit raw image
     *  delivered from the camera.
     */
    PropertyI offsetAutoBlackLevel;
    /// \brief An enumerated integer property defining the speed of the auto offset calibration circuit.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBlueFOXOffsetAutoBlackSpeed.
     */
    PropertyIBlueFOXOffsetAutoBlackSpeed offsetAutoBlackSpeed;
    /// \brief An integer property defining the delay in clocks between two lines.
    /**
     *  Can be used to slow down the image readout the reduce the peak bandwidth required
     *  for the transfer.
     */
    PropertyI lineDelay_clk;
    /// \brief An enumerated integer property defining a collection of advanced options that can be enabled or disabled.
    /**
     *  This property is highly sensor dependent. Each sensor might offer a different sub set of the options offered.
     *  Only experienced users should work with this feature.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceAdvancedOptions.
     */
    PropertyIDeviceAdvancedOptions advancedOptions;
    /// \brief An integer property defining the delay in us between the start of the flash signal output and the beginning of the expose period of the image sensor.
    /**
     *  \note
     *  This property is mainly provided for compatibility reasons. Previous versions of the
     *  \b mvBlueFOX driver produced a fixed delay of about 300 us between the beginning of the
     *  flash signal creation and the beginning of the sensors expose period. Newer versions of the
     *  driver do \b NOT produce this delay anymore which might cause a different illumination
     *  for applications using very intensive, short flash and expose times. Applications relying on
     *  the delay introduced in older driver versions should set this property to
     *  '300' by calling \b mvIMPACT::acquire::PropertyI::write.
     *
     *  \sa
     *  \b mvIMPACT::acquire::CameraSettingsBlueDevice::expose_us
     */
    PropertyI flashToExposeDelay_us;
    /// \brief An enumerated integer property defining the behaviour of the flash output of the camera (if available).
    /**
     *  If this property is set the cameras flash output (if available) will be pulsed
     *  during the exposure period of the sensor. In that case the pulse width will be equal
     *  to the exposure time.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraFlashMode.
     *
     *  \sa
     *  \b mvIMPACT::acquire::CameraSettingsBlueFOX::flashToExposeDelay_us
     */
    PropertyICameraFlashMode flashMode;
    /// \brief An enumerated integer property defining the type of the flash output of the camera (if available).
    /**
     *  Depending of the camera sensor type (\a rolling shutter or \a frame \a shutter
     *  there well be different modes available
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraFlashType.
     */
    PropertyICameraFlashType flashType;
    /// \brief An enumerated integer property defining the shutter mode to use.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraShutterMode.
     */
    PropertyICameraShutterMode shutterMode;
    /// \brief An enumerated integer property defining where the trigger signal is expected to occur.
    /**
     *  When working with hardware generated signals via \b mvIMPACT::acquire::RTCtrProgram objects
     *  this property should be set to \b mvIMPACT::acquire::ctsRTCtrl as otherwise
     *  the program will not affect the behaviour of the camera.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraTriggerSource.
     */
    PropertyICameraTriggerSource triggerSource;
    /// \brief An enumerated integer property defining the current image sensor timing mode.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBlueFOXSensorTiming.
     */
    PropertyIBlueFOXSensorTiming sensorTimingMode;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION

#   ifndef IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief \b mvBlueCOUGAR related camera settings (\b Device specific interface layout only).
/**
 *  This class contains properties to control the way the image sensor(s) of the
 *  \b mvBlueCOUGAR behaves.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraSettingsBlueCOUGAR : public CameraSettingsBlueDevice
//-----------------------------------------------------------------------------
{
    typedef std::vector<TriggerControl*> TriggerControlVector;
    TriggerControlVector m_triggerControls;
    HDRControl HDRControl_;
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::CameraSettingsBlueCOUGAR object.
    explicit CameraSettingsBlueCOUGAR(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : CameraSettingsBlueDevice( pDev, settingName ),
        m_triggerControls(), HDRControl_( m_hRoot ),
        triggerInterface(), triggerSource(), acquisitionBurstFrameCount()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( frameRate_Hz, "FrameRate_Hz" );
        locator.bindComponent( partialScanMode, "PartialScanMode" );
        locator.bindComponent( triggerInterface, "TriggerInterface" );
        locator.bindComponent( triggerSource, "TriggerSource" );
        locator.bindComponent( acquisitionBurstFrameCount, "AcquisitionBurstFrameCount" );
        if( locator.findComponent( "TriggerControls" ) != INVALID_ID )
        {
            locator.bindSearchBase( locator.searchbase_id(), "TriggerControls" );
            Component it( locator.searchbase_id() );
            it = it.firstChild();
            while( it.isValid() )
            {
                m_triggerControls.push_back( new TriggerControl( it ) );
                ++it;
            }
        }
    }
    virtual ~CameraSettingsBlueCOUGAR()
    {
        TriggerControlVector::size_type vSize = m_triggerControls.size();
        for( TriggerControlVector::size_type i = 0; i < vSize; i++ )
        {
            delete m_triggerControls[i];
        }
    }
    /// \brief Returns the number of \b mvIMPACT::acquire::TriggerControls available for this device.
    /**
     *  This might be 0 if the device either does not support this feature.
     */
    unsigned int getTriggerControlCount( void ) const
    {
        return static_cast<unsigned int>( m_triggerControls.size() );
    }
    /// \brief Returns a const pointer to a \b mvIMPACT::acquire::TriggerControl object.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr references an invalid pin an STL out_of_range exception
     *  will be thrown.
     *  \endif
     *
     *  \note
     *  The features of each \b mvIMPACT::acquire::TriggerControl will only be visible and thus available,
     *  when \b mvIMPACT::acquire::CameraSettingsBlueCOUGAR::triggerInterface
     *  is set to \b mvIMPACT::acquire::dtiAdvanced.
     */
    const TriggerControl* triggerControl(
        /// [in] The number of the trigger control
        unsigned int nr ) const
    {
        return m_triggerControls.at( nr );
    }
    /// \brief Returns a const pointer to a \b mvIMPACT::acquire::TriggerControl object or NULL if the name passed to the function does not specify a valid trigger control.
    const TriggerControl* triggerControl(
        /// [in] The name of the trigger control
        const std::string& name ) const
    {
        const TriggerControlVector::size_type cnt = m_triggerControls.size();
        for( TriggerControlVector::size_type i = 0; i < cnt; i++ )
        {
            const TriggerControl* p = triggerControl( static_cast<unsigned int>( i ) );
            if( p->getDescription() == name )
            {
                return p;
            }
        }
        return 0;
    }
    /// \brief Returns the \b mvIMPACT::acquire::HDRControl object associated with this setting.
    HDRControl& getHDRControl( void )
    {
        return HDRControl_;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief A float property defining the frame rate (in Hz) this device shall use to transfer images.
    /**
     *  Depending on other parameters the desired frame rate might not be achievable (e.g. if the exposure time
     *  is higher than the frame period. In that case the device will automatically reduce the frame rate.
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyF frameRate_Hz;
    /// \brief An enumerated integer property defining whether partial scan mode shall be used or not.
    /**
     *  This property currently is only available for \b mvBlueCOUGAR-S devices. When partial scan mode is active, the
     *  frame rate can no longer be controlled be the property \b mvIMPACT::acquire::CameraSettingsBlueCOUGAR::frameRate_Hz.
     *  The device will always transmit frames as fast as possible instead.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean partialScanMode;
    /// \brief An enumerated integer property defining which view of the trigger interface to use.
    /**
     *  This property mainly switches the visibility of trigger the different trigger interfaces. After applying changes to
     *  this property all trigger related features might have a different visibility. However the documentation will state
     *  what features are available in which mode.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceTriggerInterface.
     */
    PropertyIDeviceTriggerInterface triggerInterface;
    /// \brief An enumerated integer property defining where the trigger signal is expected to occur.
    /**
     *  When working with hardware generated signals via \b mvIMPACT::acquire::RTCtrProgram objects
     *  this property should be set to \b mvIMPACT::acquire::ctsRTCtrl as otherwise
     *  the program will not affect the behaviour of the camera.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraTriggerSource.
     *
     *  \note
     *  This feature will only be visible and thus available, when \b mvIMPACT::acquire::CameraSettingsBlueCOUGAR::triggerInterface
     *  is set to \b mvIMPACT::acquire::dtiStandard.
     */
    PropertyICameraTriggerSource triggerSource;
    /// \brief A 64-bit integer property defining the number of frames to acquire for each FrameBurstStart trigger.
    /**
    *  \note
    *  This feature will only be taken into account if the \c FrameBurstStart trigger is active when \b mvIMPACT::acquire::CameraSettingsBlueCOUGAR::triggerInterface
    *  is set to \b mvIMPACT::acquire::dtiAdvanced.
    */
    PropertyI64 acquisitionBurstFrameCount;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION

#   ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief A class to access frame grabber related camera settings(\b Device specific interface layout only).
/**
 *  This class contains properties to control the way the a frame grabber
 *  behaves in connection with the connected camera.
 *
 *  \note
 *  Not every frame grabber will support every property defined in this class. Please
 *  refer to the description of the individual properties and make heavy use of the
 *  function \b mvIMPACT::acquire::Component::isValid in order to check whether
 *  a property is available for the device.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraSettingsFrameGrabber : public CameraSettingsBase
//-----------------------------------------------------------------------------
{
    typedef std::vector<TriggerControl*> TriggerControlVector;
    TriggerControlVector m_triggerControls;
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::CameraSettingsFrameGrabber object.
    explicit CameraSettingsFrameGrabber(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& settingName = "Base" ) : CameraSettingsBase( pDev, settingName ),
        type(), aoiMode(), gain_dB(), offset_mV(), scanClock(), triggerMode(), softwareTriggerPeriod_ms(),
        serialPortBaudrate(), interlacedMode(), acquisitionField(), scanRateMode(), scanRate_kHz(),
        luminance_pc(), saturation_pc(), hue_pc(), contrast_pc(), lineCounter()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( type, "Type" );
        locator.bindComponent( aoiMode, "AoiMode" );
        locator.bindComponent( gain_dB, "Gain_dB" );
        locator.bindComponent( offset_mV, "Offset_mV" );
        locator.bindComponent( scanClock, "ScanClock" );
        locator.bindComponent( triggerMode, "TriggerMode", 0, 0 );
        locator.bindComponent( softwareTriggerPeriod_ms, "SoftwareTriggerPeriod_ms" );
        locator.bindComponent( serialPortBaudrate, "SerialPortBaudRate" );
        locator.bindComponent( interlacedMode, "InterlacedMode" );
        locator.bindComponent( acquisitionField, "AcquisitionField" );
        locator.bindComponent( scanRateMode, "ScanRateMode" );
        locator.bindComponent( scanRate_kHz, "ScanRate_kHz" );
        locator.bindComponent( luminance_pc, "Luminance_pc" );
        locator.bindComponent( saturation_pc, "Saturation_pc" );
        locator.bindComponent( hue_pc, "Hue_pc" );
        locator.bindComponent( contrast_pc, "Contrast_pc" );
        locator.bindComponent( lineCounter, "LineCounter" );
        if( locator.findComponent( "TriggerControls" ) != INVALID_ID )
        {
            locator.bindSearchBase( locator.searchbase_id(), "TriggerControls" );
            Component it( locator.searchbase_id() );
            if( it.isValid() )
            {
                it = it.firstChild();
                while( it.isValid() )
                {
                    m_triggerControls.push_back( new TriggerControl( it ) );
                    ++it;
                }
            }
        }
    }
    virtual ~CameraSettingsFrameGrabber()
    {
        TriggerControlVector::size_type vSize = m_triggerControls.size();
        for( TriggerControlVector::size_type i = 0; i < vSize; i++ )
        {
            delete m_triggerControls[i];
        }
    }
    /// \brief Returns the number of \b mvIMPACT::acquire::TriggerControls available for this device.
    /**
     *  This might be 0 if the device either does not support this feature.
     */
    unsigned int getTriggerControlCount( void ) const
    {
        return static_cast<unsigned int>( m_triggerControls.size() );
    }
    /// \brief Returns a const pointer to a \b mvIMPACT::acquire::TriggerControl object.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If \a nr references an invalid pin an STL out_of_range exception
     *  will be thrown.
     *  \endif
     */
    const TriggerControl* triggerControl(
        /// [in] The number of the trigger control
        unsigned int nr ) const
    {
        return m_triggerControls.at( nr );
    }
    /// \brief Returns a const pointer to a \b mvIMPACT::acquire::TriggerControl object or NULL if the name passed to the function does not specify a valid trigger control.
    const TriggerControl* triggerControl(
        /// [in] The name of the trigger control
        const std::string& name ) const
    {
        const TriggerControlVector::size_type cnt = m_triggerControls.size();
        for( TriggerControlVector::size_type i = 0; i < cnt; i++ )
        {
            const TriggerControl* p = triggerControl( static_cast<unsigned int>( i ) );
            if( p->getDescription() == name )
            {
                return p;
            }
        }
        return 0;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the camera description used for the image acquisition.
    /**
     *  This property \b ALWAYS defines a translation dictionary containing a string representation
     *  and a numerical value for the camera descriptions available for the device. The string
     *  representation of the camera description will be built from the property name of the class this
     *  camera description belongs to (e.g. \a 'Standard', \a 'NonStandard' or \a 'CameraLink') and
     *  the name of the camera description itself. Assuming a the device can handle standard
     *  video cameras and a description for a camera named \a 'MyCCIRCamera' will therefore
     *  add \a 'Standard_MyCCIRCamera' and a unique numerical representation to the properties
     *  translation dictionary.
     */
    PropertyI type;
    /// \brief An enumerated integer property defining the used AOI mode for the image capture.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraAoiMode.
     */
    PropertyICameraAoiMode aoiMode;
    /// \brief A float property defining the gain in dB.
    /**
     *  This is the gain applied during the analogue to digital conversion inside the frame
     *  grabber, not applied inside the camera.
     *
     *  * The formula for given \c gain_dB is
     *  \code
     *  gain_x= 10 ^ (gain_dB/20)
     *  \endcode
     *
     *  \b Example:
     *
     *  \code
     *  gain_x = 10 ^ (6/20) = 1.995
     *  \endcode
     *
     *  I.e. increasing the gain setting by 6dB corresponds to factor of 2.
     *
     *  The formula for given gain_x is
     *  \code
     *  gain_dB = 20*log(gain_x) dB
     *  \endcode
     *
     *  Where: \n
     *  \c gain_dB: MATRIX VISION gain value (logarithmic) \n
     *  \c gain_x: multiplicative gain \n
     *  \c ^: power function \n
     *
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyF gain_dB;
    /// \brief An integer property defining the offset in milli-Volt.
    /**
     *  This is the analogue offset applied during the analogue to digital conversion inside the frame
     *  grabber, not applied inside the camera.
     *
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyI offset_mV;
    /// \brief An enumerated integer property defining the scan clock mode used for the current acquisition.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TScanClock.
     *
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception! Digital frame grabbers will however \b NOT support
     *  this property.
     */
    PropertyIScanClock scanClock;
    /// \brief An enumerated integer property defining the behaviour of the frame grabbers trigger input.
    /**
     *  \note
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceTriggerMode. However
     *  not every device will offer all these trigger modes but a subset of them. Valid trigger modes therefore
     *  can be found by reading the properties translation dictionary.
     *
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyIDeviceTriggerMode triggerMode;
    /// \brief An integer property defining the software simulated trigger period.
    /**
     *  When \b mvIMPACT::acquire::CameraSettingsFrameGrabber::triggerMode is set to
     *  \b mvIMPACT::acquire::dtmPeriodically this property defines the
     *  interval between two consecutive external trigger events simulated by the driver.
     *
     *  Currently this property is only available for \b mvTITAN and \b mvGAMMA frame grabbers.
     *
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyI softwareTriggerPeriod_ms;
    /// \brief An enumerated integer property defining the baud rate of the serial communication port between frame grabber and camera.
    /**
     *  Currently this property is only available for CameraLink&reg; frame grabbers.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraSerialPortBaudRate.
     *
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyICameraSerialPortBaudRate serialPortBaudrate;
    /// \brief An enumerated integer property defining how the image from the camera shall be captured.
    /**
     *  If a video signal is transmitted to the capture device in an interlaced format, the device
     *  can either capture each individual frame, or merge two frames together into a complete image.
     *
     *  This property will be invisible when the camera description selected by the property
     *  \b mvIMPACT::acquire::CameraSettingsFrameGrabber::type does define it property
     *  \b mvIMPACT::acquire::CameraDescriptionBase::interlacedType to be \b mvIMPACT::acquire::citNone
     *  as the decision whether an interlaced image shall be reconstructed from frames or left
     *  as individual frame is redundant if the video source transmits full frames only.
     *
     *  The visibility of a property can be checked by calling \b mvIMPACT::acquire::Component::isVisible
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TInterlacedMode.
     *
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyIInterlacedMode interlacedMode;
    /// \brief An enumerated integer property defining which frame(s) of an interlaced video signal will be digitised or triggers the start of the acquisition.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAcquisitionField.
     *
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyIAcquisitionField acquisitionField;
    /// \brief An enumerated integer property defining the scan rate mode for this setting.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDeviceScanRateMode.
     *
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyIDeviceScanRateMode scanRateMode;
    /// \brief An integer property defining the current scan frequency of the capture device.
    /**
     *  This property is only visible if the \b mvIMPACT::acquire::CameraSettingsFrameGrabber::scanRateMode
     *  property is \b NOT in an auto mode.
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyI scanRate_kHz;
    /// \brief An integer property defining the luminance value to be applied to the image data by the frame grabber in per cent.
    /**
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyI luminance_pc;
    /// \brief An integer property defining the saturation value to be applied to the image data by the frame grabber in per cent.
    /**
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyI saturation_pc;
    /// \brief An integer property defining the hue value to be applied to the image data by the frame grabber in per cent.
    /**
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyI hue_pc;
    /// \brief An integer property defining the contrast value to be applied to the image data by the frame grabber in per cent.
    /**
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyI contrast_pc;
    /// \brief An enumerated integer property defining the way line counter information is handled by the device.
    /**
     *  This is interesting for line scan camera applications.
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TLineCounter.
     *
     *  \note
     *  This property will not be available for every frame grabber, so before using it, check
     *  if the property is available at all by calling \b mvIMPACT::acquire::Component::isValid. Accessing
     *  an invalid property will raise an exception!
     */
    PropertyILineCounter lineCounter;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A base class to describe a camera (\b Device specific interface layout only) connected to a frame grabber.
/**
 *  A camera description object provides an abstract way to prepare the capture
 *  device (e.g. a frame grabber) for the connected imaging device (e.g. a camera).
 *
 *  By selecting one of the available camera descriptions the underlying hardware
 *  will use the information provided in the camera description to prepare the
 *  image capture. Therefore it is crucial to select a camera description
 *  that matches the connected video signal as close as possible. If no description
 *  for the camera connected to a frame grabber is available a new description
 *  should be generated from one of the existing ones. This can be achieved by calling
 *  the function \b mvIMPACT::acquire::CameraDescriptionBase::copyDescription. A new
 *  camera description with the name that is passed to the function will be created.
 *
 *  \note
 *  The name must be unique. There can't be two descriptions with the same name
 *  belonging to the same generic class (i.e. \a 'Standard' or \a 'CameraLink'&reg;). However
 *  it's perfectly legal to have a camera description for standard analogue video signals
 *  and one for e.g. CameraLink&reg; signals with the same name.
 *
 *  This new description will be an exact copy of the one the copy function has been
 *  executed for. After creation this description can be selected e.g. by setting the
 *  property \b mvIMPACT::acquire::CameraSettingsFrameGrabber::type to the name of the
 *  new description.
 *
 *  \note
 *  Please note that the name passed to the property \b mvIMPACT::acquire::CameraSettingsFrameGrabber::type
 *  does \b NOT exactly correspond to the name assigned to the new camera description.
 *  It is a combination of the class the camera is belonging to (e.g. \a 'Standard') and the actual name.
 *  So to select a camera description the name must be build from the return value of a call to
 *  \b mvIMPACT::acquire::CameraDescriptionBase::getClassName, an underscore ('_') and the
 *  actual name of the description: &lt;class name&gt;_&lt;desc. name&gt;
 *
 *  Example: For a standard description with the name \a 'MyCam' the full name would be \a 'Standard_MyCam'.
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  #include <mvIMPACT_CPP/mvIMPACT_acquire.h>
 *  #include <iostream>
 *
 *  using namespace std;
 *
 *  //-----------------------------------------------------------------------------
 *  int main( int argc, char* argv[] )
 *  //-----------------------------------------------------------------------------
 *  {
 *    mvIMPACT::acquire::DeviceManager devMgr;
 *    mvIMPACT::acquire::Device* pDev = devMgr[0];
 *    if( !pDev )
 *    {
 *      cout << "No device found" << endl;
 *      return 1;
 *    }
 *
 *    try
 *    {
 *      // the next line will raise an exception if this device does not
 *      // support camera descriptions (e.g. if it is a USB camera rather than a frame grabber)
 *      mvIMPACT::acquire::CameraDescriptionManager cdm( pDev );
 *      mvIMPACT::acquire::CameraDescriptionStandard* pCam = cdm.cameraDescriptionStandard( "Generic" );
 *      pCam->copyDescription( "MyCam" );
 *      // Get access to the newly created description
 *      mvIMPACT::acquire::CameraDescriptionStandard* pMyCam = cdm.cameraDescriptionStandard( "MyCam" );
 *      // Modify something
 *      pMyCam->videoStandard.write( vsRS170 );
 *      pMyCam->scanStandard.write( ssITU601 );
 *      // now save the description to make it available in all future sessions
 *      pMyCam->exportDescription();
 *      // select the newly created description
 *      mvIMPACT::acquire::CameraSettingsFrameGrabber cs( pDev );
 *      // the name for this property is always a combination of the class the camera
 *      // description is belonging to and the actual name:
 *      cs.type.writeS( pMyCam->getClassName() + "_" + pMyCam->name.read() );
 *    }
 *    catch( const ImpactAcquireException& e )
 *    {
 *      cout << "An exception occurred: " << e.getErrorString() << endl;
 *      return 1;
 *    }
 *    return 0;
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  import mvIMPACT.acquire.*;
 *
 *  //-----------------------------------------------------------------------------
 *  public class CameraDescriptionManagerExample
 *  //-----------------------------------------------------------------------------
 *  {
 *    //=============================================================================
 *    //=== Static member functions =================================================
 *    //=============================================================================
 *    static
 *    {
 *      try
 *      {
 *        System.loadLibrary( "mvIMPACT_Acquire.java" );
 *      }
 *      catch( UnsatisfiedLinkError e )
 *      {
 *        System.err.println( "Native code library failed to load. Make sure the 'mvIMPACT_Acquire.java' library can be found in the systems search path.\n" + e );
 *        System.exit( 1 );
 *      }
 *    }
 *
 *    //-----------------------------------------------------------------------------
 *    public static void main( String[] args )
 *    //-----------------------------------------------------------------------------
 *    {
 *      DeviceManager devMgr = new DeviceManager();
 *      Device pDev = mvIMPACT.acquire.examples.helper.DeviceAccess.getDeviceFromUserInput( devMgr );
 *      if( pDev == null )
 *      {
 *        System.out.print( "Unable to continue!" );
 *        mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *        System.exit( 1 );
 *      }
 *
 *      System.out.println( "Initialising the device. This might take some time..." );
 *      try
 *      {
 *        pDev.open();
 *      }
 *      catch( ImpactAcquireException e )
 *      {
 *        // this e.g. might happen if the same device is already opened in another process...
 *        System.out.println( "An error occurred while opening device " + pDev.getSerial().read() +
 *                            "(error code: " + e.getMessage() + ")." );
 *        mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *        System.exit( 1 );
 *      }
 *
 *      try
 *      {
 *        // the next line will raise an exception if this device does not
 *        // support camera descriptions (e.g. if it is a USB camera rather than a frame grabber)
 *        CameraDescriptionManager cdm = new CameraDescriptionManager( pDev );
 *        CameraDescriptionStandard pCam = cdm.cameraDescriptionStandard( "Generic" );
 *        pCam.copyDescription( "MyCam" );
 *        // Get access to the newly created description
 *        CameraDescriptionStandard pMyCam = cdm.cameraDescriptionStandard( "MyCam" );
 *        // Modify something
 *        pMyCam.getVideoStandard().write( TVideoStandard.vsRS170 );
 *        pMyCam.getScanStandard().write( TScanStandard.ssITU601 );
 *        // now save the description to make it available in all future sessions
 *        pMyCam.exportDescription();
 *        // select the newly created description
 *        CameraSettingsFrameGrabber cs = new CameraSettingsFrameGrabber( pDev );
 *        // the name for this property is always a combination of the class the camera
 *        // description is belonging to and the actual name:
 *        cs.getType().writeS( pMyCam.getClassName() + "_" + pMyCam.getName().read() );
 *      }
 *      catch( ImpactAcquireException e )
 *      {
 *        System.out.println( "An error occurred: " + e.getMessage() + "." );
 *        mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *        System.exit( 1 );
 *      }
 *    }
 *  }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 * try:
 *   # the next line will raise an exception if this device does not
 *   # support camera descriptions (e.g. if it is a USB camera rather than a frame grabber)
 *   cdm = acquire.CameraDescriptionManager(pDev)
 *   pCam = cdm.cameraDescriptionStandard("Generic")
 *   pCam.copyDescription("MyCam")
 *   # Get access to the newly created description
 *   pMyCam = cdm.cameraDescriptionStandard("MyCam")
 *   # Modify something
 *   pMyCam.videoStandard.write(acquire.vsRS170)
 *   pMyCam.scanStandard.write(acquire.ssITU601)
 *   # now save the description to make it available in all future sessions
 *   pMyCam.exportDescription()
 *   # select the newly created description
 *   cs = acquire.CameraSettingsFrameGrabber(pDev)
 *   # the name for this property is always a combination of the class the camera
 *   # description is belonging to and the actual name:
 *   cs.type.writeS(pMyCam.getClassName() + "_" + pMyCam.name.readS())
 * except Exception as e:
 *   print("An exception occurred: " + e.getErrorString())
 * \endcode
 * \endif
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraDescriptionBase : public ComponentCollection
//-----------------------------------------------------------------------------
{
    HDRV m_hDrv;
protected:
    explicit CameraDescriptionBase( HDRV hDrv, HLIST hList ) : ComponentCollection( hList ), m_hDrv( hDrv ), name(),
        videoOutput(), interlacedType(), aoiHeight(), aoiStartX(), aoiStartY(), aoiWidth()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( name, "Name" );
        locator.bindComponent( videoOutput, "VideoOutput" );
        locator.bindComponent( interlacedType, "InterlacedType" );
        locator.bindSearchBase( locator.searchbase_id(), "ActiveVideoAoi" );
        locator.bindComponent( aoiHeight, "H" );
        locator.bindComponent( aoiStartX, "X" );
        locator.bindComponent( aoiStartY, "Y" );
        locator.bindComponent( aoiWidth, "W" );
    }
public:
    /// \brief Returns the class this description is belonging to.
    /**
     *  \return The class this description is belonging to.
     */
    std::string getClassName( void ) const
    {
        return ComponentList( m_hRoot ).contentDescriptor();
    }
    /// \brief Creates a new camera description list as a copy of the current one.
    /**
     *  This function can be used to create a new camera description list. It will create
     *  a deep copy of the properties referenced by this camera description and will append the new description
     *  to the list of camera descriptions.
     *
     *  \note
     *  This will \b NOT store the new description permanently. After the driver has been
     *  closed, this data will be lost. To store the new list in a way that it will be available
     *  the next time the driver/device is opened again, \b mvIMPACT::acquire::CameraDescriptionBase::exportDescription must
     *  be called with the handle of the newly created description after this function.
     *  \sa
     *  \b mvIMPACT::acquire::CameraDescriptionBase::exportDescription, \n
     *  \b mvIMPACT::acquire::CameraDescriptionBase::importDescription
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - \b mvIMPACT::acquire::DEV_INPUT_PARAM_INVALID if new name matches a description that is already
     *  existing.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int copyDescription(
        /// [in] The name for the newly created camera description. This name
        /// \b MUST NOT match a description already existing.
        const std::string& newName ) const
    {
        return DMR_CopyCameraDescription( m_hDrv, m_hRoot, newName.c_str() );
    }
    /// \brief Stores the current camera description on disc.
    /**
     *  This function can be used to store the current settings of a camera description
     *  permanently so that the next time the driver is initialized these settings are restored.
     *
     *  When exporting a camera description a file in XML format will be written to disc. On
     *  Windows&reg; camera descriptions will be stored under
     * \code
     *  %PUBLIC%/Documents/MATRIX VISION/mvIMPACT Acquire/CameraFiles
     * \endcode
     *  or
     * \code
     *  %MVIMPACT_ACQUIRE_DATA_DIR%/CameraFiles
     * \endcode
     *  which will point to the same folder), on Linux&reg; this directory will be
     *  \code
     *  /etc/matrix-vision/mvimpact-acquire/camerafiles
     *  \endcode
     *  while under other platforms these files will end up in the current working directory. This behaviour can be modified
     *  by writing the property \b mvIMPACT::acquire::Device::customDataDirectory before initialising the
     *  device.
     *
     *  \sa
     *  \b mvIMPACT::acquire::CameraDescriptionBase::copyDescription, \n
     *  \b mvIMPACT::acquire::CameraDescriptionBase::importDescription
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int exportDescription( void ) const
    {
        return DMR_ExportCameraDescription( m_hDrv, m_hRoot );
    }
    /// \brief Updates a camera description with the data stored in a previous session or with the original default data.
    /**
     *  When importing a camera description the device driver will try to retrieve the parameters
     *  needed from an XML file. On Windows&reg; camera descriptions MUST be stored under
     * \code
     *  %PUBLIC%/Documents/MATRIX VISION/mvIMPACT Acquire/CameraFiles
     * \endcode
     *  or
     * \code
     *  %MVIMPACT_ACQUIRE_DATA_DIR%/CameraFiles
     * \endcode
     *  which will point to the same folder), under Linux&reg; this directory will be
     *  \code
     *  /etc/matrix-vision/mvimpact-acquire/camerafiles
     *  \endcode
     *  while under other platforms these files MUST be located in the current working directory.
     *  This behaviour can be modified by writing the property \b mvIMPACT::acquire::Device::customDataDirectory before initialising the device.
     *  To get access to an XML description file within the application, these file must be copied to
     *  this directory \b BEFORE the device is initialized. During the initialisation process the
     *  device driver will process every file located under this location and will add them to
     *  the internal list of descriptions. Every camera located during this process and also descriptions
     *  created later on during the program operation can be selected via the property
     *  \b mvIMPACT::acquire::CameraSettingsFrameGrabber::type.
     *
     *  \note
     *  In order not to bloat the device driver with redundant data it's wise only to store the
     *  descriptions needed for the application to run under this location.
     *
     *  \note
     *  Only camera descriptions supported by the capture device will be added to the device
     *  drivers internal list and will therefore be accessible via the
     *  \b mvIMPACT::acquire::CameraDescriptionManager.
     *
     *  To restore the default values valid during the driver was initialized the function
     *  \b mvIMPACT::acquire::ComponentCollection::restoreDefault can be used as well.
     *
     *  \sa
     *  \b mvIMPACT::acquire::CameraDescriptionBase::exportDescription, \n
     *     mvIMPACT::acquire::CameraDescriptionBase::copyDescription
     *  \return
     *  - \b mvIMPACT::acquire::DMR_NO_ERROR if successful.
     *  - A negative error code of type \b mvIMPACT::acquire::TDMR_ERROR or \b mvIMPACT::acquire::TPROPHANDLING_ERROR otherwise.
     */
    int importDescription( void ) const
    {
        return DMR_ImportCameraDescription( m_hDrv, m_hRoot );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief A string property \b read-only containing the name of this camera description list.
    PropertyS name;
    /// \brief An enumerated integer property defining the type of video outputs this camera offers.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraOutput.
     *
     *  \note
     *  This property will be \b (read-only) for camera descriptions of type
     *  \b mvIMPACT::acquire::CameraDescriptionCameraLink and \b mvIMPACT::acquire::CameraDescriptionSDI
     *  as for these camera types the video output depends on certain other parameters according to the
     *  corresponding standard.
     */
    PropertyICameraOutput videoOutput;
    /// \brief An enumerated integer property defining how the camera transmits image data.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraInterlacedType.
     */
    PropertyICameraInterlacedType interlacedType;
    /// \brief An integer property defining the number of active lines to capture from the camera.
    PropertyI aoiHeight;
    /// \brief An integer property defining the X-offset in pixels to the first active pixel to capture.
    PropertyI aoiStartX;
    /// \brief An integer property defining the Y-offset in lines to the first active line to capture.
    PropertyI aoiStartY;
    /// \brief An integer property defining the number of active pixels to capture per line.
    PropertyI aoiWidth;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A base class to describe an arbitrary digital camera signal(\b Device specific interface layout only).
/**
 *  This class provides access to all settings specific for digital video signals.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraDescriptionDigitalBase : public CameraDescriptionBase
//-----------------------------------------------------------------------------
{
protected:
    explicit CameraDescriptionDigitalBase( HDRV hDrv, HLIST hList ) : CameraDescriptionBase( hDrv, hList ), bitsPerPixel(),
        format(), bayerParity()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( bitsPerPixel, "BitsPerPixel" );
        locator.bindComponent( format, "Format" );
        locator.bindComponent( bayerParity, "BayerParity" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property defining the number of bits per pixel currently transmitted by this camera.
    PropertyI bitsPerPixel;
    /// \brief An enumerated integer property defining the data format the camera is sending image data.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraDataFormat.
     */
    PropertyICameraDataFormat format;
    /// \brief An enumerated integer property defining the start pixel for a camera delivering an unconverted bayer image.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBayerMosaicParity.
     */
    PropertyIBayerMosaicParity bayerParity;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A base class to describe an SDI(Serial Digital Interface) camera signal (\b Device specific interface layout only).
/**
 *  This class provides access to all settings specific for SDI video signals.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraDescriptionSDI : public CameraDescriptionDigitalBase
//-----------------------------------------------------------------------------
{
    friend class CameraDescriptionManager;
    explicit CameraDescriptionSDI( HDRV hDrv, HLIST hList ) : CameraDescriptionDigitalBase( hDrv, hList ), videoStandard()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( videoStandard, "VideoStandard" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property for defining the video standard this camera is compliant with.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TVideoStandard.
     */
    PropertyIVideoStandard videoStandard;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A base class to describe an arbitrary digital camera signal(\b Device specific interface layout only).
/**
 *  This class provides access to all settings specific for digital video signals.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraDescriptionDigitalBase2 : public CameraDescriptionDigitalBase
//-----------------------------------------------------------------------------
{
protected:
    explicit CameraDescriptionDigitalBase2( HDRV hDrv, HLIST hList ) : CameraDescriptionDigitalBase( hDrv, hList ),
        pixelsPerCycle(), scanMode()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( pixelsPerCycle, "PixelsPerCycle" );
        locator.bindComponent( scanMode, "ScanMode" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property defining the number of pixels per clock cycle transmitted by this camera.
    /**
     *  This corresponds the number of taps used by the camera in the described configuration.
     */
    PropertyI pixelsPerCycle;
    /// \brief An enumerated integer property providing information about the sensor of this camera.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraScanMode.
     */
    PropertyICameraScanMode scanMode;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A class to describe a CameraLink&reg; compliant camera(\b Device specific interface layout only).
/**
 *  This class provides access to all settings specific for CameraLink&reg; compliant cameras.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraDescriptionCameraLink : public CameraDescriptionDigitalBase2
//-----------------------------------------------------------------------------
{
    friend class CameraDescriptionManager;
    explicit CameraDescriptionCameraLink( HDRV hDrv, HLIST hList ) : CameraDescriptionDigitalBase2( hDrv, hList ), dataValid(),
        tapsXGeometry(), tapsYGeometry()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( dataValid, "DataValid" );
        locator.bindComponent( tapsXGeometry, "TapsXGeometry" );
        locator.bindComponent( tapsYGeometry, "TapsYGeometry" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the way this camera transmits the data valid (\b DVAL) signal.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraLinkDataValidMode.
     */
    PropertyICameraLinkDataValidMode dataValid;
    /// \brief An enumerated integer property defining the way this camera transmits the pixel data in X direction.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraTapsXGeometry.
     */
    PropertyICameraTapsXGeometry tapsXGeometry;
    /// \brief An enumerated integer property defining the way this camera transmits the pixel data in Y direction.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraTapsYGeometry.
     */
    PropertyICameraTapsYGeometry tapsYGeometry;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A class to describe a non-standard digital video signal(\b Device specific interface layout only).
/**
 *  This class provides access to all settings specific for non-standard digital video signals.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraDescriptionDigital : public CameraDescriptionDigitalBase2
//-----------------------------------------------------------------------------
{
    friend class CameraDescriptionManager;
    explicit CameraDescriptionDigital( HDRV hDrv, HLIST hList ) : CameraDescriptionDigitalBase2( hDrv, hList ),
        frameSync(), lineSync(), pixelClk()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( frameSync, "FrameSync" );
        locator.bindComponent( lineSync, "LineSync" );
        locator.bindComponent( pixelClk, "PixelClk" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the edge valid for the frame sync signal of this camera.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraExternalSyncEdge.
     *
     *  \note
     *  Not every value defined by this enumeration will be supported by this property. Check which values
     *  are available by reading the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyICameraExternalSyncEdge::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyICameraExternalSyncEdge::getTranslationDictValue
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyICameraExternalSyncEdge::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     */
    PropertyICameraExternalSyncEdge frameSync;
    /// \brief An enumerated integer property defining the edge valid for the line sync. of this camera.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraExternalSyncEdge.
     *
     *  \note
     *  Not every value defined by this enumeration will be supported by this property. Check which values
     *  are available by reading the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyICameraExternalSyncEdge::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyICameraExternalSyncEdge::getTranslationDictValue
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyICameraExternalSyncEdge::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     */
    PropertyICameraExternalSyncEdge lineSync;
    /// \brief An enumerated integer property defining the edge valid for the pixel clock of this camera.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraExternalSyncEdge.
     *
     *  \note
     *  Not every value defined by this enumeration will be supported by this property. Check which values
     *  are available by reading the properties translation dictionary with
     *  the functions \b mvIMPACT::acquire::PropertyICameraExternalSyncEdge::getTranslationDictString and
     *  \b mvIMPACT::acquire::PropertyICameraExternalSyncEdge::getTranslationDictValue
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  C++ offers the more efficient function \b mvIMPACT::acquire::PropertyICameraExternalSyncEdge::getTranslationDict
     *  in addition to the functions mentioned above.
     *  \endif
     */
    PropertyICameraExternalSyncEdge pixelClk;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief An internal base class to describe standard analogue video cameras(\b Device specific interface layout only).
/**
 *  Instances of this class can't be constructed directly. Use one of the derived types.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraDescriptionStandardBase : public CameraDescriptionBase
//-----------------------------------------------------------------------------
{
protected:
    explicit CameraDescriptionStandardBase( HDRV hDrv, HLIST hList ) : CameraDescriptionBase( hDrv, hList ), videoStandard(),
        scanStandard(), scanRate_kHz(), startField()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( videoStandard, "VideoStandard" );
        locator.bindComponent( scanStandard, "ScanStandard" );
        locator.bindComponent( scanRate_kHz, "ScanRate_kHz" );
        locator.bindComponent( startField, "StartField" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property for defining the video standard this camera is compliant with.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TVideoStandard.
     */
    PropertyIVideoStandard videoStandard;
    /// \brief An enumerated integer property defining the scan standard this camera is compliant with.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TScanStandard.
     */
    PropertyIScanStandard scanStandard;
    /// \brief An integer property containing the scan rate in kHz needed to driver the AD converter of the capture device with to convert the video signal properly.
    PropertyI scanRate_kHz;
    /// \brief An enumerated integer property containing information about the first field transmitted by a camera.
    /**
     *  A camera might transmit either the odd or the even field of an interlaced video signal first.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TAcquisitionField.
     */
    PropertyIAcquisitionField startField;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief A class describing analogue standard compliant video cameras(\b Device specific interface layout only).
/**
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraDescriptionStandard : public CameraDescriptionStandardBase
//-----------------------------------------------------------------------------
{
    friend class CameraDescriptionManager;
    explicit CameraDescriptionStandard( HDRV hDrv, HLIST hList ) : CameraDescriptionStandardBase( hDrv, hList ) {}
};

//-----------------------------------------------------------------------------
/// \brief A class describing non-standard video cameras(\b Device specific interface layout only).
/**
 *  This class can be used to describe a non-standard analogue video camera. A camera
 *  considered as non-standard when it is not compliant with one of the defined
 *  video standards like e.g. CCIR.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraDescriptionNonStandard : public CameraDescriptionStandardBase
//-----------------------------------------------------------------------------
{
    friend class CameraDescriptionManager;
    explicit CameraDescriptionNonStandard( HDRV hDrv, HLIST hList ) : CameraDescriptionStandardBase( hDrv, hList ), lineFrequency_Hz(),
        VDOutput(), HDOutput(), syncOutput(), pixelClockOutput(), fieldGateMode(), fieldGateStart(), fieldGateWidth(),
        clampMode(), clampStart_us()
    {
        ComponentLocator locator( m_hRoot );
        locator.bindComponent( lineFrequency_Hz, "LineFrequency_Hz" );
        locator.bindComponent( VDOutput, "VDOutput" );
        locator.bindComponent( HDOutput, "HDOutput" );
        locator.bindComponent( syncOutput, "SyncOutput" );
        locator.bindComponent( pixelClockOutput, "PixelClockOutput" );
        locator.bindComponent( fieldGateMode, "FieldGateMode" );
        locator.bindComponent( fieldGateStart, "FieldGateStart" );
        locator.bindComponent( fieldGateWidth, "FieldGateWidth" );
        locator.bindComponent( clampMode, "ClampMode" );
        locator.bindComponent( clampStart_us, "ClampStart_us" );
    }
public:
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An integer property containing the line frequency of this camera in Hertz.
    PropertyI lineFrequency_Hz;
    /// \brief An enumerated integer property defining whether the vertical sync. information is part of the video signal or transmitted via a separate wire.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraExternalSyncEdge.
     */
    PropertyICameraExternalSyncEdge VDOutput;
    /// \brief An enumerated integer property defining whether the horizontal sync. information is part of the video signal or transmitted via a separate wire.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraExternalSyncEdge.
     */
    PropertyICameraExternalSyncEdge HDOutput;
    /// \brief An enumerated integer property for RGB cameras containing information where the sync. information is transmitted.
    /**
     *  This can either be within one of the three color components or on a separate wire.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraExternalSyncOutput.
     */
    PropertyICameraExternalSyncOutput syncOutput;
    /// \brief An enumerated integer property containing information whether the pixel clock is part of the video signal or not.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TCameraExternalSyncEdge.
     */
    PropertyICameraExternalSyncEdge pixelClockOutput;
    /// \brief An enumerated integer property defining the clamp mode for this camera description.
    /**
     *  This defines how the field detection(ODD/EVEN) is done.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TFieldGateMode.
     */
    PropertyIFieldGateMode fieldGateMode;
    /// \brief An integer property defining the start position (in pixel clocks) of the field gate detection area.
    /**
     *  This will only need modification in very rare cases.
     */
    PropertyI fieldGateStart;
    /// \brief An integer property defining the width (in pixel clocks) of the field gate detection area.
    /**
     *  This will only need modification in very rare cases.
     */
    PropertyI fieldGateWidth;
    /// \brief An enumerated integer property defining the clamp mode for this camera description.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TClampMode.
     */
    PropertyIClampMode clampMode;
    /// \brief The clamp start position defines where in each line of the video signal the frame grabber assumes the black level position.
    /**
     *  This will only need modification in very rare cases.
     */
    PropertyI clampStart_us;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief Grants access to camera description objects(\b Device specific interface layout only).
/**
 *  This class provides access to the various camera description objects. Each
 *  device recognizes a different set of camera descriptions. E.g. a digital
 *  frame grabber will not be able to work with analogue cameras. Each camera description
 *  class will be derived from \b mvIMPACT::acquire::CameraDescriptionBase.
 *
 *  \note
 *  Please note that instances of this class will \b ONLY list camera descriptions
 *  that have once been selected by the property \b mvIMPACT::acquire::CameraSettingsFrameGrabber::type
 *  at runtime. This is to save memory. A complete list of camera descriptions
 *  available for the current device therefore can only be queried by reading the
 *  the translation dictionary of the property \b mvIMPACT::acquire::CameraSettingsFrameGrabber::type.
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  #include <mvIMPACT_CPP/mvIMPACT_acquire.h>
 *  #include <algorithm>
 *  #include <iostream>
 *
 *  using namespace std;
 *  using namespace mvIMPACT::acquire;
 *
 *  //-----------------------------------------------------------------------------
 *  template<class T>
 *  class DisplayDictEntry : public unary_function<pair<string, T>, void>
 *  //-----------------------------------------------------------------------------
 *  {
 *  public:
 *    void operator()( const pair<string, T>& data ) const
 *    {
 *      cout << "  [" << data.second << "]: " << data.first << endl;
 *    }
 *  };
 *
 *  //-----------------------------------------------------------------------------
 *  // lists all available camera descriptions for a certain device
 *  int main( int argc, char* argv[] )
 *  //-----------------------------------------------------------------------------
 *  {
 *    DeviceManager devMgr;
 *    Device* pDev = devMgr[0];
 *    if( !pDev )
 *    {
 *      cout << "No device found" << endl;
 *      return 0;
 *    }
 *
 *    // display the name of every camera description available for this device.
 *    // this might be less than the number of camera descriptions available on the system as e.g.
 *    // an analog frame grabber can't use descriptions for digital cameras
 *    CameraSettingsFrameGrabber cs( pDev );
 *    std::string<std::string, int> vAvailableDescriptions;
 *    cs.type.getTranslationDict( vAvailableDescriptions );
 *    cout << endl << "Available camera descriptions: " << vAvailableDescriptions.size() << endl
 *         << "----------------------------------" << endl;
 *    for_each( vAvailableDescriptions.begin(), vAvailableDescriptions.end(), DisplayDictEntry<int>() )
 *
 *    // list all descriptions that already have been selected at least once
 *    CameraDescriptionManager camMgr( pDev );
 *    unsigned int camCnt = camMgr.getCLCameraDescriptionCount();
 *    cout << "Available CL descriptions: " << camCnt << endl;
 *    for( unsigned int a=0; a<camCnt; a++ )
 *    {
 *      cout << "  " << camMgr.cameraDescriptionCameraLink( a )->name.read() << endl;
 *    }
 *    camCnt = camMgr.getStandardCameraDescriptionCount();
 *    cout << "Available Std descriptions: " << camCnt << endl;
 *    for( unsigned int b=0; b<camCnt; b++ )
 *    {
 *      cout << "  " << camMgr.cameraDescriptionStandard( b )->name.read() << endl;
 *    }
 *    camCnt = camMgr.getNonStandardCameraDescriptionCount();
 *    cout << "Available NonStd descriptions: " << camCnt << endl;
 *    for( unsigned int c=0; c<camCnt; c++ )
 *    {
 *      cout << "  " << camMgr.cameraDescriptionNonStandard( c )->name.read() << endl;
 *    }
 *    return 0;
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 * import mvIMPACT.acquire.*;
 *
 * //-----------------------------------------------------------------------------
 * public class ListCameraDescriptions
 * //-----------------------------------------------------------------------------
 * {
 *   static
 *   {
 *     try
 *     {
 *       System.loadLibrary( "mvIMPACT_Acquire.java" );
 *     }
 *     catch( UnsatisfiedLinkError e )
 *     {
 *       System.err.println( "Native code library failed to load. Make sure the 'mvIMPACT_Acquire.java' library can be found in the systems search path.\n" + e );
 *       System.exit( 1 );
 *     }
 *   }
 *
 *   //-----------------------------------------------------------------------------
 *   public static void main( String[] args )
 *   //-----------------------------------------------------------------------------
 *   {
 *     DeviceManager devMgr = new DeviceManager();
 *     Device pDev = mvIMPACT.acquire.examples.helper.DeviceAccess.getDeviceFromUserInput( devMgr );
 *     if( pDev == null )
 *     {
 *       System.out.print( "Unable to continue!" );
 *       mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *       System.exit( 1 );
 *     }
 *
 *     System.out.println( "Initialising the device. This might take some time..." );
 *     try
 *     {
 *       pDev.open();
 *     }
 *     catch( ImpactAcquireException e )
 *     {
 *       // this e.g. might happen if the same device is already opened in another process...
 *       System.out.println( "An error occurred while opening device " + pDev.getSerial().read() +
 *                           "(error code: " + e.getMessage() + ")." );
 *       mvIMPACT.acquire.examples.helper.DeviceAccess.waitForENTER();
 *       System.exit( 1 );
 *     }
 *
 *     // display the name of every camera description available for this device.
 *     // this might be less than the number of camera descriptions available on the system as e.g.
 *     // an analog frame grabber can't use descriptions for digital cameras
 *     CameraSettingsFrameGrabber cs = new CameraSettingsFrameGrabber(pDev);
 *     StringIntVector vAvailableDescriptions = new StringIntVector();
 *     cs.getType().getTranslationDict( vAvailableDescriptions );
 *     System.out.println( String.format( "\nAvailable camera descriptions: %d", vAvailableDescriptions.size() ) );
 *     System.out.println( "----------------------------------" );
 *
 *     for( int i=0; i<vAvailableDescriptions.size(); i++ )
 *     {
 *         System.out.println( String.format( "[%d]: %s", vAvailableDescriptions.get( i ).getSecond(), vAvailableDescriptions.get( i ).getFirst() ) );
 *     }
 *
 *     // list all descriptions that already have been selected at least once
 *     CameraDescriptionManager camMgr = new CameraDescriptionManager( pDev );
 *     long camCnt = camMgr.getCLCameraDescriptionCount();
 *     System.out.println( String.format( "Available CL descriptions: %d", camCnt ) );
 *     for( long a=0; a<camCnt; a++ )
 *     {
 *       System.out.println( "  " + camMgr.cameraDescriptionCameraLink( a ).getName().read() );
 *     }
 *     camCnt = camMgr.getStandardCameraDescriptionCount();
 *     System.out.println( String.format( "Available Std descriptions: %d", camCnt ) );
 *     for( long b=0; b<camCnt; b++ )
 *     {
 *       System.out.println( "  " + camMgr.cameraDescriptionStandard( b ).getName().read() );
 *     }
 *     camCnt = camMgr.getNonStandardCameraDescriptionCount();
 *     System.out.println( String.format( "Available NonStd descriptions: %d", camCnt ) );
 *     for( long c=0; c<camCnt; c++ )
 *     {
 *       System.out.println( "  " + camMgr.cameraDescriptionNonStandard( c ).getName().read() );
 *     }
 *   }
 * }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *   # ...
 *   # display the name of every camera description available for this device.
 *   # this might be less than the number of camera descriptions available on the system as e.g.
 *   # an analog frame grabber can't use descriptions for digital cameras
 *   cs = acquire.CameraSettingsFrameGrabber(pDev)
 *   availableDescriptions = []
 *
 *   cs.type.getTranslationDict(availableDescriptions)
 *   print()
 *   print("Available camera descriptions: " + str(availableDescriptions.size()))
 *   print("----------------------------------")
 *
 *   for description in availableDescriptions:
 *       print(description)
 *
 *   # list all descriptions that already have been selected at least once
 *   camMgr = acquire.CameraDescriptionManager(pDev)
 *   camCnt = camMgr.getCLCameraDescriptionCount()
 *   print("Available CL descriptions: " + str(camCnt))
 *   for a in range(camCnt):
 *       print("  " + camMgr.cameraDescriptionCameraLink(a).name.readS())
 *
 *   camCnt = camMgr.getStandardCameraDescriptionCount()
 *   print("Available Std descriptions: " + str(camCnt))
 *   for b in range(camCnt):
 *       print("  " << camMgr.cameraDescriptionStandard(b).name.readS())
 *
 *   camCnt = camMgr.getNonStandardCameraDescriptionCount()
 *   print("Available NonStd descriptions: " + str(camCnt))
 *   for c in range(camCnt):
 *     print("  " << camMgr.cameraDescriptionNonStandard(c).name.readS())
 * \endcode
 * \endif
 *
 *  \note
 *  This class will only be available for frame grabber devices. For other devices
 *  the class constructor will raise an exception.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class CameraDescriptionManager
//-----------------------------------------------------------------------------
{
    typedef std::map<std::string, unsigned int> StringUIntMap;
#           ifndef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    struct ReferenceCountedData
    //-----------------------------------------------------------------------------
    {
        HDRV                                               m_hDrv;
        HLIST                                              m_hListCameraDescriptions;
        mutable unsigned int                               m_lastListSize;
        mutable std::vector<CameraDescriptionStandard*>    m_vStdDescriptions;
        mutable std::vector<CameraDescriptionNonStandard*> m_vNonStdDescriptions;
        mutable std::vector<CameraDescriptionSDI*>         m_vSDIDescriptions;
        mutable std::vector<CameraDescriptionCameraLink*>  m_vCLDescriptions;
        mutable std::vector<CameraDescriptionDigital*>     m_vDigitalDescriptions;
        mutable StringUIntMap                              m_mListNameToDescription;
        mutable StringUIntMap                              m_mStdNameToDescription;
        mutable StringUIntMap                              m_mNonStdNameToDescription;
        mutable StringUIntMap                              m_mSDINameToDescription;
        mutable StringUIntMap                              m_mCLNameToDescription;
        mutable StringUIntMap                              m_mDigitalNameToDescription;
        unsigned int                                       m_refCnt;
        explicit ReferenceCountedData( HDRV hDrv, HLIST hList ) : m_hDrv( hDrv ), m_hListCameraDescriptions( hList ),
            m_lastListSize( 0 ), m_vStdDescriptions(), m_vNonStdDescriptions(), m_vSDIDescriptions(), m_vCLDescriptions(),
            m_vDigitalDescriptions(), m_mListNameToDescription(), m_mStdNameToDescription(),
            m_mNonStdNameToDescription(), m_mCLNameToDescription(), m_mDigitalNameToDescription(),
            m_refCnt( 1 ) {}
        ~ReferenceCountedData()
        {
            std::vector<CameraDescriptionStandard*>::size_type vStdSize = m_vStdDescriptions.size();
            for( std::vector<CameraDescriptionStandard*>::size_type a = 0; a < vStdSize; a++ )
            {
                delete m_vStdDescriptions[a];
            }
            std::vector<CameraDescriptionStandard*>::size_type vNonStdSize = m_vNonStdDescriptions.size();
            for( std::vector<CameraDescriptionStandard*>::size_type b = 0; b < vNonStdSize; b++ )
            {
                delete m_vNonStdDescriptions[b];
            }
            std::vector<CameraDescriptionSDI*>::size_type vSDISize = m_vSDIDescriptions.size();
            for( std::vector<CameraDescriptionSDI*>::size_type c = 0; c < vSDISize; c++ )
            {
                delete m_vSDIDescriptions[c];
            }
            std::vector<CameraDescriptionStandard*>::size_type vCLSize = m_vCLDescriptions.size();
            for( std::vector<CameraDescriptionStandard*>::size_type d = 0; d < vCLSize; d++ )
            {
                delete m_vCLDescriptions[d];
            }
            std::vector<CameraDescriptionStandard*>::size_type vDigSize = m_vDigitalDescriptions.size();
            for( std::vector<CameraDescriptionStandard*>::size_type e = 0; e < vDigSize; e++ )
            {
                delete m_vDigitalDescriptions[e];
            }
        }
    }* m_pRefData;
#           endif // #ifdef DOXYGEN_SHOULD_SKIP_THIS
    //-----------------------------------------------------------------------------
    void dealloc( void )
    //-----------------------------------------------------------------------------
    {
        assert( m_pRefData && "BUG in reference counting detected!" );
        --( m_pRefData->m_refCnt );
        if( m_pRefData->m_refCnt == 0 )
        {
            delete m_pRefData;
            m_pRefData = 0;
        }
    }
    //-----------------------------------------------------------------------------
    bool locateDescription( const StringUIntMap& m, const std::string& name, unsigned int& index ) const
    //-----------------------------------------------------------------------------
    {
        update();
        StringUIntMap::const_iterator it = m_pRefData->m_mListNameToDescription.find( name );
        if( it != m_pRefData->m_mListNameToDescription.end() )
        {
            index = it->second;
            return true;
        }

        it = m.find( name );
        if( it != m.end() )
        {
            index = it->second;
            return true;
        }

        return false;
    }
    //-----------------------------------------------------------------------------
    void update( void ) const
    //-----------------------------------------------------------------------------
    {
        ComponentList camDescList( m_pRefData->m_hListCameraDescriptions );
        unsigned int curSize = camDescList.size();
        if( m_pRefData->m_lastListSize != curSize )
        {
            // new cameras at runtime can only appear at the end of the list
            Component it( m_pRefData->m_hListCameraDescriptions );
            it = it.firstChild();
            // move to the old end
            for( unsigned int i = 0; ( i < m_pRefData->m_lastListSize ) && it.isValid(); i++ )
            {
                ++it;
            }
            // start to add new descriptions
            while( it.isValid() )
            {
                ComponentList list( it );
                const std::string contentDescriptor( list.contentDescriptor() );
                if( contentDescriptor == "CameraLink" )
                {
                    CameraDescriptionCameraLink* p = new CameraDescriptionCameraLink( m_pRefData->m_hDrv, list );
                    unsigned int index = static_cast<unsigned int>( m_pRefData->m_vCLDescriptions.size() ); // do not change order of this and the next line!
                    m_pRefData->m_vCLDescriptions.push_back( p );
                    m_pRefData->m_mListNameToDescription.insert( std::make_pair( list.name(), index ) );
                    m_pRefData->m_mCLNameToDescription.insert( std::make_pair( p->name.read(), index ) );
                }
                else if( contentDescriptor == "SDI" )
                {
                    CameraDescriptionSDI* p = new CameraDescriptionSDI( m_pRefData->m_hDrv, list );
                    unsigned int index = static_cast<unsigned int>( m_pRefData->m_vCLDescriptions.size() ); // do not change order of this and the next line!
                    m_pRefData->m_vSDIDescriptions.push_back( p );
                    m_pRefData->m_mListNameToDescription.insert( std::make_pair( list.name(), index ) );
                    m_pRefData->m_mSDINameToDescription.insert( std::make_pair( p->name.read(), index ) );
                }
                else if( contentDescriptor == "Digital" )
                {
                    CameraDescriptionDigital* p = new CameraDescriptionDigital( m_pRefData->m_hDrv, list );
                    unsigned int index = static_cast<unsigned int>( m_pRefData->m_vDigitalDescriptions.size() ); // do not change order of this and the next line!
                    m_pRefData->m_vDigitalDescriptions.push_back( p );
                    m_pRefData->m_mListNameToDescription.insert( std::make_pair( list.name(), index ) );
                    m_pRefData->m_mDigitalNameToDescription.insert( std::make_pair( p->name.read(), index ) );
                }
                else if( contentDescriptor == "Standard" )
                {
                    CameraDescriptionStandard* p = new CameraDescriptionStandard( m_pRefData->m_hDrv, list );
                    unsigned int index = static_cast<unsigned int>( m_pRefData->m_vStdDescriptions.size() ); // do not change order of this and the next line!
                    m_pRefData->m_vStdDescriptions.push_back( p );
                    m_pRefData->m_mListNameToDescription.insert( std::make_pair( list.name(), index ) );
                    m_pRefData->m_mStdNameToDescription.insert( std::make_pair( p->name.read(), index ) );
                }
                else if( contentDescriptor == "NonStandard" )
                {
                    CameraDescriptionNonStandard* p = new CameraDescriptionNonStandard( m_pRefData->m_hDrv, list );
                    unsigned int index = static_cast<unsigned int>( m_pRefData->m_vNonStdDescriptions.size() ); // do not change order of this and the next line!
                    m_pRefData->m_vNonStdDescriptions.push_back( p );
                    m_pRefData->m_mListNameToDescription.insert( std::make_pair( list.name(), index ) );
                    m_pRefData->m_mNonStdNameToDescription.insert( std::make_pair( p->name.read(), index ) );
                }
                else
                {
                    ; // NOT recognized....
                }
                ++it;
            }
            m_pRefData->m_lastListSize = curSize;
        }
    }
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::CameraDescriptionManager object.
    explicit CameraDescriptionManager(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::>DeviceManager object.
        Device* pDev ) : m_pRefData( 0 )
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        if( !pDev->isOpen() )
        {
            pDev->open();
        }

        TDMR_ERROR result;
        HLIST hList;
        if( ( result = DMR_FindList( pDev->hDrv(), 0, dmltCameraDescriptions, 0, &hList ) ) != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, "Couldn't find camera description list (is this a frame grabber?)" );
        }
        m_pRefData = new ReferenceCountedData( pDev->hDrv(), hList );
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::CameraDescriptionManager from an existing one.
    CameraDescriptionManager(
        /// A constant reference to the \b mvIMPACT::acquire::CameraDescriptionManager object, this object shall be created from
        const CameraDescriptionManager& src ) : m_pRefData( src.m_pRefData )
    {
        ++( m_pRefData->m_refCnt );
    }
    /// \brief Class destructor.
    ~CameraDescriptionManager()
    {
        dealloc();
    }
    /// \brief Allows assignments of \b mvIMPACT::acquire::CameraDescriptionManager objects.
    CameraDescriptionManager& operator=( const CameraDescriptionManager& rhs )
    {
        if( this != &rhs )
        {
            dealloc();
            m_pRefData = rhs.m_pRefData;
            // inc. the NEW reference count
            ++m_pRefData->m_refCnt;
        }
        return *this;
    }
    /// \brief Returns the number of CameraLink&reg; camera descriptions currently available for the device that constructed this instance of the class.
    unsigned int getCLCameraDescriptionCount( void ) const
    {
        update();
        return static_cast<unsigned int>( m_pRefData->m_vCLDescriptions.size() );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::CameraDescriptionCameraLink object specifying the camera description found at the given index in the camera description managers internal list.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If the index is either equal or higher than the number of CameraLink&reg; camera descriptions \n
     *  detected for this device an STL out_of_range exception will be thrown.
     *  \endif
     */
    CameraDescriptionCameraLink* cameraDescriptionCameraLink(
        /// [in] The index of the camera description to return
        unsigned int index ) const
    {
        update();
        return m_pRefData->m_vCLDescriptions.at( index );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::CameraDescriptionCameraLink object specifying the camera description with the given name in the camera description managers internal list.
    /**
     *  \return
     *  - a pointer to a \b mvIMPACT::acquire::CameraDescriptionCameraLink object specifying the camera
     *  description with the given name in the camera description managers internal list if a camera
     *  description with \a name is available.
     *  - an invalid pointer or reference otherwise.
     */
    CameraDescriptionCameraLink* cameraDescriptionCameraLink(
        /// [in] The name of the camera description. This can either be
        /// the name of the list like e.g. 'CameraLink_Generic' or the
        /// value of the property 'name' of this description like
        /// e.g. 'Generic'.
        const std::string& name ) const
    {
        unsigned int index = 0;
        return ( ( locateDescription( m_pRefData->m_mCLNameToDescription, name, index ) == true ) ? m_pRefData->m_vCLDescriptions.at( index ) : 0 );
    }
    /// \brief Returns the number of SDI camera descriptions currently available for the device that constructed this instance of the class.
    unsigned int getSDICameraDescriptionCount( void ) const
    {
        update();
        return static_cast<unsigned int>( m_pRefData->m_vSDIDescriptions.size() );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::CameraDescriptionSDI object specifying the camera description found at the given index in the camera description managers internal list.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If the index is either equal or higher than the number of SDI camera descriptions \n
     *  detected for this device an STL out_of_range exception will be thrown.
     *  \endif
     */
    CameraDescriptionSDI* cameraDescriptionSDI(
        /// [in] The index of the camera description to return
        unsigned int index ) const
    {
        update();
        return m_pRefData->m_vSDIDescriptions.at( index );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::CameraDescriptionSDI object specifying the camera description with the given name in the camera description managers internal list.
    /**
     *  \return
     *  - a pointer to a \b mvIMPACT::acquire::CameraDescriptionSDI object specifying the camera
     *  description with the given name in the camera description managers internal list if a camera
     *  description with \a name is available.
     *  - an invalid pointer or reference otherwise.
     */
    CameraDescriptionSDI* cameraDescriptionSDI(
        /// [in] The name of the camera description. This can either be
        /// the name of the list like e.g. 'CameraLink_Generic' or the
        /// value of the property 'name' of this description like
        /// e.g. 'Generic'.
        const std::string& name ) const
    {
        unsigned int index = 0;
        return ( ( locateDescription( m_pRefData->m_mSDINameToDescription, name, index ) == true ) ? m_pRefData->m_vSDIDescriptions.at( index ) : 0 );
    }
    /// \brief Returns the number of non-standard digital camera descriptions currently available for the device that constructed this instance of the class.
    unsigned int getDigitalCameraDescriptionCount( void ) const
    {
        update();
        return static_cast<unsigned int>( m_pRefData->m_vDigitalDescriptions.size() );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::CameraDescriptionDigital object specifying the camera description found at the given index in the camera description managers internal list.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If the index is either equal or higher than the number of non-standard digital camera descriptions \n
     *  detected for this device an STL out_of_range exception will be thrown.
     *  \endif
     */
    CameraDescriptionDigital* cameraDescriptionDigital(
        /// [in] The index of the camera description to return
        unsigned int index ) const
    {
        update();
        return m_pRefData->m_vDigitalDescriptions.at( index );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::CameraDescriptionDigital object specifying the camera description with the given name in the camera description managers internal list.
    /**
     *  \return
     *  - a pointer to a \b mvIMPACT::acquire::CameraDescriptionDigital object specifying the camera
     *  description with the given name in the camera description managers internal list if a camera
     *  description with \a name is available.
     *  - an invalid pointer or reference otherwise.
     */
    CameraDescriptionDigital* cameraDescriptionDigital(
        /// [in] The name of the camera description. This can either be
        /// the name of the list like e.g. 'Digital_Generic' or the
        /// value of the property 'name' of this description like
        /// e.g. 'Generic'.
        const std::string& name ) const
    {
        unsigned int index = 0;
        return ( ( locateDescription( m_pRefData->m_mDigitalNameToDescription, name, index ) == true ) ? m_pRefData->m_vDigitalDescriptions.at( index ) : 0 );
    }
    /// \brief Returns the number of standard camera descriptions currently available for the device that constructed this instance of the class.
    unsigned int getStandardCameraDescriptionCount( void ) const
    {
        update();
        return static_cast<unsigned int>( m_pRefData->m_vStdDescriptions.size() );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::CameraDescriptionStandard object specifying the camera description found at the given index in the camera description managers internal list.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If the index is either equal or higher than the number of standard camera descriptions \n
     *  detected for this device an STL out_of_range exception will be thrown.
     *  \endif
     */
    CameraDescriptionStandard* cameraDescriptionStandard(
        /// [in] The index of the camera description to return
        unsigned int index ) const
    {
        update();
        return m_pRefData->m_vStdDescriptions.at( index );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::CameraDescriptionStandard object specifying the camera description with the given name in the camera description managers internal list.
    /**
     *  \return
     *  - a pointer to a \b mvIMPACT::acquire::CameraDescriptionStandard object specifying the camera
     *  description with the given name in the camera description managers internal list if a camera
     *  description with \a name is available.
     *  - an invalid pointer or reference otherwise.
     */
    CameraDescriptionStandard* cameraDescriptionStandard(
        /// [in] The name of the camera description. This can either be
        /// the name of the list like e.g. 'Standard_Generic' or the
        /// value of the property 'name' of this description like
        /// e.g. 'Generic'.
        const std::string& name ) const
    {
        unsigned int index = 0;
        return ( ( locateDescription( m_pRefData->m_mStdNameToDescription, name, index ) == true ) ? m_pRefData->m_vStdDescriptions.at( index ) : 0 );
    }
    /// \brief Returns the number of non-standard camera descriptions currently available for the device that constructed this instance of the class.
    unsigned int getNonStandardCameraDescriptionCount( void ) const
    {
        update();
        return static_cast<unsigned int>( m_pRefData->m_vNonStdDescriptions.size() );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::CameraDescriptionNonStandard object specifying the camera description found at the given index in the camera description managers internal list.
    /**
     *  \if DOXYGEN_CPP_DOCUMENTATION
     *  If the index is either equal or higher than the number of non-standard camera descriptions \n
     *  detected for this device an STL out_of_range exception will be thrown.
     *  \endif
     */
    CameraDescriptionNonStandard* cameraDescriptionNonStandard(
        /// [in] The index of the camera description to return
        unsigned int index ) const
    {
        update();
        return m_pRefData->m_vNonStdDescriptions.at( index );
    }
    /// \brief Returns a pointer to a \b mvIMPACT::acquire::CameraDescriptionNonStandard object specifying the camera description with the given name in the camera description managers internal list.
    /**
     *  \return
     *  - a pointer to a \b mvIMPACT::acquire::CameraDescriptionNonStandard object specifying the camera
     *  description with the given name in the camera description managers internal list if a camera
     *  description with \a name is available.
     *  - an invalid pointer or reference otherwise.
     */
    CameraDescriptionNonStandard* cameraDescriptionNonStandard(
        /// [in] The name of the camera description. This can either be
        /// the name of the list like e.g. 'NonStandard_Generic' or the
        /// value of the property 'name' of this description like
        /// e.g. 'Generic'.
        const std::string& name ) const
    {
        unsigned int index = 0;
        return ( ( locateDescription( m_pRefData->m_mNonStdNameToDescription, name, index ) == true ) ? m_pRefData->m_vNonStdDescriptions.at( index ) : 0 );
    }
    /// \brief Returns the total number camera descriptions currently available for the device that constructed this instance of the class.
    /**
     *  \since 2.1.4
     */
    unsigned int getTotalCameraDescriptionCount( void ) const
    {
        update();
        return m_pRefData->m_lastListSize;
    }
};
#   endif // #ifndef #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

#   ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief Properties for accessing features belonging to the I2C control(\b Device specific interface layout only).
/**
 *  Properties in this class will only be available if a device has a local I2C
 *  bus and this is configured for access from an application. Right now this is only
 *  the case for mvBlueFOX-MLC devices.
 *
 *  \b mvBlueFOX \b specific:
 *
 *  For mvBlueFOX devices
 *  - clock stretching is supported
 *  - bus master is supported
 *
 *  The following I2C addresses will be blocked for access from an application:
 *  <table>
 *  <tr><td class="header">i2c address range</td><td class="header">affected devices</td></tr>
 *  <tr><td class="indexvalue">0x20-0x3F</td><td class="indexvalue">all mvBlueFOX devices</td></tr>
 *  <tr><td class="indexvalue">0x66-0x67</td><td class="indexvalue">all mvBlueFOX devices</td></tr>
 *  <tr><td class="indexvalue">0x90-0x91</td><td class="indexvalue">mvBlueFOX-200w only</td></tr>
 *  <tr><td class="indexvalue">0xA0-0xA3</td><td class="indexvalue">all mvBlueFOX devices</td></tr>
 *  <tr><td class="indexvalue">0xA6-0xA7</td><td class="indexvalue">all mvBlueFOX devices</td></tr>
 *  <tr><td class="indexvalue">0xBA-0xBB</td><td class="indexvalue">mvBlueFOX-202a and mvBlueFOX-205 only</td></tr>
 *  </table>
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  I2CControl i2cc( pBF ); // assuming 'pBF' to be a valid 'Device*' instance to an mvBlueFOX device
 *  if( i2cc.I2COperationMode.isValid() )
 *  {
 *    // direct property access
 *    i2cc.I2CBufferLength.write( 0 );
 *    i2cc.I2COperationMode.write( I2ComRead );
 *    assert( ( i2cc.I2COperationExecute.call() == DMR_INVALID_PARAMETER ) && "Unexpected driver behaviour" );
 *    assert( ( i2cc.I2COperationStatus.read() == I2CosNotEnoughData ) && "Unexpected driver behaviour" );
 *    i2cc.I2CBufferLength.write( 1 );
 *    // assuming we write to an invalid address
 *    assert( ( i2cc.I2COperationExecute.call() == DMR_EXECUTION_FAILED ) && "Unexpected driver behaviour" );
 *    assert( ( i2cc.I2COperationStatus.read() == I2CosFailure ) && "Unexpected driver behaviour" );
 *    i2cc.I2COperationMode.write( I2ComWrite );
 *    i2cc.I2CBuffer.writeBinary( string() );
 *    assert( ( i2cc.I2COperationExecute.call() == DMR_INVALID_PARAMETER ) && "Unexpected driver behaviour" );
 *    assert( ( i2cc.I2COperationStatus.read() == I2CosNotEnoughData ) && "Unexpected driver behaviour" );
 *    {
 *      char binData[2] = { 'A', 'B' };
 *      i2cc.I2CBuffer.writeBinary( string(binData, sizeof(binData)) );
 *    }
 *    // assuming we write to an invalid address
 *    assert( ( i2cc.I2COperationExecute.call() == DMR_EXECUTION_FAILED ) && "Unexpected driver behaviour" );
 *    assert( ( i2cc.I2COperationStatus.read() == I2CosFailure ) && "Unexpected driver behaviour" );
 *    // Write some data. This will only work if several conditions are met:
 *    // - there is a device that can be written to at address 0xA6
 *    // - the sub-address 0x04 is valid
 *    // - the device is designed to work with 8 bit sub-addresses
 *    // - the device can deal with 9 bytes in a single command
 *    i2cc.I2CDeviceAddress.write( 0xA6 );
 *    i2cc.I2CDeviceSubAddress.write( 0x04 );
 *    i2cc.I2CDeviceSubAddressWidth.write( 8 );
 *    {
 *      char binData[9] = { 'D', 'E', 'A', 'D', ' ', 'B', 'E', 'E', 'F' };
 *      i2cc.I2CBuffer.writeBinary( string( binData, sizeof( binData ) ) );
 *    }
 *    i2cc.I2COperationMode.write( I2ComWrite );
 *    int I2COperationExecuteResult = i2cc.I2COperationExecute.call();
 *    if( I2COperationExecuteResult != DMR_NO_ERROR )
 *    {
 *      printf( "'I2COperationExecute' write failed. Return value: %s(%d).\n", ImpactAcquireException::getErrorCodeAsString( I2COperationExecuteResult ).c_str(), I2COperationExecuteResult );
 *    }
 *    printf( "'I2COperationStatus' after write: %s.\n", i2cc.I2COperationStatus.readS().c_str() );
 *    // Read some data. Similar condition as for write apply
 *    const int bytesToRead = 4;
 *    i2cc.I2CDeviceAddress.write( 0xA8 );
 *    i2cc.I2CDeviceSubAddress.write( 0x00 );
 *    i2cc.I2CDeviceSubAddressWidth.write( 8 );
 *    i2cc.I2CBufferLength.write( bytesToRead ); // read 'bytesToRead' bytes
 *    i2cc.I2COperationMode.write( I2ComRead );
 *    i2cc.I2COperationExecute.call();
 *    I2COperationExecuteResult = i2cc.I2COperationExecute.call();
 *    if( I2COperationExecuteResult != DMR_NO_ERROR )
 *    {
 *      printf( "'I2COperationExecute' read failed. Return value: %s(%d).\n", ImpactAcquireException::getErrorCodeAsString( I2COperationExecuteResult ).c_str(), I2COperationExecuteResult );
 *    }
 *    printf( "'I2COperationStatus' after read: %s.\n", i2cc.I2COperationStatus.readS().c_str() );
 *    if( i2cc.I2CBuffer.binaryDataBufferSize() != bytesToRead )
 *    {
 *      printf( "'I2CBuffer' reports %d bytes of data while %d bytes where expected.\n", i2cc.I2CBuffer.binaryDataBufferSize(), bytesToRead );
 *    }
 *    // usage of the convenience functions
 *    i2cc.I2CWrite( 0xA4, 0x00, 8, string("TEST") );
 *    const string i2cReadBuffer = i2cc.I2CRead( 0xA4, 0x00, 8, 4 );
 *  }
 *  else
 *  {
 *    printf( "I2CControl not available.\n" );
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  import java.nio.ByteBuffer; // needed for binary data exchange!
 *
 *  // more code and a class definition must follow here...
 *
*  I2CControl i2cc = new I2CControl( pDev ); // assuming 'pBF' to be a valid 'Device*' instance to an mvBlueFOX device
*  if( i2cc.getI2COperationMode().isValid() )
*  {
*    // direct property access
*    i2cc.getI2CBufferLength().write( 0 );
*    i2cc.getI2COperationMode().write( TI2COperationMode.I2ComRead );
*    assert i2cc.getI2COperationExecute().call() == TDMR_ERROR.DMR_INVALID_PARAMETER : "Unexpected driver behaviour";
*    assert i2cc.getI2COperationStatus().read() == TI2COperationStatus.I2CosNotEnoughData : "Unexpected driver behaviour";
*    i2cc.getI2CBufferLength().write( 1 );
*    // assuming we write to an invalid address
*    assert i2cc.getI2COperationExecute().call() == TDMR_ERROR.DMR_EXECUTION_FAILED : "Unexpected driver behaviour";
*    assert i2cc.getI2COperationStatus().read() == TI2COperationStatus.I2CosFailure : "Unexpected driver behaviour";
*    i2cc.getI2COperationMode().write( TI2COperationMode.I2ComWrite );
*    {
*      final int BUF_SIZE = 2;
*      byte[] data_bytes = new byte[BUF_SIZE];
*      data_bytes[0] = 'A';
*      data_bytes[1] = 'B';
*      ByteBuffer data = ByteBuffer.allocateDirect( BUF_SIZE );
*      data.put( data_bytes );
*      i2cc.getI2CBuffer().writeBinary( data );
*    }
*    // assuming we write to an invalid address
*    assert i2cc.getI2COperationExecute().call() == TDMR_ERROR.DMR_EXECUTION_FAILED : "Unexpected driver behaviour";
*    assert i2cc.getI2COperationStatus().read() == TI2COperationStatus.I2CosFailure : "Unexpected driver behaviour";
*    // Write some data. This will only work if several conditions are met:
*    // - there is a device that can be written to at address 0xA6
*    // - the sub-address 0x04 is valid
*    // - the device is designed to work with 8 bit sub-addresses
*    // - the device can deal with 9 bytes in a single command
*    i2cc.getI2CDeviceAddress().write( 0xA6 );
*    i2cc.getI2CDeviceSubAddress().write( 0x04 );
*    i2cc.getI2CDeviceSubAddressWidth().write( 8 );
*    {
*      final int BUF_SIZE = 9;
*      byte[] data_bytes = new byte[BUF_SIZE];
*      data_bytes[0] = 'D';
*      data_bytes[0] = 'E';
*      data_bytes[0] = 'A';
*      data_bytes[0] = 'D';
*      data_bytes[0] = ' ';
*      data_bytes[0] = 'B';
*      data_bytes[0] = 'E';
*      data_bytes[0] = 'E';
*      data_bytes[0] = 'F';
*      ByteBuffer data = ByteBuffer.allocateDirect( BUF_SIZE );
*      data.put( data_bytes );
*      i2cc.getI2CBuffer().writeBinary( data );
*    }
*    i2cc.getI2COperationMode().write( TI2COperationMode.I2ComWrite );
*    int I2COperationExecuteResult = i2cc.getI2COperationExecute().call();
*    if( I2COperationExecuteResult != TDMR_ERROR.DMR_NO_ERROR )
*    {
*      System.out.println( String.format( "'I2COperationExecute' write failed. Return value: %s(%d).", ImpactAcquireException.getErrorCodeAsString( I2COperationExecuteResult ), I2COperationExecuteResult ) );
*    }
*    System.out.println( String.format( "'I2COperationStatus' after write: %s.", i2cc.getI2COperationStatus().readS() ) );
*    // Read some data. Similar condition as for write apply
*    final int bytesToRead = 4;
*    i2cc.getI2CDeviceAddress().write( 0xA8 );
*    i2cc.getI2CDeviceSubAddress().write( 0x00 );
*    i2cc.getI2CDeviceSubAddressWidth().write( 8 );
*    i2cc.getI2CBufferLength().write( bytesToRead ); // read 'bytesToRead' bytes
*    i2cc.getI2COperationMode().write( TI2COperationMode.I2ComRead );
*    i2cc.getI2COperationExecute().call();
*    I2COperationExecuteResult = i2cc.getI2COperationExecute().call();
*    if( I2COperationExecuteResult != TDMR_ERROR.DMR_NO_ERROR )
*    {
*      System.out.println( String.format( "'I2COperationExecute' read failed. Return value: %s(%d).", ImpactAcquireException.getErrorCodeAsString( I2COperationExecuteResult ), I2COperationExecuteResult ) );
*    }
*    System.out.println( String.format( "'I2COperationStatus' after read: %s.", i2cc.getI2COperationStatus().readS() ) );
*    if( i2cc.getI2CBuffer().binaryDataBufferSize() != bytesToRead )
*    {
*      System.out.println( String.format( "'I2CBuffer' reports %d bytes of data while %d bytes where expected.", i2cc.getI2CBuffer().binaryDataBufferSize(), bytesToRead ) );
*    }
*    // usage of the convenience functions
*    i2cc.I2CWrite( 0xA4, 0x00, 8, "TEST" );
*    final String i2cReadBuffer = i2cc.I2CRead( 0xA4, 0x00, 8, 4 );
*  }
*  else
*  {
*    System.out.println( "I2CControl not available." );
*  }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  i2cc = acquire.I2CControl(pBF); # assuming 'pBF' to be a valid 'Device*' instance to an mvBlueFOX device
 *  if i2cc.I2COperationMode.isValid():
 *    # direct property access
 *    i2cc.I2CBufferLength.write(0)
 *    i2cc.I2COperationMode.write(acquire.I2ComRead)
 *    assert i2cc.I2COperationExecute.call() == acquire.DMR_INVALID_PARAMETER, "Unexpected driver behaviour"
 *    assert i2cc.I2COperationStatus.read() == acquire.I2CosNotEnoughData, "Unexpected driver behaviour"
 *    i2cc.I2CBufferLength.write(1)
 *    # assuming we write to an invalid address
 *    assert i2cc.I2COperationExecute.call() == acquire.DMR_EXECUTION_FAILED, "Unexpected driver behaviour"
 *    assert i2cc.I2COperationStatus.read() == acquire.I2CosFailure, "Unexpected driver behaviour"
 *    i2cc.I2COperationMode.write(acquire.I2ComWrite)
 *    pBuf = '\x41\x42' # 'A' and 'B'
 *    i2cc.I2CBuffer.writeBinary(pBuf)
 *    # assuming we write to an invalid address
 *    assert i2cc.I2COperationExecute.call() == acquire.DMR_EXECUTION_FAILED, "Unexpected driver behaviour"
 *    assert i2cc.I2COperationStatus.read() == acquire.I2CosFailure, "Unexpected driver behaviour"
 *    # Write some data. This will only work if several conditions are met:
 *    # - there is a device that can be written to at address 0xA6
 *    # - the sub-address 0x04 is valid
 *    # - the device is designed to work with 8 bit sub-addresses
 *    # - the device can deal with 9 bytes in a single command
 *    i2cc.I2CDeviceAddress.write(0xA6)
 *    i2cc.I2CDeviceSubAddress.write(0x04)
 *    i2cc.I2CDeviceSubAddressWidth.write(8)
 *    pBuf = '\x44\x45\x41\x44\x20\x42\x45\x45\x46' # The good old 'DEAD BEEF' in HEX notation
 *    i2cc.I2CBuffer.writeBinary(pBuf)
 *    i2cc.I2COperationMode.write(acquire.I2ComWrite)
 *    I2COperationExecuteResult = i2cc.I2COperationExecute.call()
 *    if I2COperationExecuteResult != acquire.DMR_NO_ERROR:
 *      print("'I2COperationExecute' write failed. Return value: {0}({1}).".format(acquire.ImpactAcquireException.getErrorCodeAsString(I2COperationExecuteResult), I2COperationExecuteResult))
 *    print("'I2COperationStatus' after write: {0}.".format(i2cc.I2COperationStatus.readS()))
 *    # Read some data. Similar condition as for write apply
 *    bytesToRead = 4
 *    i2cc.I2CDeviceAddress.write(0xA8)
 *    i2cc.I2CDeviceSubAddress.write(0x00)
 *    i2cc.I2CDeviceSubAddressWidth.write(8)
 *    i2cc.I2CBufferLength.write(bytesToRead) # read 'bytesToRead' bytes
 *    i2cc.I2COperationMode.write(acquire.I2ComRead)
 *    i2cc.I2COperationExecute.call()
 *    I2COperationExecuteResult = i2cc.I2COperationExecute.call()
 *    if I2COperationExecuteResult != acquire.DMR_NO_ERROR:
 *      System.out.println(String.format("'I2COperationExecute' read failed. Return value: %s(%d).", ImpactAcquireException.getErrorCodeAsString(I2COperationExecuteResult), I2COperationExecuteResult))
 *    print("'I2COperationStatus' after read: {0}.".format(i2cc.I2COperationStatus.readS()))
 *    if i2cc.I2CBuffer.binaryDataBufferSize() != bytesToRead:
 *      print("'I2CBuffer' reports {0} bytes of data while {1} bytes where expected.".format(i2cc.I2CBuffer.binaryDataBufferSize(), bytesToRead))
 *    # usage of the convenience functions
 *    i2cc.I2CWrite(0xA4, 0x00, 8, "TEST")
 *    i2cReadBuffer = i2cc.I2CRead(0xA4, 0x00, 8, 4)
 *  else:
 *    print("I2CControl not available.")
 * \endcode
 * \endif
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class I2CControl : public ComponentCollection
//-----------------------------------------------------------------------------
{
private:
    void prepareI2CAccess( int deviceAddress, int deviceSubAddress, int deviceSubAddressWidth, TI2COperationMode mode )
    {
        I2CDeviceAddress.write( deviceAddress );
        I2CDeviceSubAddress.write( deviceSubAddress );
        I2CDeviceSubAddressWidth.write( deviceSubAddressWidth );
        I2COperationMode.write( mode );
    }
public:
    /// brief Constructs a new \b mvIMPACT::acquire::I2CControl object.
    explicit I2CControl(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ): ComponentCollection( pDev ), I2COperationMode(), I2COperationExecute(), I2COperationStatus(),
        I2CDeviceAddress(), I2CDeviceSubAddressWidth(), I2CDeviceSubAddress(), I2CBuffer(), I2CBufferLength()
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        DeviceComponentLocator locator( pDev, dltIOSubSystem );
        HLIST hList = locator.findComponent( "I2CControl" );
        if( hList != INVALID_ID )
        {
            locator.bindSearchBase( locator.searchbase_id(), "I2CControl" );
            m_hRoot = locator.searchbase_id();
            locator.bindComponent( I2COperationMode, "I2COperationMode" );
            locator.bindComponent( I2COperationExecute, "I2COperationExecute@i" );
            locator.bindComponent( I2COperationStatus, "I2COperationStatus" );
            locator.bindComponent( I2CDeviceAddress, "I2CDeviceAddress" );
            locator.bindComponent( I2CDeviceSubAddressWidth, "I2CDeviceSubAddressWidth" );
            locator.bindComponent( I2CDeviceSubAddress, "I2CDeviceSubAddress" );
            locator.bindComponent( I2CBuffer, "I2CBuffer" );
            locator.bindComponent( I2CBufferLength, "I2CBufferLength" );
        }
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property to select the I2C operation.
    /**
     *  The selected operation is executed when \b mvIMPACT::acquire::I2CControl::I2COperationExecute is called.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TI2COperationMode.
     */
    PropertyII2COperationMode I2COperationMode;
    /// \brief Calling this function will execute the operation selected by \b mvIMPACT::acquire::I2CControl::I2COperationMode.
    Method I2COperationExecute;
    /// \brief Represents the I2C operation execution status.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TI2COperationStatus.
     */
    PropertyII2COperationStatus I2COperationStatus;
    /// \brief An integer property storing the address of the I2C device to communicate with.
    PropertyI I2CDeviceAddress;
    /// \brief An enumerated integer property storing the sub-address width(in bits) of the I2C device to communicate with.
    /**
     *  Valid values for this property are:
     *
     *  - 0
     *  - 8
     *  - 16
     *
     *  \note
     *  This property must be set to 0 for devices not supporting a sub-address.
     */
    PropertyI I2CDeviceSubAddressWidth;
    /// \brief An integer property storing the sub-address of the I2C device to communicate with.
    /**
     *  When \b mvIMPACT::acquire::I2CControl::I2CDeviceSubAddressWidth is set to 0, this property will be ignored.
     */
    PropertyI I2CDeviceSubAddress;
    /// \brief Defines the intermediate access buffer that allows the exchange of data between the I2C device and the application.
    /**
     *  This property can store binary data.
     */
    PropertyS I2CBuffer;
    /// \brief An integer property controlling the length of the mapping between the I2C device and the \b mvIMPACT::acquire::I2CControl::I2CBuffer property.
    PropertyI I2CBufferLength;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
    /// \brief Read data from an I2C device.
    /**
     *  This is a convenience function that wraps the property access a little.
     *  In order to find out if the command has been executed successfully
     *  \b mvIMPACT::acquire::I2CControl::I2COperationStatus should be checked afterwards.
     */
    std::string I2CRead(
        /// [in] The address of the I2C device to communicate with.
        int deviceAddress,
        /// [in] The sub-address of the I2C device to communicate with.
        int deviceSubAddress,
        /// [in] The sub-address width(in bits) of the I2C device to communicate with.
        int deviceSubAddressWidth,
        /// [in] The amount of bytes to read.
        int byteCnt )
    {
        prepareI2CAccess( deviceAddress, deviceSubAddress, deviceSubAddressWidth, I2ComRead );
        I2CBufferLength.write( byteCnt );
        I2COperationExecute.call();
        return I2CBuffer.readBinary();
    }
    /// \brief Write data to a I2C device.
    /**
     *  This is a convenience function that wraps the property access a little.
     *  In order to find out if the command has been executed successfully
     *  \b mvIMPACT::acquire::I2CControl::I2COperationStatus should be checked afterwards.
     */
    void I2CWrite(
        /// [in] The address of the I2C device to communicate with.
        int deviceAddress,
        /// [in] The sub-address of the I2C device to communicate with.
        int deviceSubAddress,
        /// [in] The sub-address width(in bits) of the I2C device to communicate with.
        int deviceSubAddressWidth,
        /// [in] The data to write to the I2C device.
        const std::string& data )
    {
        prepareI2CAccess( deviceAddress, deviceSubAddress, deviceSubAddressWidth, I2ComWrite );
        I2CBuffer.writeBinary( data );
        I2COperationExecute.call();
    }
};
#   endif // #ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION

//-----------------------------------------------------------------------------
/// \brief Properties for configuring settings belonging to the motor focus control (\b Device specific interface layout only).
/**
 *  Properties in this class will only be available if a device is fitted with
 *  a focus motor.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class MotorFocusControl : public ComponentCollection
//-----------------------------------------------------------------------------
{
public:
    /// brief Constructs a new \b mvIMPACT::acquire::MotorFocusControl object.
    explicit MotorFocusControl(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ): ComponentCollection( pDev ), motorFocusSendBuffer(), motorFocusReceiveBuffer(), motorFocusSend(),
        motorFocusIncrement(), motorFocusNear(), motorFocusFar(), motorFocusAbsolutePositionCurrent(),
        motorFocusAbsolutePositionDesired(), motorFocusMoveToAbsolutePositionDesired()
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        DeviceComponentLocator locator( pDev, dltIOSubSystem );
        HLIST hList = locator.findComponent( "MotorFocusControl" );
        if( hList != INVALID_ID )
        {
            locator.bindSearchBase( locator.searchbase_id(), "MotorFocusControl" );
            m_hRoot = locator.searchbase_id();
            locator.bindComponent( motorFocusSendBuffer, "MotorFocusSendBuffer" );
            locator.bindComponent( motorFocusReceiveBuffer, "MotorFocusReceiveBuffer" );
            locator.bindComponent( motorFocusSend, "MotorFocusSend@i" );
            locator.bindComponent( motorFocusIncrement, "MotorFocusIncrement" );
            locator.bindComponent( motorFocusNear, "MotorFocusNear@i" );
            locator.bindComponent( motorFocusFar, "MotorFocusFar@i" );
            locator.bindComponent( motorFocusAbsolutePositionCurrent, "MotorFocusAbsolutePositionCurrent" );
            locator.bindComponent( motorFocusAbsolutePositionDesired, "MotorFocusAbsolutePositionDesired" );
            locator.bindComponent( motorFocusMoveToAbsolutePositionDesired, "MotorFocusMoveToAbsolutePositionDesired@i" );
        }
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief A string property storing a command to be sent to the motor focus.
    /**
     *  To actually send the command, the function \b mvIMPACT::acquire::MotorFocusControl::motorFocusSend must be executed.
     */
    PropertyS motorFocusSendBuffer;
    /// \brief A string property \b (read-only) that will contain answers sent by the motor focus controller.
    PropertyS motorFocusReceiveBuffer;
    /// \brief Calling this function will send the value of \b mvIMPACT::acquire::MotorFocusControl::motorFocusSendBuffer to the hardware.
    /**
     *  Afterwards \b mvIMPACT::acquire::MotorFocusControl::motorFocusReceiveBuffer will contain the hardwares answer.
     */
    Method motorFocusSend;
    /// \brief An integer property storing an increment(in encoder counts) that will be used by subsequent calls to \b mvIMPACT::acquire::MotorFocusControl::motorFocusNear and \b mvIMPACT::acquire::MotorFocusControl::motorFocusFar commands.
    PropertyI motorFocusIncrement;
    /// \brief Calling this function will cause the motor focus to move forward by \b mvIMPACT::acquire::MotorFocusControl::motorFocusIncrement encoder units.
    Method motorFocusNear;
    /// \brief Calling this function will cause the motor focus to move backward by \b mvIMPACT::acquire::MotorFocusControl::motorFocusIncrement encoder units.
    Method motorFocusFar;
    /// \brief An integer property \b (read-only) storing the current absolute position(in encoder counts).
    PropertyI motorFocusAbsolutePositionCurrent;
    /// \brief An integer property storing an absolute position(in encoder counts) that will be used by subsequent calls to the \b mvIMPACT::acquire::MotorFocusControl::motorFocusMoveToAbsolutePositionDesired command.
    PropertyI motorFocusAbsolutePositionDesired;
    /// \brief Calling this function will cause the motor focus to move to the position defined by the value of \b mvIMPACT::acquire::MotorFocusControl::motorFocusAbsolutePositionDesired.
    Method motorFocusMoveToAbsolutePositionDesired;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

#   ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief Properties for configuring settings belonging to the digital I/O measurement(\b Device specific interface layout only).
/**
 *  Properties in this class will only be available if a device offers digital I/O measurement features.
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 *  // This code fragment will print result of measurement using all modes on all sources
 *  // to the standard output.
 *  DigitalIOMeasurementControl iomc(getDevicePointerFromSomewhere());
 *  if( iomc.digitalIOMeasurementMode.isValid() && iomc.digitalIOMeasurementSource.isValid() )
 *  {
 *    vector<pair<string, TDigitalIOMeasurementMode> > modeDict;
 *    iomc.digitalIOMeasurementMode.getTranslationDict( modeDict );
 *    const unsigned int modeCnt = iomc.digitalIOMeasurementMode.dictSize();
 *    vector<pair<string, TDigitalIOMeasurementSource> > srcDict;
 *    iomc.digitalIOMeasurementSource.getTranslationDict( srcDict );
 *    const unsigned int srcCnt = iomc.digitalIOMeasurementSource.dictSize();
 *    for( unsigned int i=0; i<modeCnt; i++ )
 *    {
 *      iomc.digitalIOMeasurementMode.write( modeDict[i].second );
 *      for( unsigned int j=0; j<srcCnt; j++ )
 *      {
 *        iomc.digitalIOMeasurementSource.write( srcDict[j].second );
 *        printf( "Digital I/O measurement result using mode '%s' at source '%s': %s\n", iomc.digitalIOMeasurementMode.readS().c_str(), iomc.digitalIOMeasurementSource.readS().c_str(), iomc.digitalIOMeasurementResult.readS().c_str() );
 *      }
 *    }
 *  }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 *  // This code fragment will print result of measurement using all modes on all sources
 *  // to the standard output.
 *  DigitalIOMeasurementControl iomc = new DigitalIOMeasurementControl(getDevicePointerFromSomewhere());
 *  if( iomc.digitalIOMeasurementMode.isValid() && iomc.digitalIOMeasurementSource.isValid() )
 *  {
 *    StringIntVector modeDict = new StringIntVector();
 *    iomc.digitalIOMeasurementMode.getTranslationDict( modeDict );
 *    final int modeCnt = iomc.digitalIOMeasurementMode.dictSize();
 *    StringIntVector srcDict = new StringIntVector();
 *    iomc.digitalIOMeasurementSource.getTranslationDict( srcDict );
 *    final int srcCnt = iomc.digitalIOMeasurementSource.dictSize();
 *    for( int i=0; i<modeCnt; i++ )
 *    {
 *      iomc.digitalIOMeasurementMode.write( modeDict.get( i ).getSecond() );
 *      for( int j=0; j<srcCnt; j++ )
 *      {
 *        iomc.digitalIOMeasurementSource.write( srcDict.get( j ).getSecond() );
 *        System.out.println( String.format( "Digital I/O measurement result using mode '%s' at source '%s': %s\n", iomc.digitalIOMeasurementMode.readS(), iomc.digitalIOMeasurementSource.readS(), iomc.digitalIOMeasurementResult.readS() ) );
 *      }
 *    }
 *  }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 *  modeDict = []
 *  srcDict = []
 *  iomc = acquire.DigitalIOMeasurementControl(pDev)
 *  if iomc.digitalIOMeasurementMode.isValid and iomc.digitalIOMeasurementSource.isValid:
 *      iomc.digitalIOMeasurementMode.getTranslationDict(modeDict)
 *      modeCnt = iomc.digitalIOMeasurementMode.dictSize()
 *      iomc.digitalIOMeasurementSource.getTranslationDict(srcDict);
 *      srcCnt = iomc.digitalIOMeasurementSource.dictSize();
 *      for i in range(modeCnt):
 *          iomc.digitalIOMeasurementMode.write(modeDict[i].second);
 *          for j in range(srcCnt):
 *              iomc.digitalIOMeasurementSource.write(srcDict[j].second);
 *              print("Digital I/O measurement result using mode '" +  iomc.digitalIOMeasurementMode.readS() + "' at source '" +  iomc.digitalIOMeasurementSource.readS() + "': " + iomc.digitalIOMeasurementResult.readS())
 * \endcode
 * \endif
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class DigitalIOMeasurementControl : public ComponentCollection
//-----------------------------------------------------------------------------
{
public:
    /// brief Constructs a new \b mvIMPACT::acquire::DigitalIOMeasurementControl object.
    explicit DigitalIOMeasurementControl(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ): ComponentCollection( pDev ), digitalIOMeasurementMode(), digitalIOMeasurementSource(),
        digitalIOMeasurementResult()
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        DeviceComponentLocator locator( pDev, dltIOSubSystem );
        HLIST hList = locator.findComponent( "DigitalIOMeasurementControl" );
        if( hList != INVALID_ID )
        {
            locator.bindSearchBase( locator.searchbase_id(), "DigitalIOMeasurementControl" );
            m_hRoot = locator.searchbase_id();
            locator.bindComponent( digitalIOMeasurementMode, "DigitalIOMeasurementMode" );
            locator.bindComponent( digitalIOMeasurementSource, "DigitalIOMeasurementSource" );
            locator.bindComponent( digitalIOMeasurementResult, "DigitalIOMeasurementResult" );
        }
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the type of measurement to perform.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDigitalIOMeasurementMode.
     */
    PropertyIDigitalIOMeasurementMode digitalIOMeasurementMode;
    /// \brief An enumerated integer property defining where the measurement shall be performed.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDigitalIOMeasurementMode.
     */
    PropertyIDigitalIOMeasurementSource digitalIOMeasurementSource;
    /// \brief A float property \b (read-only) that will contain the result of the measurement.
    /**
     *  Reading this property will automatically perform a new measurement.
     *
     *  \note
     *  Please note that the signal connected to the digital input must match the selected digital input
     *  threshold(see \b mvIMPACT::acquire::IOSubSystemBlueFOX::digitalInputThreshold) in order to
     *  obtain valid results.
     */
    PropertyF digitalIOMeasurementResult;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};

//-----------------------------------------------------------------------------
/// \brief This class provides access to general settings as well as to settings which are unique for the \b mvBlueFOX(\b Device specific interface layout only).
/**
 *  To see a small code example on how you can work with object of this class see
 *  the detailed description of the class \b mvIMPACT::acquire::FunctionInterface as well.
 *  Statements made for the use of the class \b mvIMPACT::acquire::FullSettingsBase apply for
 *  this class as well.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class SettingsBlueFOX : public FullSettingsBase
//-----------------------------------------------------------------------------
{
public:
    /// brief Constructs a new \b mvIMPACT::acquire::SettingsBlueFOX object.
    explicit SettingsBlueFOX(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& name = "Base" ) : FullSettingsBase( pDev, name ), cameraSetting( pDev, name ) {}
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief Camera related settings.
    CameraSettingsBlueFOX cameraSetting;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION

#   ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief This class provides access to general settings as well as to settings which are unique for frame grabber devices(\b Device specific interface layout only).
/**
 *  To see a small code example on how you can work with object of this class see
 *  the detailed description of the class \b mvIMPACT::acquire::FunctionInterface as well.
 *  Statements made for the use of the class \b mvIMPACT::acquire::FullSettingsBase apply for
 *  this class as well.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class SettingsFrameGrabber : public FullSettingsBase
//-----------------------------------------------------------------------------
{
public:
    /// brief Constructs a new \b mvIMPACT::acquire::SettingsFrameGrabber object.
    explicit SettingsFrameGrabber(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] The name of the driver internal setting to access with this instance.
        /// A list of valid setting names can be obtained by a call to
        /// \b mvIMPACT::acquire::FunctionInterface::getAvailableSettings, new
        /// settings can be created with the function
        /// \b mvIMPACT::acquire::FunctionInterface::createSetting
        const std::string& name = "Base" ) : FullSettingsBase( pDev, name ), cameraSetting( pDev, name ), connector( pDev, name ) {}
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief Camera related settings.
    CameraSettingsFrameGrabber cameraSetting;
    /// \brief Input channel related properties.
    Connector connector;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

#   ifndef IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION
#       ifndef WRAP_ANY
/// \brief \b deprecated. Use the class \b mvIMPACT::acquire::SystemSettings instead(\b Device specific interface layout only).
/**
 *  \deprecated
 *  This class has been declared \b deprecated and might not be available in future releases.
 *  All features of this class are now available in \b mvIMPACT::acquire::SystemSettings as well, so please use
 *  this class instead.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
typedef SystemSettings MVIMPACT_DEPRECATED_CPP( SystemBlueCOUGAR );
#       endif // #  ifndef WRAP_ANY
#   endif // #ifndef IGNORE_MVBLUECOUGAR_SPECIFIC_DOCUMENTATION

#   ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief A class containing \b mvBlueFOX specific settings to control the overall behaviour of the driver(\b Device specific interface layout only).
/**
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class SystemBlueFOX : public SystemSettings
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::SystemBlueFOX object.
    explicit SystemBlueFOX(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : SystemSettings( pDev ), transferSize(), footerMode(), footerCheckEnable(), powerMode(), statusLEDEnable()
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        DeviceComponentLocator locator( pDev, dltSystemSettings );
        locator.bindComponent( powerMode, "PowerMode" );
        locator.bindComponent( statusLEDEnable, "StatusLEDEnable" );
        locator.bindSearchBase( locator.searchbase_id(), "Camera" );
        locator.bindComponent( transferSize, "TransferSize" );
        locator.bindComponent( footerMode, "FooterMode" );
        locator.bindComponent( footerCheckEnable, "FooterCheckEnable" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the block size of the image data blocks transferred from the device.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBlueFOXTransferSize.
     */
    PropertyIBlueFOXTransferSize transferSize;
    /// \brief An enumerated integer property defining the footer mode of the device.
    /**
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBlueFOXFooterMode.
     */
    PropertyIBlueFOXFooterMode footerMode;
    /// \brief An enumerated integer property allowing to switch on/off the check of the image footer.
    /**
     *  The image footer contains certain additional data as e.g. the exposure time as used by the image
     *  sensor. To debug transfer related problems it sometimes can be useful to disable all internal
     *  data consistency checks by the driver.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean footerCheckEnable;
    /// \brief An enumerated integer property defining the power mode of the device.
    /**
     *  \note
     *  This property requires at least firmware version 39! See \b mvIMPACT::acquire::Device::firmwareVersion to find
     *  out which firmware is currently running on the device or use \b mvIMPACT::acquire::Device::updateFirmware()
     *  to update the firmware to the state compiled into the driver.
     *
     *  \note
     *  Do \b NOT modify this property when images are acquired in parallel. Switching off or on the power
     *  for a device that is capturing images at the same time will result in incorrect images! Therefore
     *  always make sure to stop image acquisition and clean up \b BEFORE modifying this property.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TDevicePowerMode.
     */
    PropertyIDevicePowerMode powerMode;
    /// \brief An enumerated integer property allowing to switch on/off the status LED of the device.
    /**
     *  \note
     *  This feature is currently available for mvBlueFOX-MLC devices only.
     *
     *  Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \since 2.17.0
     */
    PropertyIBoolean statusLEDEnable;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
};
#   endif // #ifndef IGNORE_MVBLUEFOX_SPECIFIC_DOCUMENTATION

#   ifndef IGNORE_MVV4L2_SPECIFIC_DOCUMENTATION
//-----------------------------------------------------------------------------
/// \brief A class containing \b mvV4L2 specific settings to control the overall behaviour of the driver(\b Device specific interface layout only).
/**
 *  \note UNDER CONSTRUCTION! Subject to change.
 *
 *  \note This class will only be available if \b mvIMPACT::acquire::Device::interfaceLayout is set to
 *  \b mvIMPACT::acquire::dilDeviceSpecific before the device is opened.
 */
class SystemV4L2 : public SystemSettings
//-----------------------------------------------------------------------------
{
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::SystemV4L2 object.
    explicit SystemV4L2(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev ) : SystemSettings( pDev ), volume(), balance(), bass(), treble(), mute(), loudness()
    {
        pDev->validateInterfaceLayout( dilDeviceSpecific );
        DeviceComponentLocator locator( pDev, dltSystemSettings );
        locator.bindSearchBase( locator.searchbase_id(), "V4L-Audio" );
        locator.bindComponent( volume, "Volume" );
        locator.bindComponent( balance, "Balance" );
        locator.bindComponent( bass, "Bass" );
        locator.bindComponent( treble, "Treble" );
        locator.bindComponent( mute, "Mute" );
        locator.bindComponent( loudness, "Loudness" );
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief If V4L2 device supports audio, this integer property adjusts the audio volume.
    /**
     *  This property represents a V4L2-audio-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI volume;
    /// \brief If V4L2 device supports audio, this integer property adjusts the audio balance.
    /**
     *  This property represents a V4L2-audio-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI balance;
    /// \brief If V4L2 device supports audio, this integer property adjusts the audio bass.
    /**
     *  This property represents a V4L2-audio-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI bass;
    /// \brief If V4L2 device supports audio, this integer property adjusts the audio treble.
    /**
     *  This property represents a V4L2-audio-control ID.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     *  If supported, a minimum value, a maximum value and step width will be defined. Thus, invalid values may be tuned after writing to fit within the step size,
     *  values too large or too small will raise an exception.
     */
    PropertyI treble;
    /// \brief If V4L2 device supports audio, this enumerated integer property sets audio mute on/off.
    /**
     *  This property represents a boolean-valued V4L2-control ID. Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIBoolean mute;
    /// \brief If V4L2 device supports audio, this enumerated integer property sets audio loudness on/off.
    /**
     *  This property represents a boolean-valued V4L2-control ID. Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     *
     *  \note This property is not supported by every device.
     *  Therefore always call the function \b mvIMPACT::acquire::Component::isValid to check if this property is available or not.
     */
    PropertyIBoolean loudness;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*

};
#   endif // #ifndef IGNORE_MVV4L2_SPECIFIC_DOCUMENTATION

/// @}

#endif // #ifndef IGNORE_MVDEVICE_SPECIFIC_INTERFACE_DOCUMENTATION

inline void ExceptionFactory::raiseException( const char* pFunctionName, int lineNumber, int errorCode, HOBJ objectHandle /* = INVALID_ID*/ )
{
    std::ostringstream oss;
    oss << pFunctionName << " (line: " << lineNumber << ")";
    switch( errorCode )
    {
    case PROPHANDLING_NOT_A_LIST:
        throw ENotAList( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_NOT_A_PROPERTY:
        throw ENotAProperty( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_NOT_A_METHOD:
        throw ENotAMethod( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_NO_READ_RIGHTS:
        throw ENoReadRights( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_NO_WRITE_RIGHTS:
        throw ENoWriteRights( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_NO_MODIFY_SIZE_RIGHTS:
        throw ENoModifySizeRights( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_INCOMPATIBLE_COMPONENTS:
        throw EIncompatibleComponents( getLastErrorString(), oss.str(), false );
    case PROPHANDLING_UNSUPPORTED_PARAMETER:
        throw EUnsupportedParameter( oss.str() );
    case PROPHANDLING_SIZE_MISMATCH:
        throw ESizeMismatch( getLastErrorString(), oss.str() );
    case PROPHANDLING_IMPLEMENTATION_MISSING:
        throw EImplementationMissing( getLastErrorString(), oss.str() );
    case PROPHANDLING_INVALID_PROP_VALUE:
        throw EInvalidValue( getLastErrorString(), oss.str(), false );
    case PROPHANDLING_PROP_TRANSLATION_TABLE_CORRUPTED:
        throw ETranslationTableCorrupted( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_PROP_VAL_ID_OUT_OF_BOUNDS:
        throw EValIDOutOfBounds( getLastErrorString(), oss.str(), false );
    case PROPHANDLING_PROP_TRANSLATION_TABLE_NOT_DEFINED:
        throw ETranslationTableNotDefined( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_INVALID_PROP_VALUE_TYPE:
        throw EInvalidValueType( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_PROP_VAL_TOO_LARGE:
        throw EValTooLarge( getLastErrorString(), oss.str() );
    case PROPHANDLING_PROP_VAL_TOO_SMALL:
        throw EValTooSmall( getLastErrorString(), oss.str() );
    case PROPHANDLING_COMPONENT_NOT_FOUND:
        throw EComponentNotFound( getLastErrorString(), oss.str() );
    case PROPHANDLING_LIST_ID_INVALID:
        throw EInvalidListID( getLastErrorString(), oss.str() );
    case PROPHANDLING_COMPONENT_ID_INVALID:
        throw EComponentIDInvalid( oss.str() );
    case PROPHANDLING_LIST_ENTRY_OCCUPIED:
        throw EListEntryOccupied( oss.str() );
    case PROPHANDLING_LIST_CANT_ACCESS_DATA:
        throw ECantAccessData( getLastErrorString(), oss.str() );
    case PROPHANDLING_METHOD_PTR_INVALID:
        throw EMethodPtrInvalid( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_METHOD_INVALID_PARAM_LIST:
        throw EInvalidParameterList( getLastErrorString(), oss.str() );
    case PROPHANDLING_INVALID_INPUT_PARAMETER:
        throw EInvalidInputParameter( getLastErrorString(), oss.str() );
    case PROPHANDLING_INPUT_BUFFER_TOO_SMALL:
        throw EInputBufferTooSmall( oss.str() );
    case PROPHANDLING_WRONG_PARAM_COUNT:
        throw EWrongParamCount( getLastErrorString(), oss.str() );
    case PROPHANDLING_UNSUPPORTED_OPERATION:
        throw EUnsupportedOperation( oss.str() );
    case PROPHANDLING_CANT_SERIALIZE_DATA:
        throw ECantSerializeData( Component( objectHandle ).name(), oss.str() );
    case PROPHANDLING_INVALID_FILE_CONTENT:
        throw EInvalidFileContent( getLastErrorString(), oss.str() );
    case PROPHANDLING_CANT_ALLOCATE_LIST:
        throw ECantAllocateNewList( oss.str() );
    case PROPHANDLING_CANT_REGISTER_COMPONENT:
        throw ECantRegisterComponent( getLastErrorString(), oss.str() );
    case PROPHANDLING_PROP_VALIDATION_FAILED:
        throw EValidationFailed( getLastErrorString(), oss.str() );
    // unsupported:
    //PROPHANDLING_ACCESSTOKEN_CREATION_FAILED          = -2011
    //PROPHANDLING_COMPONENT_HAS_OWNER_ALREADY          = -2023,
    //PROPHANDLING_COMPONENT_ALREADY_REGISTERED         = -2024,
    //PROPHANDLING_SWIG_ERROR                           = -2028,
    //PROPHANDLING_COMPONENT_NO_CALLBACK_REGISTERED     = -2030,
    case DMR_DEV_NOT_FOUND:
    case DMR_INIT_FAILED:
    case DMR_DRV_ALREADY_IN_USE:
    case DMR_DEV_CANNOT_OPEN:
    case DMR_NOT_INITIALIZED:
    case DMR_DRV_CANNOT_OPEN:
    case DMR_DEV_REQUEST_QUEUE_EMPTY:
    case DMR_DEV_REQUEST_CREATION_FAILED:
    case DMR_INVALID_PARAMETER:
    case DMR_EXPORTED_SYMBOL_NOT_FOUND:
    case DEV_UNKNOWN_ERROR:
    case DEV_HANDLE_INVALID:
    case DEV_INPUT_PARAM_INVALID:
    case DEV_WRONG_INPUT_PARAM_COUNT:
    case DEV_CREATE_SETTING_FAILED:
    case DEV_REQUEST_CANT_BE_UNLOCKED:
    case DEV_INVALID_REQUEST_NUMBER:
    case DEV_LOCKED_REQUEST_IN_QUEUE:
    case DEV_NO_FREE_REQUEST_AVAILABLE:
    case DEV_WAIT_FOR_REQUEST_FAILED:
    case DEV_UNSUPPORTED_PARAMETER:
    case DEV_INVALID_RTC_NUMBER:
    case DMR_INTERNAL_ERROR:
    case DMR_INPUT_BUFFER_TOO_SMALL:
    case DEV_INTERNAL_ERROR:
    case DMR_LIBRARY_NOT_FOUND:
    case DMR_FUNCTION_NOT_IMPLEMENTED:
    case DMR_FEATURE_NOT_AVAILABLE:
    case DMR_EXECUTION_PROHIBITED:
    case DMR_FILE_NOT_FOUND:
    case DMR_INVALID_LICENCE:
    case DEV_SENSOR_TYPE_ERROR:
    case DMR_CAMERA_DESCRIPTION_INVALID:
    case DMR_NEWER_LIBRARY_REQUIRED:
    case DMR_TIMEOUT:
    case DMR_WAIT_ABANDONED:
    case DMR_EXECUTION_FAILED:
    case DEV_REQUEST_ALREADY_IN_USE:
    case DEV_REQUEST_BUFFER_INVALID:
    case DEV_REQUEST_BUFFER_MISALIGNED:
    case DEV_ACCESS_DENIED:
    case DMR_PRELOAD_CHECK_FAILED:
    case DMR_FILE_ACCESS_ERROR:
    case DMR_CAMERA_DESCRIPTION_INVALID_PARAMETER:
    case DMR_INVALID_QUEUE_SELECTION:
    case DMR_ACQUISITION_ENGINE_BUSY:
    case DMR_BUSY:
    case DMR_OUT_OF_MEMORY:
        throw EDeviceManager( getLastErrorString(), oss.str(), static_cast<TDMR_ERROR>( errorCode ) );
    default:
        throw ImpactAcquireException( "Unknown error(" + getLastErrorString() + ")", oss.str(), errorCode );
    }
}

//-----------------------------------------------------------------------------
/// \brief A class to perform a firmware update of a specific device.
/**
 * This class is intended to provide an ease of use possibility to update the firmware of specific devices. It is possible to
 * specify the behavior of the class very detailed to make sure the update suits the users expectations. It is also possible to derive
 * from this class and override various functions in order to get custom notifications e.g. to update a GUI application.
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * To start a firmware update for MATRIX VISION %GenICam devices the following code will be sufficient:
 * \code
 * // force the update even if the version of the mvu-file is the same as the one on the device
 * mvIMPACT::acquire::FirmwareUpdater fwUpdater( pDev, true );
 * try
 * {
 *     const string pathToFirmwareArchive( "someArchive.mvu" );
 *     // start the whole update process
 *     const int FWUpdateResult = fwUpdater.update( pathToFirmwareArchive );
 *     cout << "Result of 'updateFirmware' call: " << ImpactAcquireException::getErrorCodeAsString( FWUpdateResult ) << "." << endl;
 * }
 * catch( const ImpactAcquireException& e )
 * {
 *     cout << "An error occurred while updating the firmware of the device " << pDev->serial.read()
 *          << "(error code: " << e.getErrorCodeAsString() << ").";
 *     // reading out potential issues
 *     cout << "Status: " << fwUpdater.statusMessage() << endl;
 *     return 1;
 * }
 * \endcode
 *
 * To start a firmware update for MATRIX VISION mvBlueFOX devices the following code will be sufficient:
 * \code
 * mvIMPACT::acquire::FirmwareUpdater fwUpdater( pDev );
 * // if necessary, a specific version for the update can be selected by using the firmwareVersionToUpload property
 * try
 * {
 *     const int FWUpdateResult = fwUpdater.update();
 *     cout << "Result of 'updateFirmware' call: " << ImpactAcquireException::getErrorCodeAsString( FWUpdateResult ) << "." << endl;
 * }
 * catch( const ImpactAcquireException& e )
 * {
 *     cout << "An error occurred while updating the firmware of the device " << pDev->serial.read()
 *          << "(error code: " << e.getErrorCodeAsString() << ").";
 *     return 1;
 * }
 * \endcode
 *
 * A more custom behavior can be accomplished by deriving from the mvIMPACT::acquire::FirmwareUpdater class and re-implementing the various notification functions:
 * \code
 * //-----------------------------------------------------------------------------
 * class MyFirmwareUpdater : public mvIMPACT::acquire::FirmwareUpdater
 * //-----------------------------------------------------------------------------
 * {
 * public:
 *     explicit MyFirmwareUpdater( mvIMPACT::acquire::Device* pDev, bool boForceOverideSameVersion = false, bool boForceDowngrade = false, bool boForceSameVersion = false, bool boForceBreakingChange = false ) : mvIMPACT::acquire::FirmwareUpdater( pDev, boForceOverideSameVersion, boForceDowngrade, boForceSameVersion, boForceBreakingChange ) {}
 *     virtual int onErrorMessage( const double timeElapsed_s ) const
 *     {
 *         cout << "Error: " << statusMessage() << "@" << timeElapsed_s << " s" << endl;
 *         return fuaCancel;
 *     }
 *     virtual int onErasingFlash( const int currentProgress_pc, const double timeElapsed_s ) const
 *     {
 *         cout << "Erasing - Update progress: " << currentProgress_pc << ", time " << timeElapsed_s << " s" << endl;
 *         return fuaContinue;
 *     }
 *     virtual int onUnzippingFirmwareArchive( const int currentProgress_pc, const double timeElapsed_s ) const
 *     {
 *         cout << "Unzipping firmware archive - Update progress: " << currentProgress_pc << ", time " << timeElapsed_s << " s" << endl;
 *         return fuaContinue;
 *     }
 *     virtual int onUpdatingBootProgrammer( const int currentProgress_pc, const double timeElapsed_s ) const
 *     {
 *         cout << "Updating boot programmer - Update progress: " << currentProgress_pc << ", time " << timeElapsed_s << " s" << endl;
 *         return fuaContinue;
 *     }
 *     virtual int onUploadingImage( const int currentProgress_pc, const double timeElapsed_s ) const
 *     {
 *         cout << "Uploading - Update progress: " << currentProgress_pc << ", time " << timeElapsed_s << " s" << endl;
 *         return fuaContinue;
 *     }
 *     virtual int onRebooting( const int currentProgress_pc, const double timeElapsed_s ) const
 *     {
 *         cout << "Rebooting - Update progress: " << currentProgress_pc << ", time " << timeElapsed_s << " s" << endl;
 *         return fuaContinue;
 *     }
 *     virtual int onHardResetRequired( const int currentProgress_pc, const double timeElapsed_s ) const
 *     {
 *         cout << "Rebooting - Update progress: " << currentProgress_pc << ", time " << timeElapsed_s << " s" << endl << "Manual hard reset required." << endl;
 *         return fuaCancel;
 *     }
 *     virtual int onSavingUserSets( const int currentProgress_pc, const double timeElapsed_s ) const
 *     {
 *         cout << "Saving sets - Update progress: " << currentProgress_pc << ", time " << timeElapsed_s << " s" << endl;
 *         return fuaContinue;
 *     }
 *     virtual int onLoadingUserSets( const int currentProgress_pc, const double timeElapsed_s ) const
 *     {
 *         cout << "Loading sets - Update progress: " << currentProgress_pc << ", time " << timeElapsed_s << " s" << endl;
 *         return fuaContinue;
 *     }
 * };
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * To start a firmware update for MATRIX VISION GenICam devices the following code will be sufficient:
 * \code
 * // force the update even if the version of the mvu-file is the same as the one on the device
 * mvIMPACT.acquire.FirmwareUpdater fwUpdater = new mvIMPACT.acquire.FirmwareUpdater( pDev, true );
 * try
 * {
 *     String pathToMVUfile = new String( "someArchive.mvu" );
 *     // start the whole update process
 *     System.out.println( "Result of firmware update call: " + ImpactAcquireException.getErrorCodeAsString( pFWU.update( pathToMVUfile ) ) );
 * }
 * catch( ImpactAcquireException e )
 * {
 *     System.out.println( "An error occured during the firmware update process. Error code: " + e.getErrorCodeAsString() );
 *     System.out.println( "Status: " + pFWU.statusMessage() );
 * }
 * \endcode
 *
 * To start a firmware update for MATRIX VISION mvBlueFOX devices the following code will be sufficient:
 * \code
 * mvIMPACT.acquire.FirmwareUpdater fwUpdater = new mvIMPACT.acquire.FirmwareUpdater( pDev );
 * // if necessary, a specific version for the update can be selected by using the firmwareVersionToUpload property
 * try
 * {
 *     // start the whole update process
 *     System.out.println( "Result of firmware update call: " + ImpactAcquireException.getErrorCodeAsString( pFWU.update() ) );
 * }
 * catch( ImpactAcquireException e )
 * {
 *     System.out.println( "An error occured during the firmware update process. Error code: " + e.getErrorCodeAsString() );
 *     System.out.println( "Status: " + pFWU.statusMessage() );
 * }
 * \endcode
 *
 * A more custom behavior can be accomplished by deriving from the mvIMPACT.acquire.FirmwareUpdater class and re-implementing the various notification functions:
 * \code
 * import mvIMPACT.acquire.*;
 *
 * public class MyFirmwareUpdater extends FirmwareUpdater
 * {
 *     public MyFirmwareUpdater( Device pDev, boolean boForceOverideSameVersion, boolean boForceDowngrade, boolean boKeepUserSets, boolean boForceBreakingChange )
 *     {
 *         super( pDev, boForceOverideSameVersion, boForceDowngrade, boKeepUserSets, boForceBreakingChange );
 *     }
 *     @Override
 *     public int onErrorMessage( double timeElapsed_s )
 *     {
 *         System.out.println( "Error: " + statusMessage() + " @ " + timeElapsed_s + " s"  );
 *         return mvIMPACT.acquire.TFirmwareUpdateAction.fuaContinue;
 *     }
 *     @Override
 *     public int onErasingFlash( int currentProgress_pc, double timeElapsed_s )
 *     {
 *         System.out.println( "Erasing - Update progress: " + currentProgress_pc + ", time " + timeElapsed_s + " s" );
 *         return mvIMPACT.acquire.TFirmwareUpdateAction.fuaContinue;
 *     }
 *     @Override
 *     public int onUnzippingFirmwareArchive( int currentProgress_pc, double timeElapsed_s )
 *     {
 *         System.out.println( "Unzipping firmware archive - Update progress: " + currentProgress_pc + ", time " + timeElapsed_s + " s" );
 *         return mvIMPACT.acquire.TFirmwareUpdateAction.fuaContinue;
 *     }
 *     @Override
 *     public int onUpdatingBootProgrammer( int currentProgress_pc, double timeElapsed_s )
 *     {
 *         System.out.println( "Updating boot programmer - Update progress: " + currentProgress_pc + ", time " + timeElapsed_s + " s" );
 *         return mvIMPACT.acquire.TFirmwareUpdateAction.fuaContinue;
 *     }
 *     @Override
 *     public int onUploadingImage( int currentProgress_pc, double timeElapsed_s )
 *     {
 *         System.out.println( "Uploading - Update progress: " + currentProgress_pc + ", time " + timeElapsed_s + " s" );
 *         return mvIMPACT.acquire.TFirmwareUpdateAction.fuaContinue;
 *     }
 *     @Override
 *     public int onRebooting( int currentProgress_pc, double timeElapsed_s )
 *     {
 *         System.out.println( "Rebooting - Update progress: " + currentProgress_pc + ", time " + timeElapsed_s + " s" );
 *         return mvIMPACT.acquire.TFirmwareUpdateAction.fuaContinue;
 *     }
 *     @Override
 *     public int onHardResetRequired( int currentProgress_pc, double timeElapsed_s )
 *     {
 *         System.out.println( "Rebooting - Update progress: " + currentProgress_pc + ", time " + timeElapsed_s + " s" );
 *         System.out.println( "Manual hard reset required." );
 *         System.out.println( "Status message: " + statusMessage() );
 *         return mvIMPACT.acquire.TFirmwareUpdateAction.fuaCancel;
 *     }
 *     @Override
 *     public int onSavingUserSets( int currentProgress_pc, double timeElapsed_s )
 *     {
 *         System.out.println( "Saving sets - Update progress: " + currentProgress_pc + ", time " + timeElapsed_s + " s" );
 *         return mvIMPACT.acquire.TFirmwareUpdateAction.fuaContinue;
 *     }
 *     @Override
 *     public int onLoadingUserSets( int currentProgress_pc, double timeElapsed_s )
 *     {
 *         System.out.println( "Loading sets - Update progress: " + currentProgress_pc + ", time " + timeElapsed_s + " s" );
 *         return mvIMPACT.acquire.TFirmwareUpdateAction.fuaContinue;
 *     }
 * }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 *
 * To start a firmware update for MATRIX VISION mvBlueFOX devices the following code will be sufficient:
 * \code
 * fwUpdater = acquire.FirmwareUpdater( pDev, False, False, True, False )
 * fwUpdateResult = fwUpdater.update( PATH_TO_FIRMWARE_ARCHIVE.mvu )
 * if FWUpdateResult == 0:
 *    print("Update successful!")
 * else:
 *    print( fwUpdater.statusMessage() )
 * \endcode
 * To start a firmware update for MATRIX VISION mvBlueFOX devices the following code will be sufficient:
 * \code
 * fwUpdater = acquire.FirmwareUpdater( pDev )
 * fwUpdateResult = fwUpdater.update( 52 )
 * if FWUpdateResult == 0:
 *    print("Update successful!")
 * else:
 *    print( fwUpdater.statusMessage() )
 * \endcode
 * A more custom behavior can be accomplished by deriving from the acquire.FirmwareUpdater class and re-implementing the various notification functions:
 * \code
 * from mvIMPACT import acquire
 *
 *  class MyFirmwareUpdater( acquire.FirmwareUpdater ):
 *    def __init__(self, *args):
 *        super(MyFirmwareUpdater, self).__init__(*args)
 *
 *    def onErrorMessage( self, timeElapsed_s ):
 *        print( "Error: " + statusMessage() + " @ " + str(timeElapsed_s) + " s"  )
 *        return acquire.fuaContinue
 *
 *    def onErasingFlash( self, currentProgress_pc, timeElapsed_s ):
 *        print( "Erasing - Update progress: " + str(currentProgress_pc) + ", time " + str(timeElapsed_s) + " s" )
 *        return acquire.fuaContinue
 *
 *    def onUnzippingFirmwareArchive( self, currentProgress_pc, timeElapsed_s ):
 *        print( "Unzipping firmware archive - Update progress: " + str(currentProgress_pc) + ", time " + str(timeElapsed_s) + " s" )
 *        return acquire.fuaContinue
 *
 *    def onUpdatingBootProgrammer( self, currentProgress_pc, timeElapsed_s ):
 *        print( "Updating boot programmer - Update progress: " + str(currentProgress_pc) + ", time " + str(timeElapsed_s) + " s" )
 *        return acquire.fuaContinue
 *
 *    def onUploadingImage( self, currentProgress_pc, timeElapsed_s ):
 *        print( "Uploading - Update progress: " + str(currentProgress_pc) + ", time " + str(timeElapsed_s) + " s" )
 *        return acquire.fuaContinue
 *
 *    def onRebooting( self, currentProgress_pc, timeElapsed_s ):
 *        print( "Rebooting - Update progress: " + str(currentProgress_pc) + ", time " + str(timeElapsed_s) + " s" )
 *        return acquire.fuaContinue
 *
 *    def onHardResetRequired( self, currentProgress_pc, timeElapsed_s ):
 *        print( "Rebooting - Update progress: " + str(currentProgress_pc) + ", time " + str(timeElapsed_s) + " s" )
 *        print( "Manual hard reset required." )
 *        print( "Status message: " + statusMessage() )
 *        return acquire.fuaCancel
 *
 *    def onSavingUserSets( self, currentProgress_pc, timeElapsed_s ):
 *        print( "Saving sets - Update progress: " + str(currentProgress_pc) + ", time " + str(timeElapsed_s) + " s" )
 *        return acquire.fuaContinue
 *
 *    def onLoadingUserSets( self, currentProgress_pc, timeElapsed_s ):
 *        print( "Loading sets - Update progress: " + str(currentProgress_pc) + ", time " + str(timeElapsed_s) + " s" )
 *        return acquire.fuaContinue
 * \endcode

 * \endif

 * \note
 * The following device families are currently supported by this API:
 * \note
 * - GenICam compliant MATRIX VISION imaging devices
 *   - mvBlueCOUGAR-X
 *   - mvBlueCOUGAR-XD
 *   - mvBlueCOUGAR-XT
 *   - mvBlueFOX3
 *   - mvBlueNAOS
 * - Other MATRIX VISION imaging devices
 *   - mvBlueFOX
 *   - mvBlueFOX-MLC/IGC
 *
 * \attention
 * - Do not unplug the device during the update procedure!
 * - Once the firmwareUpdate method call returns an error call the \b mvIMPACT::acquire::FirmwareUpdater::statusMessage function. It will return useful information about the current status (including issues) of the update procedure.
 * - The actual \b mvIMPACT::acquire::FirmwareUpdater::update method did get an additional parameter in version 2.48.0 of this SDK! Make sure you understand the intention of this parameter! When using older versions of this API
 *   make sure \b not attempting to use a device without closing, updating the device list and re-opening it again. Undefined behavior might be the result when not doing so!
 *
 * \since 2.41.0
 * \ingroup CommonInterface
 */
class FirmwareUpdater
//-----------------------------------------------------------------------------
{
private:
#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
    PropertyS        firmwareUpdateFileName_;
    PropertyPtr      firmwareUpdateProgressListenerAddress_;
    PropertyPtr      firmwareUpdateProgressListenerUserDataAddress_;
    PropertyIBoolean firmwareUpdateKeepUserSets_;
    PropertyIBoolean firmwareUpdateForceBreakingChange_;
    PropertyIBoolean firmwareUpdateForceOverrideSameVersion_;
    PropertyIBoolean firmwareUpdateForceDowngrade_;
    PropertyS        firmwareUpdateStatusMessage_;
    Method           updateFirmware_;
    double           timeElapsed_s_;
    Device* pDev_;
    bool             boForceOverideSameVersion_;
    bool             boForceDowngrade_;
    bool             boKeepUserSets_;
    bool             boForceBreakingChange_;
    std::string      lastStatusMessage_;

    void registerFirmwareUpdateCallback( CBP_FIRMWARE_UPDATE pCB, void* pUserData )
    {
        if( firmwareUpdateProgressListenerAddress_.isValid() && firmwareUpdateProgressListenerUserDataAddress_.isValid() )
        {
            function_cast<CBP_FIRMWARE_UPDATE> pFunc;
            pFunc.pO = pCB;
            firmwareUpdateProgressListenerAddress_.write( pFunc.pI );
            firmwareUpdateProgressListenerUserDataAddress_.write( pUserData );
        }
    }
    void unregisterFirmwareUpdateCallback( void )
    {
        if( firmwareUpdateProgressListenerAddress_.isValid() && firmwareUpdateProgressListenerUserDataAddress_.isValid() )
        {
            firmwareUpdateProgressListenerAddress_.write( 0 );
            firmwareUpdateProgressListenerUserDataAddress_.write( 0 );
        }
    }
    static int infoCallback( void* pUserData, FirmwareUpdateStatusData* pFwUpdateData, unsigned long int /*fwUpdateDataSize*/ )
    {
        if( !pUserData )
        {
            return fuaContinue;
        }
        FirmwareUpdater* pFirmwareUpdater = reinterpret_cast<FirmwareUpdater*>( pUserData );
        pFirmwareUpdater->setTimeElapsed( pFwUpdateData->timeElapsed_s );
        switch( pFwUpdateData->updateStep )
        {
        case fusErasingFlash:
            return pFirmwareUpdater->onErasingFlash( pFwUpdateData->progressPercent, pFwUpdateData->timeElapsed_s );
        case fusUpdatingBootProgrammer:
            return pFirmwareUpdater->onUpdatingBootProgrammer( pFwUpdateData->progressPercent, pFwUpdateData->timeElapsed_s );
        case fusUnzippingFirmwareArchive:
            return pFirmwareUpdater->onUnzippingFirmwareArchive( pFwUpdateData->progressPercent, pFwUpdateData->timeElapsed_s );
        case fusUploadingFirmware:
            return pFirmwareUpdater->onUploadingImage( pFwUpdateData->progressPercent, pFwUpdateData->timeElapsed_s );
        case fusRebootingDevice:
            return pFirmwareUpdater->onRebooting( pFwUpdateData->progressPercent, pFwUpdateData->timeElapsed_s );
        case fusHardResetRequired:
            return pFirmwareUpdater->onHardResetRequired( pFwUpdateData->progressPercent, pFwUpdateData->timeElapsed_s );
        case fusSavingUserSets:
            return pFirmwareUpdater->onSavingUserSets( pFwUpdateData->progressPercent, pFwUpdateData->timeElapsed_s );
        case fusLoadingUserSets:
            return pFirmwareUpdater->onLoadingUserSets( pFwUpdateData->progressPercent, pFwUpdateData->timeElapsed_s );
        case fusErrorMessage:
            return pFirmwareUpdater->onErrorMessage( pFwUpdateData->timeElapsed_s );
        }
        return fuaContinue;
    }
    bool bindProperties( void )
    {
        bool needsReInitAfterUpdate = false;
        ComponentLocator l( pDev_->hDev() );
        l.bindComponent( updateFirmware_, "UpdateFirmware@i" );
        if( !updateFirmware_.isValid() )
        {
            needsReInitAfterUpdate = true;
            if( !pDev_->isOpen() )
            {
                pDev_->open();
            }
            DeviceComponentLocator locator( pDev_, dltSystemSettings );
            locator.bindComponent( firmwareUpdateKeepUserSets_, "KeepUserSets" );
            locator.bindComponent( firmwareUpdateForceBreakingChange_, "ForceBreakingChange" );
            locator.bindComponent( firmwareUpdateForceOverrideSameVersion_, "ForceOverrideSameVersion" );
            locator.bindComponent( firmwareUpdateForceDowngrade_, "ForceDowngrade" );
            locator.bindComponent( firmwareUpdateFileName_, "FileName" );
            locator.bindComponent( firmwareUpdateStatusMessage_, "UpdateStatusMessage" );
            locator.bindComponent( firmwareUpdateProgressListenerAddress_, "ProgressListenerAddress" );
            locator.bindComponent( firmwareUpdateProgressListenerUserDataAddress_, "ProgressListenerUserDataAddress" );
            locator.bindComponent( updateFirmware_, "UpdateDeviceFirmware@i" );
        }

        if( firmwareUpdateForceOverrideSameVersion_.isValid() )
        {
            firmwareUpdateForceOverrideSameVersion_.write( boForceOverideSameVersion_ ? bTrue : bFalse );
        }
        if( firmwareUpdateForceDowngrade_.isValid() )
        {
            firmwareUpdateForceDowngrade_.write( boForceDowngrade_ ? bTrue : bFalse );
        }
        if( firmwareUpdateKeepUserSets_.isValid() )
        {
            firmwareUpdateKeepUserSets_.write( boKeepUserSets_ ? bTrue : bFalse );
        }
        if( firmwareUpdateForceBreakingChange_.isValid() )
        {
            firmwareUpdateForceBreakingChange_.write( boForceBreakingChange_ ? bTrue : bFalse );
        }
        lastStatusMessage_ = firmwareUpdateStatusMessage_.isValid() ? firmwareUpdateStatusMessage_.read() : std::string( "STATUS PROPERTY NOT AVAILABLE" );
        return needsReInitAfterUpdate;
    }
    // do not allow assignments
    FirmwareUpdater& operator=( const FirmwareUpdater& );
    // do not allow copy construction
    FirmwareUpdater( const FirmwareUpdater& src );

protected:
    void setTimeElapsed( double time_s )
    {
        timeElapsed_s_ = time_s;
    }
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS)
public:
    /// \brief Creates a new <b>mvIMPACT::acquire::FirmwareUpdater</b> object.
    explicit FirmwareUpdater(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        mvIMPACT::acquire::Device* pDev,
        /// [in] A boolean value which defines if updates using the same version as installed on the camera should be allowed.
        bool boForceOverideSameVersion = false,
        /// [in] A boolean value which defines if updates using an older version as installed on the camera should be allowed.
        bool boForceDowngrade = false,
        /// [in] A boolean value which defines if the user sets of the device will be kept or will be deleted during the update.
        bool boKeepUserSets = true,
        /// [in] A boolean value which defines if updates to versions which will deliver interface breaking changes will be allowed. Setting this value to \c true will also update a device which after the update
        /// might have a different interface. See documentation for additional information about breaking changes in firmware versions(there are not too many)!
        bool boForceBreakingChange = false ) : timeElapsed_s_( 0 ), pDev_( pDev ),
        boForceOverideSameVersion_( boForceOverideSameVersion ), boForceDowngrade_( boForceDowngrade ), boKeepUserSets_( boKeepUserSets ), boForceBreakingChange_( boForceBreakingChange ), lastStatusMessage_( "Idle" )
    {
        ComponentLocator l( pDev_->hDev() );
        l.bindComponent( updateFirmware_, "UpdateFirmware@i" );
        if( updateFirmware_.isValid() )
        {
            l.bindComponent( firmwareVersionToUpload, "FirmwareVersionToUpload" );
        }
    }
    virtual ~FirmwareUpdater() {}
    /// \brief This function will be called once a message is waiting to be passed to the user.
    /**
    * Re-implement this function in a derived class in order to implement a custom behaviour.
    * \return
    * - <b>mvIMPACT::acquire::fuaContinue</b> if the current update shall continue.
    * - <b>mvIMPACT::acquire::fuaCancel</b> otherwise.
    */
    virtual int onErrorMessage(
        /// [in] The total time elapsed since starting the update process (in seconds).
        const double timeElapsed_s ) const
    {
        ( void ) timeElapsed_s;
        return fuaContinue;
    }
    /// \brief This function will be called once the devices flash memory is erased.
    /**
    * Re-implement this function in a derived class in order to implement a custom behaviour.
    *
    * \note Only some device types require this step so this callback might not be called for every device type.
    *
    * \return
    * - <b>mvIMPACT::acquire::fuaContinue</b> if the current update shall continue.
    * - <b>mvIMPACT::acquire::fuaCancel</b> otherwise.
    */
    virtual int onErasingFlash(
        /// [in] The current progress of the erase operation (in percent).
        const int currentProgress_pc,
        /// [in] The total time elapsed since starting the update process (in seconds).
        const double timeElapsed_s ) const
    {
        ( void ) currentProgress_pc;
        ( void ) timeElapsed_s;
        return fuaContinue;
    }
    /// \brief This function will be called once firmware archive (*.mvu) is unzipped to provide the correct firmware file.
    /**
    * Re-implement this function in a derived class in order to implement a custom behaviour.
    *
    * \return
    * - <b>mvIMPACT::acquire::fuaContinue</b> if the current update shall continue.
    * - <b>mvIMPACT::acquire::fuaCancel</b> otherwise.
    */
    virtual int onUnzippingFirmwareArchive(
        /// [in] The current progress of the unzip operation (in percent).
        const int currentProgress_pc,
        /// [in] The total time elapsed since starting the update process (in seconds).
        const double timeElapsed_s ) const
    {
        ( void ) currentProgress_pc;
        ( void ) timeElapsed_s;
        return fuaContinue;
    }
    /// \brief This function will be called once the boot programmer of an mvBlueFOX3 camera is updated.
    /**
    * Re-implement this function in a derived class in order to implement a custom behaviour.
    *
    * \note
    * - Only mvBlueFOX3 cameras require this step so this callback might not be called in case of different device types.
    * - BootProgrammer updates won't be necessary often, so this callback will not apply in every firmware update process.
    *
    * \return
    * - <b>mvIMPACT::acquire::fuaContinue</b> if the current update shall continue.
    * - <b>mvIMPACT::acquire::fuaCancel</b> otherwise.
    */
    virtual int onUpdatingBootProgrammer(
        /// [in] The current progress of the update operation (in percent).
        const int currentProgress_pc,
        /// [in] The total time elapsed since starting the update process (in seconds).
        const double timeElapsed_s ) const
    {
        ( void ) currentProgress_pc;
        ( void ) timeElapsed_s;
        return fuaContinue;
    }
    /// \brief This function will be called once the actual firmware file is uploaded to the device's flash memory.
    /**
    * Re-implement this function in a derived class in order to implement a custom behaviour.
    *
    * \note
    * - Depending on the device type this step might take a few seconds up to a few minutes.
    * - The callback will be called several times during the upload.
    * - Each time there was a progress of 5 percent this callback will be called.
    *
    * \return
    * - <b>mvIMPACT::acquire::fuaContinue</b> if the current update shall continue.
    * - <b>mvIMPACT::acquire::fuaCancel</b> otherwise.
    */
    virtual int onUploadingImage(
        /// [in] The current progress of the upload operation (in percent).
        const int currentProgress_pc,
        /// [in] The total time elapsed since starting the update process (in seconds).
        const double timeElapsed_s ) const
    {
        ( void ) currentProgress_pc;
        ( void ) timeElapsed_s;
        return fuaContinue;
    }
    /// \brief This function will be called once the device reboots to make sure the new firmware is applied to the device.
    /**
    * Re-implement this function in a derived class in order to implement a custom behaviour.
    *
    * \note Returning <b>mvIMPACT::acquire::fuaCancel</b> on this callback will stop the upgrade process without rebooting the device. However, a new firmware is not active until a reboot or hard reset has been performed.
    *
    * \return
    * - <b>mvIMPACT::acquire::fuaContinue</b> if the current update shall continue.
    * - <b>mvIMPACT::acquire::fuaCancel</b> otherwise.
    */
    virtual int onRebooting(
        /// [in] The current progress of the reboot operation (in percent).
        const int currentProgress_pc,
        /// [in] The total time elapsed since starting the update process (in seconds).
        const double timeElapsed_s ) const
    {
        ( void ) currentProgress_pc;
        ( void ) timeElapsed_s;
        return fuaContinue;
    }
    /// \brief This function will be called once the device reboots and a manual hard reset is required.
    /**
    * Re-implement this function in a derived class in order to implement a custom behaviour.
    *
    * \note If this function is called, a power cycle is inevitable. Otherwise the new firmware may be broken. The default is to stop the update at this point, so that the user can manually disconnect the power source.
    *
    * \return
    * - <b>mvIMPACT::acquire::fuaContinue</b> if the current update shall continue.
    * - <b>mvIMPACT::acquire::fuaCancel</b> otherwise.
    */
    virtual int onHardResetRequired(
        /// [in] The current progress of the reboot operation (in percent).
        const int currentProgress_pc,
        /// [in] The total time elapsed since starting the update process (in seconds).
        const double timeElapsed_s ) const
    {
        ( void ) currentProgress_pc;
        ( void ) timeElapsed_s;
        return fuaCancel;
    }
    /// \brief This function will be called when the settings of the device are stored before updating the firmware.
    /**
    * Re-implement this function in a derived class in order to implement a custom behaviour.
    *
    * This callback will only be called when user sets shall be available after the update. This can be specified by setting the \b boKeepUserSets flag upon construction of this object.
    *
    * \return
    * - <b>mvIMPACT::acquire::fuaContinue</b> if the current update shall continue.
    * - <b>mvIMPACT::acquire::fuaCancel</b> otherwise.
    */
    virtual int onSavingUserSets(
        /// [in] The current progress of the store operation (in percent).
        const int currentProgress_pc,
        /// [in] The total time elapsed since starting the update process (in seconds).
        const double timeElapsed_s ) const
    {
        ( void ) currentProgress_pc;
        ( void ) timeElapsed_s;
        return fuaContinue;
    }
    /// \brief This function will be called when the settings of the device are written back after updating the firmware.
    /**
    * Re-implement this function in a derived class in order to implement a custom behaviour.
    *
    * This callback will only be called when user sets shall be available after the update. This can be specified by setting the \b boKeepUserSets flag upon construction of this object.
    *
    * \return
    * - <b>mvIMPACT::acquire::fuaContinue</b> if the current update shall continue.
    * - <b>mvIMPACT::acquire::fuaCancel</b> otherwise.
    */
    virtual int onLoadingUserSets(
        /// [in] The current progress of the load operation (in percent).
        const int currentProgress_pc,
        /// [in] The total time elapsed since starting the update process (in seconds).
        const double timeElapsed_s ) const
    {
        ( void ) currentProgress_pc;
        ( void ) timeElapsed_s;
        return fuaContinue;
    }
    /// \brief A function to start the firmware update process.
    /**
    * This function is intended to be used to update MATRIX VISION imaging and image capture devices.
    * \note
    * - Once this function returns, the device will be closed! All objects previously created using the \b mvIMPACT::acquire::Device pointer must be recreated then.
    * - For mvBlueFOX device this function needs to be called \b without passing any parameters to the function!
    *
    * \return
    *  - <b>mvIMPACT::acquire::DMR_NO_ERROR</b> if successful.
    *  - A negative error code of type <b>::TDMR_ERROR</b> otherwise.
    */
    TDMR_ERROR update(
        /// [in] Path to the file which should be used to update the device. Can be empty if no update archives are needed for the device.
        const std::string& archivePath = "",
        /// [in] Can be set to false in order to save time when updating multiple devices in one go. Please note that as soon as at least one GenICam
        /// device is part of these multiple devices either \b mvIMPACT::acquire::DeviceManager::updateDeviceList \b must be called \b or every instance
        /// to mvIMPACT::acquire::DeviceManager in the current process needs to be destroyed afterwards before any of those GenICam
        /// devices can be used again!
        const bool boUpdateDataAsNeeded = true )
    {
        if( pDev_->isOpen() )
        {
            pDev_->close();
        }
        const bool needsReInitAfterUpdate = bindProperties();
        if( !updateFirmware_.isValid() )
        {
            return DMR_FEATURE_NOT_AVAILABLE;
        }
        if( firmwareUpdateFileName_.isValid() )
        {
            firmwareUpdateFileName_.writeS( archivePath );
        }
        registerFirmwareUpdateCallback( infoCallback, this );
        const TDMR_ERROR returnVal = static_cast<TDMR_ERROR>( updateFirmware_.call() );
        unregisterFirmwareUpdateCallback();
        lastStatusMessage_ = firmwareUpdateStatusMessage_.isValid() ? firmwareUpdateStatusMessage_.read() : std::string( "STATUS PROPERTY NOT AVAILABLE" );
        if( needsReInitAfterUpdate )
        {
            pDev_->close();
            if( boUpdateDataAsNeeded )
            {
                DeviceManager devMgr;
                devMgr.updateDeviceList(); // Refresh GenICam XML file related properties as well as the firmware version properties.
            }
        }
        return returnVal;
    }
    /// \brief Returns the current status from the status property
    std::string statusMessage( void ) const
    {
        return firmwareUpdateStatusMessage_.isValid() ? firmwareUpdateStatusMessage_.read() : lastStatusMessage_;
    }
    /// \brief A method to receive the time in seconds since the update process has been started
    /**
     * \return The time elapsed since the firmware update currently running has been started.
     */
    double getTimeElapsed( void ) const
    {
        return timeElapsed_s_;
    }
    /// \brief A function to check the integrity of the firmware running on a device.
    /**
    * This function is intended to be used to check the firmware integrity of MATRIX VISION imaging and image capture devices only.
    * Most MATRIX VISION imaging and image capture devices are capable of calculating a hash from the firmware image which is currently running on the device. In addition to
    * that firmware archives for imaging devices provided by MATRIX VISION contain hashes for all the firmware images contained in the update archive. Comparing these
    * 2 hashes will provide additional security when an application wants to make sure that the firmware running on the device is undamaged.
    *
    * \note
    * - When calling this function, the firmware archive path passed to it must contain the exact same firmware that is running on the
    * device.
    * - This feature is currently only available for most MATRIX VISION GenICam compliant devices.
    * - Once this function returns, the device will be closed! All objects previously created using the mvIMPACT::acquire::Device pointer must be recreated then.
    * - If the function returns a negative code of type \b mvIMPACT::acquire::TDMR_ERROR, the status string will contain a more specific explanation about the root cause for the issue.
    *
    * \since 2.47.0
    *
    * \return
    *  - <b>mvIMPACT::acquire::DMR_NO_ERROR</b> if successful.
    *  - A negative error code of type <b>::TDMR_ERROR</b> otherwise.
    */
    static TDMR_ERROR verifyFirmwareChecksum(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] Path to the file which should be used to compare the firmware checksum from with the firmware currently running on the device.
        const std::string& archivePath,
        /// [out] Pointer to a string receiving additional information about the outcome of the operation. This can be 0 if no one is interested in status information.
        std::string* pStatusMessage = 0 )
    {
        if( pDev->isOpen() )
        {
            pDev->close();
        }
        try
        {
            pDev->interfaceLayout.write( dilGenICam );
        }
        catch( const ImpactAcquireException& )
        {
            return DMR_FEATURE_NOT_AVAILABLE;
        }

        DeviceComponentLocator locator( pDev, dltSystemSettings );
        Method verifyFirmwareChecksum;
        locator.bindComponent( verifyFirmwareChecksum, "VerifyDeviceFirmwareChecksum@i" );
        if( !verifyFirmwareChecksum.isValid() )
        {
            pDev->close();
            return DMR_FEATURE_NOT_AVAILABLE;
        }

        PropertyS firmwareUpdateFileName;
        PropertyS firmwareUpdateStatusMessage;
        locator.bindComponent( firmwareUpdateFileName, "FileName" );
        locator.bindComponent( firmwareUpdateStatusMessage, "UpdateStatusMessage" );
        firmwareUpdateFileName.writeS( archivePath );
        const TDMR_ERROR returnVal = static_cast<TDMR_ERROR>( verifyFirmwareChecksum.call() );
        if( pStatusMessage && firmwareUpdateStatusMessage.isValid() )
        {
            *pStatusMessage = firmwareUpdateStatusMessage.read();
        }
        pDev->close();
        return returnVal;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
        // *INDENT-ON*
    /// \brief An enumerated integer property containing a list of available firmware versions.
    /**
     * \note
     * This feature currently is only available for \b mvBlueFOX devices since here the firmware is part of the driver library.
     * So no additional archive is needed, but the desired firmware version to upload into the device's non-volatile memory can
     * be selected by writing to this property before calling the \b mvIMPACT::acquire::FirmwareUpdater::update function.
     */
    PropertyI firmwareVersionToUpload;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
        // *INDENT-OFF*
};

namespace GenICam
{

class GenTLDriverConfigurator;

//-----------------------------------------------------------------------------
/// \brief A class that contains items to configure the behaviour of the %GenICam GenTL driver stack.
/**
 * This class contains items to configure the enumeration behaviour of a third party GenTL producer library.
 *
*  \note
 * Instances of this class cannot be constructed directly. To get access the functions \b mvIMPACT::acquire::GenICam::GenTLDriverConfigurator::createProducerConfiguration,
 * \b mvIMPACT::acquire::GenICam::GenTLDriverConfigurator::getProducerConfigurations
 * or \b mvIMPACT::acquire::GenICam::GenTLDriverConfigurator::getProducerConfiguration must be used.
 * must be used.
 *
 * For a comprehensive usage example see the description of the class \b mvIMPACT::acquire::GenICam::GenTLDriverConfigurator.
 *
 * \sa
 * \ref CommonCases_mvGenTLConsumerSetup
 *
 * \since 2.34.0
 * \ingroup GenICamInterfaceProducer
 */
class GenTLProducerConfiguration : public mvIMPACT::acquire::ComponentCollection
//-----------------------------------------------------------------------------
{
    friend class GenTLDriverConfigurator;

    Method createProducerInterfaceConfigurationEntry_;
    Method deleteProducerInterfaceConfigurationEntry_;

    void bindProperties( HLIST hList )
    {
        {
            Component it( hList );
            ComponentLocator locator( it.parent().parent().hObj() );
            locator.bindComponent( createProducerInterfaceConfigurationEntry_, "CreateProducerInterfaceConfigurationEntry@iss" );
            locator.bindComponent( deleteProducerInterfaceConfigurationEntry_, "DeleteProducerInterfaceConfigurationEntry@iss" );
        }
        {
            ComponentLocator locator( hList );
            locator.bindComponent( enumerationEnable, "EnumerationEnable" );
        }
    }
    explicit GenTLProducerConfiguration( HLIST hList ) : mvIMPACT::acquire::ComponentCollection( hList ),
        createProducerInterfaceConfigurationEntry_(), deleteProducerInterfaceConfigurationEntry_(),
        enumerationEnable()
    {
        bindProperties( hList );
    }
public:
    /// \brief Constructs a new \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration from an existing one.
    GenTLProducerConfiguration(
        /// [in] A constant reference to the \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration object, this object shall be created from
        const GenTLProducerConfiguration& src ) : ComponentCollection( src.hObj() ),
        createProducerInterfaceConfigurationEntry_( src.createProducerInterfaceConfigurationEntry_ ),
        deleteProducerInterfaceConfigurationEntry_( src.deleteProducerInterfaceConfigurationEntry_ ),
        enumerationEnable( src.enumerationEnable ) {}
    /// \brief Allows assignments of \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration objects.
    GenTLProducerConfiguration& operator=( const GenTLProducerConfiguration& rhs )
    {
        if( this != &rhs )
        {
            ComponentCollection::operator=( rhs );
            bindProperties( rhs.hObj() );
        }
        return *this;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the enumeration behavior this particular GenTL producer.
    /**
     * If this property is set to \b mvIMPACT::acquire::bTrue ALL interfaces of this producer will be enumerated
     * unless a specific interface enumeration behaviour has been set to \b mvIMPACT::acquire::iebForceIgnore.
     *
     * Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TBoolean.
     */
    PropertyIBoolean enumerationEnable;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
    /// \brief Returns the interface enumeration behaviour property for the specified interface ID for this particular GenTL producer.
    /**
     *
     * Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TInterfaceEnumerationBehaviour.
     *
     * \note If no entry for the specified interface ID exists an exception will be thrown.
     *
     * \return The enumeration behaviour configuration property for the specified interface
     */
    PropertyIInterfaceEnumerationBehaviour getInterfaceEnumerationBehaviour(
        /// [in] The interface ID previously passed e.g. to the \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration::createProducerInterfaceConfigurationEntry function.
        const std::string& interfaceID ) const
    {
        ComponentLocator locator( hObj(), "Interfaces" );
        const HOBJ hObj = locator.findComponent( interfaceID, 0, 1 );
        if( hObj == INVALID_ID )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, static_cast<TDMR_ERROR>( PROPHANDLING_COMPONENT_NOT_FOUND ), "Couldn't find 'InterfaceEnumerationBehaviour' for interface '" + interfaceID + "' of producer '" + getProducerName() + "'" );
        }
        return PropertyIInterfaceEnumerationBehaviour( hObj );
    }
    /// \brief Returns a map containing all the configured interface IDs and their corresponding enumeration behaviour properties for this particular GenTL producer.
    /**
     * The returned map will only contain interface IDs which have explicitly been configured (e.g. by a previous call to
     * \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration::createProducerInterfaceConfigurationEntry. Certain third party
     * interfaces might also have an entry in this map (e.g. if there is a MATRIX VISION GenICam GenTL producer supporting the same technology present
     * on the system).
     *
     * Valid values for the properties are defined by the enumeration \b mvIMPACT::acquire::TInterfaceEnumerationBehaviour.
     *
     * \return A map containing all the configured interface IDs and their corresponding enumeration behaviour properties for this particular GenTL producer
     */
    std::map<std::string, PropertyIInterfaceEnumerationBehaviour> getInterfaceEnumerationBehaviours( void ) const
    {
        std::map<std::string, PropertyIInterfaceEnumerationBehaviour> m;
        ComponentLocator locator( hObj(), "Interfaces" );
        Component it( locator.searchbase_id() );
        it = it.firstChild();
        while( it.isValid() )
        {
            m.insert( make_pair( it.name(), PropertyIInterfaceEnumerationBehaviour( it.hObj() ) ) );
            it++;
        }
        return m;
    }
    /// \brief Creates a new interface configuration entry for this producers configuration.
    /**
     * Usually the parameter passed to this function will be one of the interface IDs of the producers list of reported interfaces
     * in order to configure this particular interface. However it can also be an identifier for an interface not yet connected to the
     * system or not yet available to the producer. No internal checks are performed regarding the validity of the given interface ID.
     *
     * \note If an entry with the same interface ID already exists an exception will be thrown.
     */
    PropertyIInterfaceEnumerationBehaviour createProducerInterfaceConfigurationEntry(
        /// [in] The interface ID to create the configuration entry for.
        const std::string& interfaceID )
    {
        Component it( hObj() );
        std::vector<std::string> parameters;
        parameters.push_back( it.name() );
        parameters.push_back( interfaceID );
        const int result = createProducerInterfaceConfigurationEntry_.call( parameters );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, static_cast<TDMR_ERROR>( result ), "Failed to create interface configuration entry" );
        }
        ComponentLocator locator( hObj(), "Interfaces" );
        return PropertyIInterfaceEnumerationBehaviour( locator.findComponent( interfaceID ) );
    }
    /// \brief Deletes an interface configuration entry from this producers configuration.
    /**
     * \note If no entry for the specified interface can be found an exception will be thrown.
     */
    void deleteProducerInterfaceConfigurationEntry(
        /// [in] The exact interface ID of the producers list of reported interfaces to delete the configuration entry for.
        const std::string& interfaceID )
    {
        Component it( hObj() );
        std::vector<std::string> parameters;
        parameters.push_back( it.name() );
        parameters.push_back( interfaceID );
        const int result = deleteProducerInterfaceConfigurationEntry_.call( parameters );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, static_cast<TDMR_ERROR>( result ), "Failed to delete interface configuration entry" );
        }
    }
    /// \brief Returns the name of the GenTL producer associated with this configuration object.
    /**
     * \return The name of the GenTL producer associated with this configuration object.
     */
    std::string getProducerName( void ) const
    {
        return Component( hObj() ).name();
    }
};

//-----------------------------------------------------------------------------
/// \brief A class that contains items to configure the behaviour of the %GenICam GenTL driver stack.
/**
 * This class contains items e.g. to configure the enumeration behaviour of third party GenTL producer libraries.
 *
 * Since version 2.32.0 mvIMPACT Acquire has built-in support for third party GenTL producer libraries.
 * The latest version of the GenTL specification can be found here: https://www.emva.org/standards-technology/genicam/.
 *
 * Detection of GenTL producer libraries works by evaluating the \c GENICAM_GENTL32_PATH environment variable
 * within a 32-bit process or the \c GENICAM_GENTL64_PATH variable in a 64-bit process. This variable contains
 * a list of directories that might potentially contain GenTL producer libraries. These libraries use a
 * the file extension \c .cti and export a defined interface.
 *
 * All libraries that fulfill these requirements will be loaded into the mvIMPACT Acquire process. By default
 * all these libraries will then also be enumerated for connected/bound devices. The only exception will be
 * if a third party producer is found that reports an interface supporting the same technology as one delivered
 * by mvIMPACT Acquire (e.g. for the GigE Vision or USB3 Vision standard). These interfaces by default will not
 * be enumerated.
 *
 * The purpose of this class now is to allow an application to modify this behaviour. This might be beneficial for
 * several reasons:
 *
 * - a certain third party library on the system has negative impact on the overall stability of the process
 * - there are so many third party libraries on the system that enumeration takes a very long time but the application does not want to access devices reported by these third party libraries
 * - multiple producers support the same device resulting in very long and confusing device lists
 * - etc.
 *
 * To exclude a certain producer from enumeration first an mvIMPACT::acquire::GenICam::GenTLProducerConfiguration entry for that
 * producer must be created and then the \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration::enumerationEnable
 * property for this producer must be set to \b mvIMPACT::acquire::bFalse.
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 * // Assuming a certain 'ACME.producer.cti' producer has been found somewhere in the GENICAM_GENTLXY_PATH.
 * GenTLDriverConfigurator driverConfigurator;
 * if( !driverConfigurator.hasProducerConfiguration( "ACME.producer.cti" ) )
 * {
 *   driverConfigurator.createProducerConfiguration( "ACME.producer.cti" ); // the 'enumerationEnable' will be false by default!
 * }
 * else
 * {
 *   driverConfigurator.getProducerConfiguration( "ACME.producer.cti" ).enumerationEnable.write( bFalse );
 * }
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 * // Assuming a certain 'ACME.producer.cti' producer has been found somewhere in the GENICAM_GENTLXY_PATH.
 * GenTLDriverConfigurator driverConfigurator = new GenTLDriverConfigurator();
 * if( !driverConfigurator.hasProducerConfiguration( "ACME.producer.cti" ) )
 * {
 *   driverConfigurator.createProducerConfiguration( "ACME.producer.cti" ); // the 'enumerationEnable' will be false by default!
 * }
 * else
 * {
 *    driverConfigurator.getProducerConfiguration( "ACME.producer.cti" ).enumerationEnable.write( TBoolean.bFalse );
 * }
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 * # Assuming a certain 'ACME.producer.cti' producer has been found somewhere in the GENICAM_GENTLXY_PATH.
 * driverConfigurator = acquire.GenTLDriverConfigurator()
 * if driverConfigurator.hasProducerConfiguration("ACME.producer.cti") == False:
 *   driverConfigurator.createProducerConfiguration("ACME.producer.cti") # the 'enumerationEnable' will be false by default!
 * else:
 *    driverConfigurator.getProducerConfiguration("ACME.producer.cti").enumerationEnable.write(acquire.bFalse)
 * \endcode
 * \endif
 *
 * To exclude a certain interface from a producer from enumeration an \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration::enumerationEnable
 * property for this producer can be set to \b mvIMPACT::acquire::bFalse and the interface enumeration behaviour should be set to
 * \b mvIMPACT::acquire::iebForceEnumerate.
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 * // Assuming a certain 'ACME.producer.cti' producer has been found somewhere in the GENICAM_GENTLXY_PATH.
 * GenTLDriverConfigurator driverConfigurator;
 * GenTLProducerConfiguration configuration( driverConfigurator.hasProducerConfiguration( "ACME.producer.cti" ) ? driverConfigurator.getProducerConfiguration( "ACME.producer.cti" ) : driverConfigurator.createProducerConfiguration( "ACME.producer.cti" ) );
 * configuration.enumerationEnable.write( bTrue ); // switch on ALL interfaces...
 * configuration.createProducerInterfaceConfigurationEntry( "ACME.interface0.ID" ).write( iebForceIgnore ); // ... except this one
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 * // Assuming a certain 'ACME.producer.cti' producer has been found somewhere in the GENICAM_GENTLXY_PATH.
 * GenTLDriverConfigurator driverConfigurator = new GenTLDriverConfigurator();
 * GenTLProducerConfiguration configuration = null;
 * if( driverConfigurator.hasProducerConfiguration( "ACME.producer.cti" ) )
 * {
 *   configuration = driverConfigurator.getProducerConfiguration( "ACME.producer.cti" );
 * }
 * else
 * {
 *   configuration = driverConfigurator.createProducerConfiguration( "ACME.producer.cti" );
 * }
 * configuration.getEnumerationEnable().write( TBoolean.bTrue ); // switch on ALL interfaces...
 * configuration.createProducerInterfaceConfigurationEntry( "ACME.interface0.ID" ).write( TInterfaceEnumerationBehaviour.iebForceIgnore ); // ... except this one
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 * # Assuming a certain 'ACME.producer.cti' producer has been found somewhere in the GENICAM_GENTLXY_PATH.
 * driverConfigurator = acquire.GenTLDriverConfigurator()
 * GenTLProducerConfiguration configuration = None
 * if driverConfigurator.hasProducerConfiguration("ACME.producer.cti"):
 *   configuration = driverConfigurator.getProducerConfiguration("ACME.producer.cti")
 * else:
 *   configuration = driverConfigurator.createProducerConfiguration("ACME.producer.cti")
 * configuration.enumerationEnable.write(acquire.bTrue) # switch on ALL interfaces...
 * configuration.createProducerInterfaceConfigurationEntry("ACME.interface0.ID").write(acquire.iebForceIgnore) # ... except this one
 * \endcode
 * \endif
 *
 * The same thing can be done the other way round:
 *
 * \if DOXYGEN_CPP_DOCUMENTATION
 * \code
 * // Assuming a certain 'ACME.producer.cti' producer has been found somewhere in the GENICAM_GENTLXY_PATH and only a certain interface shall be enumerated.
 * GenTLDriverConfigurator driverConfigurator;
 * GenTLProducerConfiguration configuration( driverConfigurator.hasProducerConfiguration( "ACME.producer.cti" ) ? driverConfigurator.getProducerConfiguration( "ACME.producer.cti" ) : driverConfigurator.createProducerConfiguration( "ACME.producer.cti" ) );
 * configuration.enumerationEnable.write( bFalse ); // switch off ALL interfaces...
 * configuration.createProducerInterfaceConfigurationEntry( "ACME.interface0.ID" ).write( iebForceEnumerate ); // ... except this one
 * \endcode
 * \elseif DOXYGEN_JAVA_DOCUMENTATION
 * \code
 * GenTLDriverConfigurator driverConfigurator = new GenTLDriverConfigurator();
 * GenTLProducerConfiguration configuration = null;
 * if( driverConfigurator.hasProducerConfiguration( "ACME.producer.cti" ) )
 * {
 *   configuration = driverConfigurator.getProducerConfiguration( "ACME.producer.cti" );
 * }
 * else
 * {
 *   configuration = driverConfigurator.createProducerConfiguration( "ACME.producer.cti" );
 * }
 * configuration.getEnumerationEnable().write( TBoolean.bFalse ); // switch on ALL interfaces...
 * configuration.createProducerInterfaceConfigurationEntry( "ACME.interface0.ID" ).write( TInterfaceEnumerationBehaviour.iebForceEnumerate ); // ... except this one
 * \endcode
 * \elseif DOXYGEN_PYTHON_DOCUMENTATION
 * \code
 * # Assuming a certain 'ACME.producer.cti' producer has been found somewhere in the GENICAM_GENTLXY_PATH.
 * driverConfigurator = acquire.GenTLDriverConfigurator()
 * GenTLProducerConfiguration configuration = None
 * if driverConfigurator.hasProducerConfiguration("ACME.producer.cti"):
 *   configuration = driverConfigurator.getProducerConfiguration("ACME.producer.cti")
 * else:
 *   configuration = driverConfigurator.createProducerConfiguration("ACME.producer.cti")
 * configuration.enumerationEnable.write(acquire.bFalse) # switch on ALL interfaces...
 * configuration.createProducerInterfaceConfigurationEntry("ACME.interface0.ID").write(acquire.iebForceEnumerate) # ... except this one
 * \endcode
 * \endif
 * \sa
 * \ref CommonCases_mvGenTLConsumerSetup
 *
 * \since 2.34.0
 * \ingroup GenICamInterfaceProducer
 */
class GenTLDriverConfigurator : public mvIMPACT::acquire::ComponentCollection
//-----------------------------------------------------------------------------
{
private:
    Method createProducerConfigurationEntry_;
    Method deleteProducerConfigurationEntry_;
    Method createProducerInterfaceConfigurationEntry_;

    void bindProperties( void )
    {
        HLIST hList;
        TDMR_ERROR result;
        if( ( result = DMR_FindList( INVALID_ID, "mvGenTLConsumer", dmltDeviceDriverLib, 0, &hList ) ) != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result, "Couldn't find list 'mvGenTLConsumer'(type: dmltDeviceDriverLib)" );
        }
        mvIMPACT::acquire::ComponentLocator locator( hList, "GenTL" );
        hList = locator.findComponent( "ProducersConfiguration", 0, 1 );
        if( hList == INVALID_ID )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, DMR_NEWER_LIBRARY_REQUIRED, "Couldn't find list 'ProducersConfiguration'. An update of the GenTL Acquire package might fix this!" );
        }
        locator.bindComponent( masterEnumerationBehaviour, "MasterEnumerationBehaviour" );
        locator.bindComponent( createProducerConfigurationEntry_, "CreateProducerConfigurationEntry@is" );
        locator.bindComponent( deleteProducerConfigurationEntry_, "DeleteProducerConfigurationEntry@is" );
        locator.bindComponent( createProducerInterfaceConfigurationEntry_, "CreateProducerInterfaceConfigurationEntry@iss" );
        locator.bindSearchBase( hList );
        m_hRoot = locator.searchbase_id();
    }
public:
    /// \brief Constructs a new <b>mvIMPACT::acquire::GenICam::GenTLDriverConfigurator</b> object.
    explicit GenTLDriverConfigurator() : mvIMPACT::acquire::ComponentCollection( INVALID_ID ),
        createProducerConfigurationEntry_(), deleteProducerConfigurationEntry_(),
        createProducerInterfaceConfigurationEntry_(),
        masterEnumerationBehaviour()
    {
        bindProperties();
    }
    /// \brief Constructs a new \b mvIMPACT::acquire::GenICam::GenTLDriverConfigurator from an existing one.
    GenTLDriverConfigurator(
        /// [in] A constant reference to the \b mvIMPACT::acquire::GenICam::GenTLDriverConfigurator object, this object shall be created from
        const GenTLDriverConfigurator& src ) : ComponentCollection( src.hObj() ),
        createProducerConfigurationEntry_( src.createProducerConfigurationEntry_ ),
        deleteProducerConfigurationEntry_( src.deleteProducerConfigurationEntry_ ),
        createProducerInterfaceConfigurationEntry_( src.createProducerInterfaceConfigurationEntry_ ),
        masterEnumerationBehaviour( src.masterEnumerationBehaviour ) {}
    /// \brief Allows assignments of \b mvIMPACT::acquire::GenICam::GenTLDriverConfigurator objects.
    GenTLDriverConfigurator& operator=( const GenTLDriverConfigurator& rhs )
    {
        if( this != &rhs )
        {
            ComponentCollection::operator=( rhs );
            bindProperties();
        }
        return *this;
    }
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %immutable; )
    // *INDENT-ON*
    /// \brief An enumerated integer property defining the master enumeration mode for all GenTL producer detected in the current session.
    /**
     * Valid values for this property are defined by the enumeration \b mvIMPACT::acquire::TInterfaceEnumerationBehaviour.
     */
    PropertyIInterfaceEnumerationBehaviour masterEnumerationBehaviour;
    // *INDENT-OFF*
    PYTHON_OR_JAVA_ONLY( %mutable; )
    // *INDENT-ON*
    /// \brief Creates a new \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration object for the desired interface reported by the specified producer.
    /**
     * Calling this function will creates a new \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration object for the desired interface
     * reported by the specified producer.
     *
     * \note If a configuration entry for the specified interface does already exist an exception will be thrown.
     */
    GenTLProducerConfiguration createProducerConfiguration(
        /// [in] The exact name of the producer library without the path to create the entry for.
        const std::string& producerName,
        /// [in] The interface ID to create the configuration entry for.
        const std::string& interfaceID = "" )
    {
        int result = DMR_NO_ERROR;
        if( interfaceID.empty() )
        {
            result = createProducerConfigurationEntry_.call( producerName );
        }
        else
        {
            std::vector<std::string> parameters;
            parameters.push_back( producerName );
            parameters.push_back( interfaceID );
            result = createProducerInterfaceConfigurationEntry_.call( parameters );
        }
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, static_cast<TDMR_ERROR>( result ), "Failed to create entry '" + producerName + "'" + ( interfaceID.empty() ? "" : " with interface entry '" + interfaceID + "'" ) );
        }
        ComponentLocator locator( hObj(), "ConfigurationData" );
        return GenTLProducerConfiguration( locator.findComponent( producerName, 0, 1 ) );
    }
    /// \brief Deletes a \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration objects.
    /**
     * Calling this function will delete the \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration object for the referenced producer.
     *
     * \note If no entry for the specified producer can be found an exception will be thrown.
     */
    void deleteProducerConfiguration(
        /// [in] The exact name of the producer library without the path to delete the entry from.
        const std::string& producerName )
    {
        const int result = deleteProducerConfigurationEntry_.call( producerName );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, static_cast<TDMR_ERROR>( result ), "Failed to delete entry '" + producerName + "'" );
        }
    }
    /// \brief Deletes all \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration objects.
    /**
     * Calling this function will result in all \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration objects to be deleted. When the next
     * mvIMPACT Acquire process will be started after shutting down the current one all producer libraries found on the system will be processed. By default only interfaces reporting
     * types/technologies (e.g. GigE Vision) also supported by MATRIX VISION will be ignored (will not enumerate devices) then.
     */
    void deleteAllProducerConfigurations( void )
    {
        std::vector<GenTLProducerConfiguration> data( getProducerConfigurations() );
        std::vector<GenTLProducerConfiguration>::size_type cnt = data.size();
        for( std::vector<GenTLProducerConfiguration>::size_type i = 0; i < cnt; i++ )
        {
            deleteProducerConfiguration( data[i].getProducerName() );
        }
    }
    /// \brief Checks if a certain producer library has been associated with a \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration.
    /**
     * \return
     * - true if a \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration is currently associated with the referenced producer library
     * - false otherwise
     */
    bool hasProducerConfiguration(
        /// [in] The exact name of the producer library without the path.
        const std::string& producerName ) const
    {
        ComponentLocator locator( hObj(), "ConfigurationData" );
        return locator.findComponent( producerName, 0, 1 ) != INVALID_ID;
    }
    /// \brief Returns the \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration associated with the referenced producer library.
    /**
     *
     * \note If no entry for the specified producer can be found an exception will be thrown.
     *
     * \return The \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration associated with the referenced producer library.
     */
    GenTLProducerConfiguration getProducerConfiguration(
        /// [in] The exact name of the producer library without the path.
        const std::string& producerName ) const
    {
        ComponentLocator locator( hObj(), "ConfigurationData" );
        const HLIST hList = locator.findComponent( producerName, 0, 1 );
        if( hList == INVALID_ID )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, static_cast<TDMR_ERROR>( PROPHANDLING_COMPONENT_NOT_FOUND ), "Couldn't find configuration for producer '" + producerName + "'" );
        }
        return GenTLProducerConfiguration( hList );
    }
    /// \brief Returns a vector containing all \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration objects currently defined.
    /**
     * \return A vector containing all \b mvIMPACT::acquire::GenICam::GenTLProducerConfiguration objects currently defined.
     */
    std::vector<GenTLProducerConfiguration> getProducerConfigurations( void ) const
    {
        ComponentLocator locator( hObj(), "ConfigurationData" );
        Component it( locator.searchbase_id() );
        it = it.firstChild();
        std::vector<GenTLProducerConfiguration> data;
        while( it.isValid() )
        {
            data.push_back( GenTLProducerConfiguration( it.hObj() ) );
            it++;
        }
        return data;
    }
};

} // namespace GenICam

/// \namespace mvIMPACT::acquire::labs This namespace contains classes and functions belonging to the general part of this SDK that
/// are not yet final and might change in the future without further notice. Yet still we think code within this namespace
/// might prove useful thus we encourage you to use it if beneficial for your application. However be prepared to apply changes when needed.
/// Feedback that helps to improve or finalize code from this namespace will be highly appreciated! A migration guide will be provided and we will
/// perform changes only if they make sense and improve the code.
namespace labs
{

//-----------------------------------------------------------------------------
/// \brief A class to create compressed video stream from images captured or loaded using the mvIMPACT Acquire API.
/**
 * This class heavily depends on the FFmpeg project (see \ref LegalNotice_UsedThirdPartySoftware_FFmpeg). Without the
 * libraries belonging to this project being present on the target system video streams cannot be created.
 *
 * Because of what is stated in the above section mvIMPACT Acquire is \b NOT shipped with the FFmpeg binaries required to use
 * this class!
 *
 * On Windows the \a FFmpeg-share package matching the platform the application shall run with (32- or 64-bit) is needed. This
 * can either be extracted into the installation folder of mvIMPACT Acquire e.g. into <b>\$(MVIMPACT_ACQUIRE_DIR)/Toolkits/ffmpeg-4.2.2-win64-shared</b> or
 * <b>\$(MVIMPACT_ACQUIRE_DIR)/Toolkits/ffmpeg-4.2.2-win32-shared</b> (Works only for this versions) \b OR at the location pointed to by \b MVIMPACT_ACQUIRE_FFMPEG_DIR (see below)
 * \b OR anywhere into the systems search path.
 *
 * On Linux the package \a ffmpeg must be installed and if e.g. H.264 support is needed the libavcodec-extra package as well.
 *
 * \attention Please carefully read and understand the legal implications coming with the use of FFmpeg in a commercial product: http://ffmpeg.org/legal.html
 *
 * mvIMPACT Acquire is capable of communicating with FFmpeg 4.x right now. This means that the following libraries will be recognized:
 * - libavcodec-58, libavformat-58 and libavutil-56 (FFmpeg 4.0 was released on 20.04.2018)
 *
 * In order to load the FFmpeg libraries
 * from a custom location the environment variable \b MVIMPACT_ACQUIRE_FFMPEG_DIR can be defined before creating the first
 * \b mvIMPACT::acquire::labs::VideoStream instance after loading the mvDeviceManager library into the current processes address space.
 * Without this environment variable only the systems default search path will be used to locate it and (Windows only) the \a Toolkits
 * folder of the installation directory. This is how the search algorithm will operate:
 *
 * \code
 * if isEnvironmentVariableDefined( MVIMPACT_ACQUIRE_FFMPEG_DIR )
 *   if tryToLoadFFmpegVersion4Succeeded
 *     return
 *   if tryToLoadFFmpegVersion3Succeeded
 *     return
 * if isWindowsSystem
 *   if tryToLoadFFmpegVersionFromToolkits4Succeeded
 *     return
 * if tryToLoadFFmpegVersion4Succeeded
 *   return
 * if tryToLoadFFmpegVersion3Succeeded
 *   return
 * ReportError
 * \endcode
 *
 * \note
 * Currently video streams can only be created for a limited number of pixel formats. Which codec supports which input formats is described at the corresponding
 * \b mvIMPACT::acquire::TVideoCodec value. Make sure to use one of these formats either by setting up your device accordingly or by using
 * the \b mvIMPACT::acquire::ImageDestination::pixelFormat property of the \ref Image_Format_Converter.
 *
 * \attention
 * - You have to feed one of the supported pixel formats depending on the video codecs requirements into the stream! The video stream API will NOT perform internal conversion. If you need to convert
 *  (most likely you will be!) use the \ref Image_Format_Converter to achieve that. It will get the job done!
 * - When not providing timestamps together with the images that are fed into the encoder the resulting video stream can still be used, but the playback speed will differ from the acquisition speed then.
 *   When providing the timestamps coming with the requests the playback speed will resemble exactly the acquisition speed. Most codecs even support variable playback speeds so dynamic changes in the
 *   frame rate will be reflected during playback.
 * \since 2.39.0
 * \ingroup CommonInterface
 */
class VideoStream
//-----------------------------------------------------------------------------
{
    HDMR_VIDEO_STREAM hStream_;
    std::string fileName_;
    TVideoCodec videoCodec_;

    void create( const std::string& fileName, const unsigned int imageWidth, const unsigned int imageHeight, const TVideoCodec codec, const unsigned int quality_pc, const unsigned int bitrate )
    {
        const TDMR_ERROR result = DMR_OpenVideoStream( fileName.c_str(), imageWidth, imageHeight, codec, quality_pc, bitrate, &hStream_ );
        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( MVIA_FUNCTION, __LINE__, result );
        }
    }
public:
/// \brief Creates a new video stream file.
    /**
     * \note
     * Internally the FFmpeg project (see \ref LegalNotice_UsedThirdPartySoftware_FFmpeg section) is used for this operation. If the corresponding libraries
     * cannot be located in one of the supported versions on the host system calling this constructor will raise an exception.
     */
    explicit VideoStream(
        /// [in] The name or full path of the file to create. The recommended file extensions for files can be found where the
        /// \b mvIMPACT::acquire::TVideoCodec enumeration is documented
        const std::string& fileName,
        /// [in] An image buffer containing the layout of the images that are about to get stored in the stream. This structure can be
        /// extracted from a real \b mvIMPACT::acquire::Request object captured previously but \b NOT by calling the
        /// \b mvIMPACT::acquire::FunctionInterface::getCurrentCaptureBufferLayout function after setting up the device
        /// completely.The latter one will not contain all the information needed for a successful stream creation. You could even create a stream from a list of files e.g. on a hard-disc using the
        /// \b mvIMPACT::acquire::ImageBufferDesc constructor accepting a file name. If you want to use the \b mvIMPACT::acquire::Request
        /// object obtained from a call to \b mvIMPACT::acquire::FunctionInterface::getCurrentCaptureBufferLayout use the constructor accepting
        /// a \b mvIMPACT::acquire::Request pointer!
        const ImageBuffer* pBuffer,
        /// [in] The codec that shall be used while encoding the images into the stream.
        const TVideoCodec codec = vcH264,
        /// [in] The quality of the resulting video stream in percent. The higher this value the larger the file will get. This value is only taken into
        /// account for the following codecs: \b mvIMPACT::acquire::vcH264, \b mvIMPACT::acquire::vcH265.
        const unsigned int quality_pc = 60,
        /// [in] The bitrate of the resulting video stream in kBit/s. The higher this value the larger the file will get. This value is only taken into
        /// account for the following codecs: \b mvIMPACT::acquire::vcMPEG2.
        const unsigned int bitrate = 6000 ) : hStream_( 0 ), fileName_( fileName ), videoCodec_( codec )
    {
        create( fileName, pBuffer->iWidth, pBuffer->iHeight, codec, quality_pc, bitrate );
    }
    /// \brief Creates a new video stream file.
    /**
     * \note
     * Internally the FFmpeg project (see \ref LegalNotice_UsedThirdPartySoftware_FFmpeg section) is used for this operation. If the corresponding libraries
     * cannot be located in one of the supported versions on the host system calling this constructor will raise an exception.
     */
    explicit VideoStream(
        /// [in] The name or full path of the file to create. The recommended file extensions for files can be found where the
        /// \b mvIMPACT::acquire::TVideoCodec enumeration is documented
        const std::string& fileName,
        /// [in] The input image width in pixels
        const unsigned int imageWidth,
        /// [in] The input image height in pixels
        const unsigned int imageHeight,
        /// [in] The codec that shall be used while encoding the images into the stream.
        const TVideoCodec codec = vcH264,
        /// [in] The quality of the resulting video stream in percent. The higher this value the larger the file will get. This value is only taken into
        /// account for the following codecs: \b mvIMPACT::acquire::vcH264, \b mvIMPACT::acquire::vcH265.
        const unsigned int quality_pc = 60,
        /// [in] The bitrate of the resulting video stream in kBit/s. The higher this value the larger the file will get. This value is only taken into
        /// account for the following codecs: \b mvIMPACT::acquire::vcMPEG2.
        const unsigned int bitrate = 6000 ) : hStream_( 0 ), fileName_( fileName ), videoCodec_( codec )
    {
        create( fileName, imageWidth, imageHeight, codec, quality_pc, bitrate );
    }
    /// \brief Creates a new video stream file.
    /**
     * \note
     * Internally the FFmpeg project (see \ref LegalNotice_UsedThirdPartySoftware_FFmpeg section) is used for this operation. If the corresponding libraries
     * cannot be located in one of the supported versions on the host system calling this constructor will raise an exception.
     */
    explicit VideoStream(
        /// [in] The name or full path of the file to create. The recommended file extensions for files can be found where the
        /// \b mvIMPACT::acquire::TVideoCodec enumeration is documented.
        const std::string& fileName,
        /// [in] A \b mvIMPACT::acquire::Request object carrying the image related information that are about to get stored in the stream. This can either be
        /// extracted from a real \b mvIMPACT::acquire::Request object captured previously or by calling the
        /// \b mvIMPACT::acquire::FunctionInterface::getCurrentCaptureBufferLayout function after setting up the device
        /// completely. To create a stream from a list of files e.g. on a hard-disc use the \b mvIMPACT::acquire::labs::VideoStream
        /// constructor accepting a \b mvIMPACT::acquire::ImageBufferDesc instead! Create instances of b mvIMPACT::acquire::ImageBufferDesc
        /// objects from files call the \b mvIMPACT::acquire::ImageBufferDesc constructor accepting a file name.
        const Request* pRequest,
        /// [in] The codec that shall be used while encoding the images into the stream.
        const TVideoCodec codec = vcH264,
        /// [in] The quality of the resulting video stream in percent. The higher this value the larger the file will get. This value is only taken into
        /// account for the following codecs: \b mvIMPACT::acquire::vcH264, \b mvIMPACT::acquire::vcH265.
        const unsigned int quality_pc = 60,
        /// [in] The bitrate of the resulting video stream in kBit/s. The higher this value the larger the file will get. This value is only taken into
        /// account for the following codecs: \b mvIMPACT::acquire::vcMPEG2.
        const unsigned int bitrate = 6000 ) : hStream_( 0 ), fileName_( fileName ), videoCodec_( codec )
    {
        create( fileName, pRequest->imageWidth.read(), pRequest->imageHeight.read(), codec, quality_pc, bitrate );
    }
    ~VideoStream()
    {
        DMR_CloseVideoStream( hStream_ );
    }
    /// \brief Returns the file name of this video stream.
    /**
     * This function returns the file name of this video stream.
     *
     * \since 2.39.0
     *
     *  \return The file name of this video stream.
     */
    const std::string& getFileName( void ) const
    {
        return fileName_;
    }
    /// \brief Returns the codec used by this video stream.
    /**
     * This function returns the codec used by this video stream.
     *
     * \since 2.39.0
     *
     *  \return The codec used by this video stream.
     */
    const TVideoCodec& getCodec( void ) const
    {
        return videoCodec_;
    }
    /// \brief Returns the a string representation for a video codec.
    /**
     * This function returns a string representation for a video codec.
     *
     * \since 2.39.0
     *
     *  \return A string representation for a video codec.
     */
    static std::string getCodecAsString( const TVideoCodec codec )
    {
        switch( codec )
        {
        case vcH264:
            return "H.264";
        case vcH265:
            return "H.265";
        case vcMPEG2:
            return "MPEG-2";
        }
        return "INVALID VIDEO CODEC";
    }
    /// \brief Returns the codec used by this video stream as a string.
    /**
     * This function returns the codec used by this video stream as a string.
     *
     * \since 2.39.0
     *
     *  \return The codec used by this video stream as a string.
     */
    std::string getCodecAsString( void ) const
    {
        return getCodecAsString( getCodec() );
    }
    /// \brief Checks if the video stream API is available.
    /**
     * This function checks if the video stream API is available.
     *
     * \since 2.39.0
     *
     * \return
     *  - true if the video stream API is available thus video streams can be created
     *  - false otherwise.
     */
    static bool isAPIAvailable( void )
    {
        return DMR_InitVideoStreamAPI( 0, 0 ) == DMR_NO_ERROR;
    }
    /// \brief Stores an image into the video stream.
    /**
     *  This function stores an image into the video stream.
     *
     *  \note
     *  Internally the FFmpeg project (see \ref LegalNotice_UsedThirdPartySoftware_FFmpeg section as well as the remarks made here: \b mvIMPACT::acquire::labs::VideoStream) is used for this operation. If the corresponding libraries
     *  cannot be located in one of the supported versions on the host system calling this function will fail.
     *
     * \since 2.39.0
     *
     *  \return
     *  - <b>mvIMPACT::acquire::DMR_NO_ERROR</b> if successful.
     *  - <b>mvIMPACT::acquire::DMR_LIBRARY_NOT_FOUND</b> if no compatible version of the FFmpeg libraries could be located on the host system.
     *  - <b>mvIMPACT::acquire::DEV_UNSUPPORTED_PARAMETER</b> if a pixel format has been passed to the function that is not supported by the internal algorithms.
     *  - <b>mvIMPACT::acquire::DEV_INPUT_PARAM_INVALID</b> e.g. if a pixel format has been passed to the function that is not supported by the FFmpeg libraries.
     *  - A negative error code of type <b>::TDMR_ERROR</b> otherwise.
     */
    int saveImage(
        /// [in] The image to encode and store.
        const ImageBuffer* pBuffer,
        /// [in] A timestamp(in us) to associate this image with. This can be 0 if no timestamp is available.
        int64_type timestamp_us = 0LL )
    {
        return DMR_SaveImageBufferToVideoStream( hStream_, pBuffer, timestamp_us );
    }
    /// \brief Encodes and stores the image associated with the \b mvIMPACT::acquire::Request object into the stream.
    /**
     *  This function stores the image associated with an \b mvIMPACT::acquire::Request object into the video stream.
     *
     *  \note
     *  Internally the FFmpeg project (see \ref LegalNotice_UsedThirdPartySoftware_FFmpeg section as well as the remarks made here: \b mvIMPACT::acquire::labs::VideoStream) is used for this operation. If the corresponding libraries
     *  cannot be located in one of the supported versions on the host system calling this function will fail.
     *
     * \since 2.39.0
     *
     *  \sa
     *  \b mvIMPACT::acquire::labs::VideoStream::pause, \n
     *  \b mvIMPACT::acquire::labs::VideoStream::isPaused, \n
     *  \b mvIMPACT::acquire::labs::VideoStream::resume \n
     *
     *  \return
     *  - <b>mvIMPACT::acquire::DMR_NO_ERROR</b> if successful.
     *  - <b>mvIMPACT::acquire::DMR_LIBRARY_NOT_FOUND</b> if no compatible version of the FFmpeg libraries could be located on the host system.
     *  - <b>mvIMPACT::acquire::DEV_UNSUPPORTED_PARAMETER</b> if a pixel format has been passed to the function that is not supported by the internal algorithms.
     *  - <b>mvIMPACT::acquire::DEV_INPUT_PARAM_INVALID</b> e.g. if a pixel format has been passed to the function that is not supported by the FFmpeg libraries.
     *  - A negative error code of type <b>::TDMR_ERROR</b> otherwise.
     */
    int saveImage(
        /// [in] A pointer to a \b mvIMPACT::acquire::Device object obtained from
        /// a \b mvIMPACT::acquire::DeviceManager object.
        Device* pDev,
        /// [in] A pointer to the \b mvIMPACT::acquire::Request object carrying the image to encode and store.
        const Request* pRequest )
    {
        return DMR_ImageRequestSaveToVideoStream( pDev->hDrv(), pRequest->getNumber(), hStream_ );
    }
    /// \brief Pauses this video stream.
    /**
     *  This function pauses this video stream. While paused no images can be written into the stream. Pausing internally simply starts a timer
     *  and all accumulated pause times will be subtracted from images that will be written into the stream after the pause has been ended effectively
     *  allowing to remove inactive sections from the video stream.
     *
     *  \note
     *  Internally the FFmpeg project (see \ref LegalNotice_UsedThirdPartySoftware_FFmpeg section as well as the remarks made here: \b mvIMPACT::acquire::labs::VideoStream) is used for this operation. If the corresponding libraries
     *  cannot be located in one of the supported versions on the host system calling this function will fail.
     *
     * \since 2.41.0
     *
     *  \sa
     *  \b mvIMPACT::acquire::labs::VideoStream::resume, \n
     *  \b mvIMPACT::acquire::labs::VideoStream::isPaused
     *
     *  \return
     *  - <b>mvIMPACT::acquire::DMR_NO_ERROR</b> if successful.
     *  - <b>mvIMPACT::acquire::DMR_BUSY</b> if this stream has been paused already.
     *  - A negative error code of type <b>::TDMR_ERROR</b> otherwise.
     */
    int pause( void ) const
    {
        return DMR_PauseVideoStream( hStream_ );
    }
    /// \brief Checks is this video stream is currently paused.
    /**
     *
     *  \note
     *  Internally the FFmpeg project (see \ref LegalNotice_UsedThirdPartySoftware_FFmpeg section as well as the remarks made here: \b mvIMPACT::acquire::labs::VideoStream) is used for this operation. If the corresponding libraries
     *  cannot be located in one of the supported versions on the host system calling this function will fail.
     *
     * \since 2.41.0
     *
     *  \sa
     *  \b mvIMPACT::acquire::labs::VideoStream::pause, \n
     *  \b mvIMPACT::acquire::labs::VideoStream::resume
     *
     *  \return
     *  - true if this video stream is currently paused.
     *  - false otherwise.
     */
    bool isPaused( void ) const
    {
        return DMR_IsVideoStreamPaused( hStream_ ) == DMR_NO_ERROR;
    }
    /// \brief Resumes this video stream.
    /**
     *  This function resumes this previously paused video stream. While paused no images can be written into the stream. Pausing internally simply starts a timer
     *  and all accumulated pause times will be subtracted from images that will be written into the stream after the pause has been ended effectively
     *  allowing to remove inactive sections from the video stream.
     *
     *  \note
     *  Internally the FFmpeg project (see \ref LegalNotice_UsedThirdPartySoftware_FFmpeg section as well as the remarks made here: \b mvIMPACT::acquire::labs::VideoStream) is used for this operation. If the corresponding libraries
     *  cannot be located in one of the supported versions on the host system calling this function will fail.
     *
     * \since 2.41.0
     *
     *  \sa
     *  \b mvIMPACT::acquire::labs::VideoStream::pause, \n
     *  \b mvIMPACT::acquire::labs::VideoStream::isPaused
     *
     *  \return
     *  - <b>mvIMPACT::acquire::DMR_NO_ERROR</b> if successful.
     *  - <b>mvIMPACT::acquire::DMR_EXECUTION_PROHIBITED</b> if this stream has been paused already.
     *  - A negative error code of type <b>::TDMR_ERROR</b> otherwise.
     */
    int resume( void ) const
    {
        return DMR_ResumeVideoStream( hStream_ );
    }
};

//-----------------------------------------------------------------------------
/// \brief A smaller helper class for pausing a video stream for a defined time.
/**
 * This class uses a RAII pattern to pause an instance of <b>mvIMPACT::acquire::labs::VideoStream</b>
 * \since 2.41.0
 * \ingroup CommonInterface
 */
class VideoStreamPauseScope
//-----------------------------------------------------------------------------
{
    VideoStream& stream_;
    bool boPausedWithinScope_;
public:
    /// \brief Creates a new <b>mvIMPACT::acquire::labs::VideoStreamPauseScope</b> object.
    /**
     * Trying to pause a stream that is paused already or trying to resume a stream that is not paused will raise an exception!
     * When this object goes out of scope the previous state will be restored automatically.
     */
    explicit VideoStreamPauseScope(
        /// [in] The video stream that shall be configured.
        VideoStream& stream,
        /// [in] The mode the selected video stream shall have while this object is alive.
        bool boPausedWithinScope = true ) : stream_( stream ), boPausedWithinScope_( boPausedWithinScope )
    {
        TDMR_ERROR result = DMR_NO_ERROR;
        if( boPausedWithinScope_ )
        {
            result = static_cast<TDMR_ERROR>( stream_.pause() );
        }
        else
        {
            result = static_cast<TDMR_ERROR>( stream_.resume() );
        }

        if( result != DMR_NO_ERROR )
        {
            ExceptionFactory::raiseException( __FUNCTION__, __LINE__, result );
        }
    }
    ~VideoStreamPauseScope()
    {
        if( boPausedWithinScope_ )
        {
            stream_.resume();
        }
        else
        {
            stream_.pause();
        }
    }
};

} // namespace labs

} // namespace acquire
} // namespace mvIMPACT

PYTHON_ONLY( ENUM_PROPERTY( PropertyI, EnumPropertyI, int, ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIAcquisitionField, EnumPropertyI, TAcquisitionField, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyIAcquisitionMode, EnumPropertyI, TAcquisitionMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIAcquisitionStartStopBehaviour, EnumPropertyI, TAcquisitionStartStopBehaviour, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIAoiMode, EnumPropertyI, TAoiMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIAutoControlSpeed, EnumPropertyI, TAutoControlSpeed, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIAutoControlMode, EnumPropertyI, TAutoControlMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIAutoExposureControl, EnumPropertyI, TAutoExposureControl, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIAutoGainControl, EnumPropertyI, TAutoGainControl, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIAutoOffsetCalibration, EnumPropertyI, TAutoOffsetCalibration, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIBayerConversionMode, EnumPropertyI, TBayerConversionMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIBayerMosaicParity, EnumPropertyI, TBayerMosaicParity, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIBayerWhiteBalanceResult, EnumPropertyI, TBayerWhiteBalanceResult, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIBlueFOXDigitalInputThreshold, EnumPropertyI, TBlueFOXDigitalInputThreshold, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIBlueFOXFooterMode, EnumPropertyI, TBlueFOXFooterMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIBlueFOXInfoSensorCapabilities, EnumPropertyI, TBlueFOXInfoSensorCapabilities, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIBlueFOXOffsetAutoBlackSpeed, EnumPropertyI, TBlueFOXOffsetAutoBlackSpeed, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIBlueFOXSensorTiming, EnumPropertyI, TBlueFOXSensorTiming, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIBlueFOXTransferSize, EnumPropertyI, TBlueFOXTransferSize, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIBoolean, EnumPropertyI, TBoolean, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraAoiMode, EnumPropertyI, TCameraAoiMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraBinningMode, EnumPropertyI, TCameraBinningMode, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraDataFormat, EnumPropertyI, TCameraDataFormat, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraExposeMode, EnumPropertyI, TCameraExposeMode, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraExternalSyncEdge, EnumPropertyI, TCameraExternalSyncEdge, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraExternalSyncOutput, EnumPropertyI, TCameraExternalSyncOutput, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraFlashMode, EnumPropertyI, TCameraFlashMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraFlashType, EnumPropertyI, TCameraFlashType, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraHDRMode, EnumPropertyI, TCameraHDRMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraInterlacedType, EnumPropertyI, TCameraInterlacedType, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraLinkDataValidMode, EnumPropertyI, TCameraLinkDataValidMode, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraOutput, EnumPropertyI, TCameraOutput, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraPixelClock, EnumPropertyI, TCameraPixelClock, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraScanMode, EnumPropertyI, TCameraScanMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraSerialPortBaudRate, EnumPropertyI, TCameraSerialPortBaudRate, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraShutterMode, EnumPropertyI, TCameraShutterMode, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraTapsXGeometry, EnumPropertyI, TCameraTapsXGeometry, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraTapsYGeometry, EnumPropertyI, TCameraTapsYGeometry, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraTestMode, EnumPropertyI, TCameraTestMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraTriggerMode, EnumPropertyI, TCameraTriggerMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyICameraTriggerSource, EnumPropertyI, TCameraTriggerSource, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIChannelSplitMode, EnumPropertyI, TChannelSplitMode, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIClampMode, EnumPropertyI, TClampMode, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyIColorTwistInputCorrectionMatrixMode, EnumPropertyI, TColorTwistInputCorrectionMatrixMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIColorTwistOutputCorrectionMatrixMode, EnumPropertyI, TColorTwistOutputCorrectionMatrixMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIColorProcessingMode, EnumPropertyI, TColorProcessingMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDarkCurrentFilterMode, EnumPropertyI, TDarkCurrentFilterMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDefectivePixelsFilterMode, EnumPropertyI, TDefectivePixelsFilterMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceAccessMode, EnumPropertyI, TDeviceAccessMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceAdvancedOptions, EnumPropertyI, TDeviceAdvancedOptions, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceCapability, EnumPropertyI, TDeviceCapability, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceClass, EnumPropertyI, TDeviceClass, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceDigitalOutputMode, EnumPropertyI, TDeviceDigitalOutputMode, mvIMPACT::acquire:: ) )
//PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceEventMode, EnumPropertyI, TDeviceEventMode, mvIMPACT::acquire:: ) ) // deprecated!
//PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceEventType, EnumPropertyI, TDeviceEventType, mvIMPACT::acquire:: ) ) // deprecated!

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceImageTrigger, EnumPropertyI, TDeviceImageTrigger, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceInterfaceLayout, EnumPropertyI, TDeviceInterfaceLayout, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceLoadSettings, EnumPropertyI, TDeviceLoadSettings, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDevicePowerMode, EnumPropertyI, TDevicePowerMode, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceScanRateMode, EnumPropertyI, TDeviceScanRateMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceSignalOutputStartEvent, EnumPropertyI, TDeviceSignalOutputStartEvent, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceState, EnumPropertyI, TDeviceState, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceSyncOutMode, EnumPropertyI, TDeviceSyncOutMode, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceTriggerInterface, EnumPropertyI, TDeviceTriggerInterface, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDeviceTriggerMode, EnumPropertyI, TDeviceTriggerMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDigIOState, EnumPropertyI, TDigIOState, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDigitalIOMeasurementMode, EnumPropertyI, TDigitalIOMeasurementMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDigitalIOMeasurementSource, EnumPropertyI, TDigitalIOMeasurementSource, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIDigitalOutputControlMode, EnumPropertyI, TDigitalOutputControlMode, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyIDigitalSignal, EnumPropertyI, TDigitalSignal, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIFieldGateMode, EnumPropertyI, TFieldGateMode, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyIFlatFieldFilterCorrectionMode, EnumPropertyI, TFlatFieldFilterCorrectionMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIFlatFieldFilterMode, EnumPropertyI, TFlatFieldFilterMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIHWUpdateResult, EnumPropertyI, THWUpdateResult, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyII2COperationMode, EnumPropertyI, TI2COperationMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyII2COperationStatus, EnumPropertyI, TI2COperationStatus, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIImageBufferPixelFormat, EnumPropertyI, TImageBufferPixelFormat, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIImageBufferFormatReinterpreterMode, EnumPropertyI, TImageBufferFormatReinterpreterMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIImageDestinationPixelFormat, EnumPropertyI, TImageDestinationPixelFormat, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIImageProcessingFilter, EnumPropertyI, TImageProcessingFilter, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIImageProcessingMode, EnumPropertyI, TImageProcessingMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIImageProcessingOptimization, EnumPropertyI, TImageProcessingOptimization, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIImageProcessingResult, EnumPropertyI, TImageProcessingResult, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIRequestImageMemoryMode, EnumPropertyI, TRequestImageMemoryMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIImageRequestControlMode, EnumPropertyI, TImageRequestControlMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIInfoSensorColorMode, EnumPropertyI, TInfoSensorColorMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIInfoSensorType, EnumPropertyI, TInfoSensorType, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIInterfaceEnumerationBehaviour, EnumPropertyI, TInterfaceEnumerationBehaviour, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIInterlacedMode, EnumPropertyI, TInterlacedMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyILineCounter, EnumPropertyI, TLineCounter, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyILUTGammaMode, EnumPropertyI, TLUTGammaMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyILUTImplementation, EnumPropertyI, TLUTImplementation, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyILUTInterpolationMode, EnumPropertyI, TLUTInterpolationMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyILUTMapping, EnumPropertyI, TLUTMapping, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyILUTMode, EnumPropertyI, TLUTMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIMemoryManagerMode, EnumPropertyI, TMemoryManagerMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIMemoryManagerPoolMode, EnumPropertyI, TMemoryManagerPoolMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIMirrorMode, EnumPropertyI, TMirrorMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIMirrorOperationMode, EnumPropertyI, TMirrorOperationMode, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIOnBoardMemoryMode, EnumPropertyI, TOnBoardMemoryMode, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyIPolarizedDataExtractionMode, EnumPropertyI, TPolarizedDataExtractionMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIPolarizedDataExtractionInterpolationMode, EnumPropertyI, TPolarizedDataExtractionInterpolationMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIPulseStartTrigger, EnumPropertyI, TPulseStartTrigger, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIRequestResult, EnumPropertyI, TRequestResult, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIRequestState, EnumPropertyI, TRequestState, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIRTCtrlModes, EnumPropertyI, TRTCtrlModes, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIRTProgOpCodes, EnumPropertyI, TRTProgOpCodes, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIScalerMode, EnumPropertyI, TScalerMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIScalerInterpolationMode, EnumPropertyI, TScalerInterpolationMode, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIScanClock, EnumPropertyI, TScanClock, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIScanStandard, EnumPropertyI, TScanStandard, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyITriggerMoment, EnumPropertyI, TTriggerMoment, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIUserDataAccessRight, EnumPropertyI, TUserDataAccessRight, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIUserDataReconnectBehaviour, EnumPropertyI, TUserDataReconnectBehaviour, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyIVideoStandard, EnumPropertyI, TVideoStandard, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyIVirtualDeviceImageType, EnumPropertyI, TVirtualDeviceImageType, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIVirtualDeviceTestMode, EnumPropertyI, TVirtualDeviceTestMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIWhiteBalanceCalibrationMode, EnumPropertyI, TWhiteBalanceCalibrationMode, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyIWhiteBalanceParameter, EnumPropertyI, TWhiteBalanceParameter, mvIMPACT::acquire:: ) )

PYTHON_ONLY( ENUM_PROPERTY( PropertyI64, EnumPropertyI64, int64_type, mvIMPACT::acquire:: ) )
PYTHON_ONLY( ENUM_PROPERTY( PropertyI64BufferPartDataType, EnumPropertyI64, TBufferPartDataType, mvIMPACT::acquire:: ) )

#ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION
PYTHON_ONLY( ENUM_PROPERTY( PropertyI64DeviceTriggerOverlap, EnumPropertyI64, TDeviceTriggerOverlap, mvIMPACT::acquire:: ) )
#endif // #ifndef IGNORE_MVGRABBER_SPECIFIC_DOCUMENTATION

PYTHON_ONLY( ENUM_PROPERTY( PropertyF, EnumPropertyF, double, ) )

// restore Borland compiler switch 'force enums to the size of integer'
#if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
#   ifdef _WIN32
#       ifdef __BORLANDC__
#           pragma option pop
#       endif // #ifdef __BORLANDC__
#   endif // _WIN32
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)

#if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)
#   ifndef MVIMPACT_USE_NAMESPACES
using namespace mvIMPACT::acquire;
#   endif // #ifndef MVIMPACT_USE_NAMESPACES
#endif // #if !defined(DOXYGEN_SHOULD_SKIP_THIS) && !defined(WRAP_ANY)

#ifdef _MSC_VER // is Microsoft compiler?
// restore old warning level
#   pragma warning( pop )
#endif // #ifdef _MSC_VER

#endif // MVIMPACT_ACQUIRE_H_
