After connecting to a device through your adaptor, users might
want to view or modify values of the properties of the device. For
example, a user might adjust the value of the Brightness
property
or retrieve the current value of the Temperature
property.
(For information about how to define the properties you want to expose
to users, see Creating Device Properties.)
To receive notification from the engine when a user wants to
view or modify a property, associate a listener object
with the property. The toolbox defines two types of listener classes: get listeners
that respond to get
commands and set listeners
that respond to set
commands.
To provide support for getting and setting property values, follow this procedure:
Define a listener class of the appropriate type. The toolbox defines two abstract classes, one for get listeners and one for set listeners, from which you derive your class.
Implement the virtual function required by the class.
Associate an instance of your listener class with the property.
The following sections describe how to set up get listeners and set listeners and in your adaptor.
To receive notification from the engine when a user requests
the current value of a property using the get
command:
Define a get listener class, deriving
it from the IPropCustomGetFcn
abstract class—see Defining a Get Listener Class.
Implement the getValue()
virtual
function in your listener class—see Creating the getValue() Function for Your Class.
Associate an instance of your listener class with a property—see Associating Get Listeners with Properties.
Create a get listener class, deriving it from the abstract class IPropCustomGetFcn
,
as shown in the following example.
In this example, the constructor accepts a handle to an IAdaptor
object.
Because the toolbox establishes listeners on a per-instance basis,
passing this handle can be helpful, but it is not a requirement.
The IPropCustomGetFcn
class defines one virtual
function: the getValue()
member function. In this
function, you define how your adaptor responds when a user requests
the current value of a property. For more information about the getValue()
function,
see Creating the getValue() Function for Your Class.
#include "mwadaptorimaq.h" #include "MyDeviceImaq.h" // For this example class MyDevicePropGetListener : public IPropCustomGetFcn { public: // Constructor/Destructor MyDevicePropGetListener(MyDeviceAdaptor* parent): _parent(parent) {} virtual ~MyDevicePropGetListener() {}; virtual void getValue(imaqkit::IPropInfo* propertyInfo, void* value); private: // Declare handle to parent as member data. MyDeviceAdaptor* _parent; };
When a user requests the current value of a property, the engine
calls the getValue()
function of the get listener
class associated with the property.
Your getValue()
function must accept two
parameters:
void getValue(IPropInfo* propertyInfo, void* value)
propertyInfo
is a handle to an IPropInfo
object.—The IPropInfo
class
is the interface that lets you get information about the property.
For example, using IPropInfo
functions you can
retrieve the property name, its storage type and its default value.
This information is useful if you have a generic listener class that
handles multiple properties.
value
is a pointer to the location
in memory where your adaptor stores the requested property value.—The
engine passes this value as a void*
. Your getValue()
function
must cast the value to the appropriate C++ data type. The following
table tells which C++ data type to cast to for all property
types supported by the adaptor kit.
imaqkit::PropertyTypes | C++ Data Type |
---|---|
|
|
|
|
|
|
|
|
|
|
For nonscalar data types, character vectors, double arrays,
and integer arrays, your listener class must allocate sufficient memory
for the current property value using the new[]
operator.
The engine deletes this memory, calling delete[]
.
An example using a character vector property is:
char** returnStr = reinterpret_cast<char**>(value); *returnStr = imaqkit::imaqmalloc(sizeof(char) * (stringLength)); strcpy(*returnStr, currentPropertyValueString);
Suggested Algorithm for a getValue() Function. The design of the getValue()
function varies
with the needs of your device and the facilities offered by its SDK.
For example, you could create one get listener class that handles
value queries for all properties in a particular property container
(general or device-specific). In this case, the getValue()
function
includes a switch statement with cases that handle each individual
property.
Alternatively, define a separate get listener class for each property or each property storage type. Then, the engine calls the specific listener for the property specified.
You also can define get listener classes that fit the way the device SDK organizes property configuration. For example, if an SDK provides one function to configure all device properties, you can define a get listener class for these properties.
Example. This example shows an implementation of a getValue()
function
for integer types:
void MyDevicePropGetListener::getValue(IPropInfo* propertyInfo, void* value) { // Get property name from the IPropInfo object. const char* propname = propertyInfo->getPropertyName(); // Get the value using whatever facility your device's SDK provides. *reinterpret_cast<const int*>(value) = sdk_function_get(); // For debug purposes only. imaqkit::adaptorWarn("In listener. Property name is %s\n",propname); }
To set up a listener for a property, you associate the listener object with the property in the property container. The following example shows how to add get listeners for all device-specific properties in the adaptor property container. Adaptor writers typically set up property listeners in their adaptor class constructor—see Implementing Your Adaptor Class Constructor.
Get a handle to the appropriate property container object.
The IEngine
object has two member functions
that return handles to property containers (IPropContainer
objects).
The example calls the IEngine
class getAdaptorPropContainer()
member
function to get the device-specific property container:
imaqkit::IPropContainer* adaptorPropContainer = getEngine()->getAdaptorPropContainer();
Add a get listener to a property in
the container, using the IPropContainer
object setCustomGetFcn()
function.
As arguments, specify the property name and a handle to the listener
object.
Note
Because the toolbox deletes each instance of a listener object when a user deletes the video input object, associate a new instance of a listener object with each property.
The following example iterates through all properties in the adaptor property container, associating a get listener object with each one.
void MyDeviceAdaptor::MyDeviceAdaptor() { // get a handle to the property container IPropContainer* propContainer = getEngine()->getAdaptorPropContainer(); // Determine the number of properties in the container. int numDeviceProps = propContainer->getNumberProps(); // Retrieve the names of all the properties in the container const char **devicePropNames = new const char*[numDeviceProps]; propContainer->getPropNames(devicePropNames); // Create a variable to point to a property get listener object. MyDevicePropGetListener* getListener; // For each property in the container... for (int i = 0; i < numDeviceProps; i++){ // Create a get listener object... getListener = new MyDevicePropGetListener(this); // and associate it with a specific property. propContainer->setCustomGetFcn(devicePropNames[i], getListener); } // clean up the array of property names. delete [] devicePropNames; }
To receive notification from the engine when a user changes
the value of a property using the set
command:
Define a set listener class, deriving
it from the IPropPostSetListener
abstract class—see Defining a Set Listener Class.
Implement the notify()
virtual
function in your set listener class—see Creating the notify() Function for Your Class.
Associate an instance of your set listener class with the property—see Associating Set Listeners with Properties.
Create a set listener class, deriving it from the abstract class IPropPostSetListener
,
as shown in the following example. (The name of the class includes
the word Post
because the toolbox notifies listeners
after it updates the property value stored in the container.)
In this example, the constructor accepts a handle to an IAdaptor
object.
Because the toolbox establishes listeners on a per-instance basis,
passing this handle can be helpful, but it is not a requirement.
The IPropPostSetListener
class defines one
virtual function: the notify()
member function.
In this function, you define how your adaptor responds when a user
changes the value of a property. For more information, see Creating the notify() Function for Your Class.
#include "mwadaptorimaq.h" #include "MyDeviceImaq.h" // For this example class MyDevicePropSetListener : public IPropPostSetListener { public: // Constructor/Destructor MyDevicePropSetListener(MyDeviceAdaptor* parent): _parent(parent) {} virtual ~MyDevicePropSetListener() {}; virtual void notify(imaqkit::IEnginePropInfo* propertyInfo, void* newValue); private: // Declare handle to parent as member data MyDeviceAdaptor* _parent; // Property Information object. imaqkit::IPropInfo* _propInfo; // The new value for integer properties. int _lastIntValue; // The new value for double properties. double _lastDoubleValue; // The new value for character vector properties. char* _lastStrValue; };
When a user calls the set
command to change
the value of a property, the engine calls the notify()
function
of the set listener class associated with the property.
A set listener class notify()
function must
accept two parameters:
void notify(IPropInfo* propertyInfo, void* newValue)
propertyInfo
is a handle to an IPropInfo
object—The IPropInfo
class
is the interface that lets you get information about the property.
For example, using IPropInfo
functions you can
get the property name, its storage type, and its default value.
newValue
is a pointer to the new
property value—This engine passes this value as a void*
.
Your notify()
function must cast the value to the
appropriate C++ data type. The following table tells which C++ data type to cast to for all property types supported by the
adaptor kit.
imaqkit::PropertyTypes | C++ Data Type |
---|---|
|
|
|
|
|
|
|
|
|
|
Suggested Algorithm for notify() Function. The design of the notify()
function varies
with the needs of your device and the facilities offered by its SDK.
For example, you can create one set listener class that handles all
value changes for all properties in a particular property container
(general or device-specific). In this case, the notify()
function
includes a switch statement with cases that handle each individual
property.
Alternatively, you could define a separate set listener class for each property or each property storage type. Then, the engine calls the specific listener for the property specified.
You also can define set listener classes that fit the way the SDK organizes property configuration. For example, if an SDK provides one function to configure all device properties, you can define a set listener class for these properties.
Example. This example shows an implementation of a notify()
function
for integer types:
void MyDevicePropSetListener::notify(IPropInfo* propertyInfo, void* newValue) { // Get property name from the IPropInfo object. const char* propname = propertyInfo->getPropertyName(); // Cast newValue to the proper type newVal = *reinterpret_cast<const int*>(newValue); // ***************************************************** // Insert calls to device SDK to apply value to hardware. // ***************************************************** // For debug purposes only. imaqkit::adaptorWarn("In listener. Property name is %s\n",propname); }
To set up a listener for a property, you associate the listener object with the property in the property container. The following example shows how to add set listeners for all the device-specific properties in the adaptor property container. Adaptor writers typically set up property listeners in their adaptor class constructor—see Implementing Your Adaptor Class Constructor.
Get a handle to the appropriate property container object.
The IEngine
object has two member functions
that return handles to property containers (IPropContainer
objects).
The example calls the IEngine
class getAdaptorPropContainer()
member
function to get the device-specific property container:
imaqkit::IPropContainer* adaptorPropContainer = getEngine()->getAdaptorPropContainer();
Add a set listener to a property in
the container, using the IPropContainer
object's addListener()
function.
As arguments, specify the property name and a handle to the listener
object.
Note
Because the toolbox deletes each instance of a listener object when a user deletes the video input object, associate a new instance of a listener object with each property.
The following example iterates through all properties in the adaptor property container, associating a set listener object with each property:
void MyDeviceAdaptor::MyDeviceAdaptor() { // get a handle to the property container IPropContainer* propContainer = getEngine()->getAdaptorPropContainer(); // Determine the number of properties in the container. int numDeviceProps = propContainer->getNumberProps(); // Retrieve the names of all the properties in the container const char **devicePropNames = new const char*[numDeviceProps]; propContainer->getPropNames(devicePropNames); // Create a variable to point to a property listener object. MyDevicePropSetListener* setListener; // For each property in the container... for (int i = 0; i < numDeviceProps; i++){ // Create a set listener object... setListener = new MyDevicePropSetListener(this); // and associate it with a specific property. propContainer->addListener(devicePropNames[i], setListener); } // clean up the array of property names. delete [] devicePropNames; }