Creating a Device Driver

Writing the Device Driver

Creating the Device Driver

When you create the library file for your device driver, there are a few things that you need to think about:

• You need to retrieve information from the connected device in order to make the device drive something in Softimage. To do this, you can use one of the following strategies according to your needs and style:

- Set up a timer procedure that checks the status of the device every few milliseconds .

- Write event procedures that run code whenever there is a change in the status of the device.

• Device drivers can contain many channels with data that are continuously being refreshed. For this reason, you should cache the device information to maximize your driver’s performance.

For example, you can cache the channel object when the driver is activated. For details on how to do this, see the Mouse Driver example under the mousedriver directory in the SDK example directory.

• To hook into Softimage, use the device callbacks listed in the table below.

Callback | Description
XSIDeviceOnInitialize | Fired when Softimage loads the device. When the Device Manager turned on (activated), Softimage reads each XML device description file and builds a list of devices corresponding to each file it finds.
XSIDeviceOnUnInitialize | Fired when Softimage unloads the device when quitting or when the Device Manager is turned off (deactivated).
XSIDeviceOnActivate | Fired when the user connects the driver by checking the Active option in the DeviceManager or selecting Devices > Enable All Devices from the Animate toolbar or menu.
XSIDeviceOnDeActivate | Fired when the user disconnects the driver by unchecking the Active option in the DeviceManager or selecting Devices > Disable All Devices from the Animate toolbar or menu.

The Mouse driver plug-in uses the mouse’s position to drive the X and Y position. This example illustrates how to use the tools mentioned above to create your device driver.

Example: using the XSIDeviceOnActivate callback

| You can find the source code and .xsidevice file for the Mouse plug-in under the mousedriver directory in the SDK example directory (for example:
    <factory_path>\XSISDK\examples\drivers\MouseDriver

If you look at the source code for the Mouse driver, it uses the XSIDeviceOnActivate callback to set up the coordinates for the mouse’s position.

    extern "C" HRESULT WINAPI XSIDeviceOnActivate()
    {
       ApplicationPtr l_pApp;

       l_pApp.CreateInstance("XSI.Application");

    #ifdef DEBUG
       l_pApp->LogMessage(L"Connecting Mouse Device...", siInfo);
    #endif

       //-----------------------------------------------------
       // Get the mouse position
       //-----------------------------------------------------
       POINT  l_ptClientMousePos;
       ::GetCursorPos( &l_ptClientMousePos );

       //-----------------------------------------------------
       //-----------------------------------------------------
       if (g_pDeviceinfo.m_pChannelX == 0 || g_pDeviceinfo.m_pChannelY ==0)
       {
           // here is where the information from the device is initialized
           // (the actual code that goes here appears in below)
       }

       //-----------------------------------------------------
       // Start a timer  using the parameter named :
       // PollingInterval (20 msec by default)
       //-----------------------------------------------------
    #ifdef _TIMER_BASED_EXAMPLE
       ULONG l_ulPollingInterval = 20;
       m_idTimer = ::SetTimer( NULL, 1, l_ulPollingInterval, (TIMERPROC)fnTimerProc ) ;
    #endif

       g_currentHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)MyMouseProc, g_hInstance,0);

       return S_OK;
    }

Example: using a timer loop (instead of an event)

The timer loop forces the driver to periodically refresh the information:

    VOID CALLBACK fnTimerProc( HWND /*hwnd*/, UINT /*uMsg*/, UINT /*idEvent*/, DWORD /*dwTime*/ )
    {
       ApplicationPtr l_pApp;
       l_pApp.CreateInstance("XSI.Application");

       //-----------------------------------------------------
       // Get the mouse position
       //-----------------------------------------------------
       POINT  l_ptClientMousePos;
       ::GetCursorPos( &l_ptClientMousePos );

       // Set the X channel
       CComVariant l_varX( (DOUBLE)l_ptClientMousePos.x );
       CComVariant l_varY( (DOUBLE)l_ptClientMousePos.y );

       g_pDeviceinfo.m_pChannelX->put_Value( l_varX );
       g_pDeviceinfo.m_pChannelY->put_Value( l_varY );
    }

Example: using an event (instead of a timer loop)

The Mouse driver example also illustrates how to use an event procedure to update the information

    LRESULT CALLBACK MyMouseProc
    (
      int nCode,      // hook code
      WPARAM wParam,  // message identifier
      LPARAM lParam   // mouse coordinates
    )
    {
       if (wParam == WM_MOUSEMOVE)
       {
           MOUSEHOOKSTRUCT *l_sMouseInfo = (MOUSEHOOKSTRUCT *)lParam;

           if (g_pDeviceinfo.m_pChannelX)
           {
              // Set the X an Y channels
              CComVariant l_varX( (DOUBLE)l_sMouseInfo->pt.x );
              CComVariant l_varY( (DOUBLE)l_sMouseInfo->pt.y );

              g_pDeviceinfo.m_pChannelX->put_Value( l_varX );
              g_pDeviceinfo.m_pChannelY->put_Value( l_varY );
           }
       }
       else if (wParam == WM_LBUTTONDOWN)
       {
           if (g_pDeviceinfo.m_pChannelLB)
           {
              // Trigger the command on the Left Button
              g_pDeviceinfo.m_pChannelLB->put_Value( CComVariant(1) );
           }
       }
       else if (wParam == WM_MBUTTONDOWN)
       {
           if (g_pDeviceinfo.m_pChannelMB)
           {
              // Trigger the command on the Middle Button
              g_pDeviceinfo.m_pChannelMB->put_Value( CComVariant(1) );
           }
       }
       else if (wParam == WM_RBUTTONDOWN)
       {
           if (g_pDeviceinfo.m_pChannelRB)
           {
              // Trigger the command on the Right Button
              g_pDeviceinfo.m_pChannelRB->put_Value( CComVariant(1) );
           }
       }

       return CallNextHookEx(g_currentHook,nCode,wParam,lParam);
    }

Example: caching your device information

You can create a global instance of the device information, which caches the channel objects so you don’t have to get new ones for each mouse message:

    static _DeviceInfo g_pDeviceinfo;

To add options to your device driver

Users can click the Options button on the device driver window to access the options you set up. To create add options to your device driver plug-in:

1. Create a custom parameter set that contains the set of options you want to make available to your device driver. For more information on how to create custom parameter sets, see the Animation guide.

2. In the .xsidevice file, specify the filename (including the path) of the options custom parameter set in the <OptionsPreset> tag.

When the device driver is instantiated, a new custom parameter set is created and nested under the device driver.

3. When you write your device driver plug-in you can use the object model to access the options values. For more information on how to use the object model to access custom parameter sets, see Working with Parameters .

Accessing Device Drivers through the Object Model

The Softimage object model contains these objects:

• The Device object represents a device driver in Softimage. In the User Interface, device drivers are accessible through the Device Manager, which you can open with Tools > Devices on the Animate toolbar.

• The DeviceCollection gives access to all device drivers in Softimage. This is the scripting equivalent of the Device Manager, in which you can activate or deactivate a device, add or remove devices, etc.

• The Channel object represents the wire between a device and its input into Softimage. Each device driver has a set of channels and each channel can drive something different in the scene.

• The ChannelCollection gives access to all channels in the device.

| For more information on the specifics of each device driver object and their functions, see the C# and Scripting Reference.

To illustrate how to use the COM API, you can return to the Mouse driver example.

Example: getting the device driver information

You need to get pointers to the Application, the ChannelCollection, and the Device objects:

    HRESULT          l_hr;
    XSIApplicationPtr l_xsiApp(l_pApp);
    ChannelCollectionPtr l_pChannels;
    DevicePtr     l_pDevice;

    // Get the DeviceCollection from the Application
    DeviceCollectionPtr l_pDeviceManager;
    l_hr = l_xsiApp->get_Devices(&l_pDeviceManager);
    AssertAndReturn(l_hr);

    // Get the "Mouse" Device object
    l_hr = l_pDeviceManager->get_Item( CComVariant(L"Mouse"), &l_pDevice );
    AssertAndReturn(l_hr);

    // Get all channels in the Mouse device
    l_hr = l_pDevice->get_Channels( &l_pChannels );
    AssertAndReturn(l_hr);

Example: getting the information for all channels

Once you have all the channels for a device, you can enumerate the collection to get each member:

    // Iterate through all channels in the Mouse device
    l_hr = l_pChannels->get_Item( CComVariant(0), &g_pDeviceinfo.m_pChannelX);
    AssertAndReturn(l_hr);

    l_hr = l_pChannels->get_Item( CComVariant(1), &g_pDeviceinfo.m_pChannelY);
    AssertAndReturn(l_hr);

    l_hr = l_pChannels->get_Item( CComVariant(2), &g_pDeviceinfo.m_pChannelLB);
    AssertAndReturn(l_hr);
    l_hr = l_pChannels->get_Item( CComVariant(3), &g_pDeviceinfo.m_pChannelMB);
    AssertAndReturn(l_hr);

    l_hr = l_pChannels->get_Item( CComVariant(4), &g_pDeviceinfo.m_pChannelRB);
    AssertAndReturn(l_hr);

Example: getting the information for a specific channel

You can use the Channel ID to get the channel, which is faster than iterating the entire collection:

    l_hr = l_pDevice->get_Channel( 1, &g_pDeviceinfo.m_pChannelX);
    AssertAndReturn(l_hr);

    l_hr = l_pDevice->get_Channel( 2, &g_pDeviceinfo.m_pChannelY);
    AssertAndReturn(l_hr);

Adding Peripheral Files

You may want to create some extra files that can help support your driver in Softimage, such as:

• Device presets—you can specify values in a preset so that they load by default. For example, you can create a preset that has a channel with Command specified for the Action field and the name of the command or procedure specified for the Target field.

For more information on how to save and load presets, see the Softimage user guidethe Softimage user guide.

• Option custom property sets—you can create a custom property set that contains lists of special options for the device. When available, these options appear on the options window for your device, which the user can open by clicking the Options button on the Device Manager window.

For more information, see To add options to your device driver.

• Help files—you may also want to create a web page or a help file for users to explain the functionality of your device driver. In this case, you will need to include your HTML or WinHelp files with your library, .xsidevice, preset, and SPDL files when you distribute your device.

Communicating the Device Information to Softimage

Communicating the Device Information to Softimage

Softimage builds a set of device drivers based on the information that you provide in the .xsidevice file. When Softimage starts, it reads the .xsidevice file and creates a device driver for each device specified.

Understanding the XML device description file

When you want to tell Softimage about the device you want to use, you need to enter all the information in a Device Description file (.xsidevice). The .xsidevice file uses the following XML tag structure:

| Click on the tag name to see a description and any possible values in the sample below.

    <?xml version="1.0"?>
    <Device>
       <FileVersion>...</FileVersion>
       <DeviceName>...</DeviceName>
       <DeviceType>...</DeviceType>
       <DefaultPresetFilename>...</DefaultPresetFilename>
       <PluginFilename>...</PluginFilename>
       <SupportMultiInstance>...</SupportMultiInstance>
       <OtherInfo>...</OtherInfo>
       <OptionsPreset>...</OptionsPreset>
       <Description>
           <![CDATA[  ...  ]]>
       </Description>
       <Channel>
           <ChannelName>...</ChannelName>
           <ChannelDescription>
              <![CDATA[  ...  ]]>
           </ChannelDescription>
           <ChannelID>...</ChannelID>
           <ChannelDirectionType>...</ChannelDirectionType>
           <ChannelType>...</ChannelType>
           <ChannelMin>...</ChannelMin>
           <ChannelMax>...</ChannelMax>
           <SaveKeyOnSameValue>...</SaveKeyOnSameValue>
       </Channel>
       <Channel>
           ...
       </Channel>
       ...
    </Device>

Softimage uses these tags to build a list of available device drivers that users can access through the DeviceManager window.

| You must use a separate .xsidevice file for each device you want to make available in Softimage.

XML device description tags reference

The following table lists each XML tag for devices and how to use it.

Tag Name | Description
Device | Starting tag to decribe a device.
FileVersion | Version of the file.
DeviceName | Name of the device to be used. This name will be use to instantiate the device.
DeviceType | Type of device. Possible values are: • MIDI: Musical Instrument Digital Interface • SOCK: Socket Driver for Softimage|3D • Controller: Input device to control Softimage • Other: Other kind of device
DefaultPresetFilename | (Optional) Filename of the device’s default preset to be used when instantiating the driver.
PluginFilename | For non built-in drivers (MIDI or SOCK) this is the filename of the plug-in library. The extension is optional since it can be supported on multiple platforms.
SupportMultiInstance | Can the device be instantiated multiple times in the same session? Possible values are: • false: single instances only (default) • true: multiple instances are allowed
OtherInfo | (Optional) Other information used by the sock driver. May contain internal information or reserved data.
OptionsPreset | (Optional) Filename of the custom parameter set preset that contains device options. You may want to use options to create modes for keypad buttons. For example, you could specify an option for toggling whether or not to invoke capture sessions for keydown and keyup or just keydown.
Description | (Optional) An informative description of the device.

XML channel description tags reference

The following table lists each XML tag for channels and how to use it.

Tag Name | Description
Channel | Starting tag to describe a channel.
ChannelName | Name of the channel.
ChannelDescription | (Optional) A description of the channel.
ChannelID | The Identifier of the channel. This must be a non-negative number. Note: Two channels cannot have the same ID.
ChannelDirectionType | Direction Type of the channel. Possible values are: • input: channel is an input for Softimage • output: channel is an output for Softimage • io: channel is an input and an output
ChannelType | Type of channel. Possible values are: • slider: slider (commonly found on electronic audio equipment) • button: 2-state button (for example, ON or OFF) • 3states: 3-state button (for example, LEFT, MIDDLE or RIGHT) • jog: jog or dial control (commonly found on electronic audio equipment) • unknown: other type
ChannelMin | The hardware minimum value of the channel.
ChannelMax | The hardware maximum value of the channel.
SaveKeyOnSameValue | This is only for the slider type of channel. Possible values are: • true: For motion capture, a key is saved even if the value is the same as the previous one (ie there were no changes). • false: No new key if the value is the same. This can help on performance. (default)

Validating XML device description files

When you launch Softimage, it reads each XML device description file and checks to make sure it is valid. If all .xsidevice files are valid, when you click on the Add button from the DeviceManager, the Select a Device Driver dialog box lists each driver.

However, if one or more of your .xsidevice files is not valid, as soon as you activate the DeviceManager a message identifying the problem with the file appears in the history log of the Script Editor window. For example, if you forgot to use a closing tag, this message appears:

    'ERROR : "2000 - Error Parsing the DeviceInfo: mismatched tag at line ** col *
    '"

If you leave out the type of the device (no <DeviceType> set of tags), this message appears:

    'ERROR : "2000 - Error parsing the Device [device_name], File: [$factory]\\Data\Devices\[filename].xsidevice
    'Error parsing the device:
       '- Device plugin filename is empty
    '"

To validate XML device description files outside Softimage

To verify whether or not your .xsidevice file is valid, you can use the deviceparser tool:

1. Open a command prompt and navigate to the bin directory of your installation folder (for example, C:\Softimage\Softimage_7.5\Application\bin).

2. Type the following line:

           deviceparser.exe -list <filename>

| You can use this tool on just one file at a time.

If your file is valid, this message appears followed by a summary of the information for the device and all valid channels:

    Parsing device desription file: [$factory]\Data\Devices\[filename].xsidevice

       -- Succeeded

If your file is not valid, a message similar to this appears:

    Parsing device desription file: [$factory]\Data\Devices\[filename].xsidevice
    Error Parsing the DeviceInfo: mismatched tag at line ** col *

Autodesk Softimage v7.5