SDK Redrat Com API
SDK Redrat Com API
Introduction ............................................................................................................... 3
Prerequisites and SDK Installation............................................................................. 3
Changes..................................................................................................................... 3
From SDK V2.04 on .......................................................................................... 3
From SDK V1.10 on .......................................................................................... 3
From SDK V1.00 on .......................................................................................... 3
In SDK V0.17 .................................................................................................... 4
Using the COM API .................................................................................................. 4
Setting up the Program for Compilation................................................................. 4
Runtime Initialisation and Finalization Tasks......................................................... 5
Creating a RedRat3 Object..................................................................................... 5
Simple RedRat3 Operations ................................................................................... 6
Dealing with Errors................................................................................................ 6
Using an IR Signal Database and Outputting an IR Signal ..................................... 7
FastPath Signal Output ................................................................................... 9
Signal Input via Events .......................................................................................... 9
Signal Input from the Learning Detector .......................................................... 11
Signal Recognition............................................................................................... 11
The RedRat COM API............................................................................................. 12
Interfaces ............................................................................................................. 12
IRedRatLookup................................................................................................ 12
ICCWRedRat3................................................................................................. 12
ICCWRedRat4................................................................................................. 13
ISignalDB........................................................................................................ 13
IRR3Events ..................................................................................................... 14
IRR4Events ..................................................................................................... 14
ISignalInEventArgs.......................................................................................... 15
Structs ................................................................................................................. 15
CCWModulatedSignal ..................................................................................... 15
ToggleBit......................................................................................................... 15
CCWDoubleModulatedSignal.......................................................................... 15
CCWIrDaSignal............................................................................................... 15
CCWSubPacket ............................................................................................... 16
CCWRR3DeviceInfo ....................................................................................... 16
CCWRR3LocationInfo .................................................................................... 16
CCWRR4DeviceInfo ....................................................................................... 16
CCWRR4LocationInfo .................................................................................... 16
CCWAVDeviceInfo......................................................................................... 16
Enumerations....................................................................................................... 17
SignalEventAction ........................................................................................... 17
AVDeviceType ................................................................................................ 17
Introduction
The core support code for RedRat devices has been written as a .NET assembly,
however application code developed with VB6 and VC++6 needs to access this
functionality via COM. This document outlines how to use this API, i.e. instantiating
the COM objects, sending and receiving data from them, checking for errors etc. It
does not however go into detail about the semantics of the function calls, e.g. what the
function call put_EndOfSignalTimeout() means please see the .NET API document
for more information at this level.
The COM interface is created automatically by the .NET interoperability facilities in
the Common Language Runtime (CLR), the result being a COM Callable Wrapper
(CCW). The object structure in the .NET assembly is flattened for the CCW, so the
interfaces presented are basically the aggregation of itself and all superclasses for a
given class. Nonetheless, the function calls map pretty much one-to-one onto the
.NET API.
Hopefully you will find that it will not be necessary to know much about .NET and
mechanisms for COM interoperability to use the RedRat COM interfaces, but if you
would like more information on .NET and COM interoperability, please see the book
.NET and COM The Complete Interoperability Guide by Adam Nathan,
published by SAMS.
Changes
This section lists the major changes impacting the use of the COM API.
All .NET code has been ported to .NET 2.0, so to use the COM API, .NET 2.0
or 3.0 will need to be installed on the PC. Microsoft Vista is also now
supported.
The SDK has initial support for the RedRat4, sold under the product name
iretBox, some details of which are given at the end of this document.
The RedRat runtime for distribution with applications developed using the
SDK now supports side-by-side installation, i.e. one can have multiple
In SDK V0.17
Support has been added for outputting IrDa-like IR signals that are used by
some set-top boxes.
A new fastpath signal output mechanism has been introduced to reduce the
overhead of passing signal data from .NET to COM and back again for each
output. This is detailed in the section on signal DBs and output.
The Release() function should be called on all COM objects once the program
is finished. This decrements the reference count for the object, allowing the
system to free memory when the object is no longer in use.
This slightly more involved example obtains the firmware version number for output:
// Print the firmware version
BSTR fwVer;
hr = rr3->get_FirmwareVersion(&fwVer);
if (FAILED(hr))
fprintf(stderr, "rr3->get_FirmwareVersion() failed.);
else
// wprintf for BSTR
wprintf(L"\n -> Firmware Ver: %s\n", fwVer);
if (fwVer) SysFreeString(fwVer);
The PrintErrorMsg() function is basically code in the demo application that looks up
known/common HRESULT codes and prints out their meaning. More interesting is
the CreateExtendedErrorInfo() function whose body is shown below:
ISupportErrorInfo* suppErrInfo;
IErrorInfo* errorInfo;
_Exception* exception;
_Type* type;
BSTR desc, exTypeName, stackTrace;
if (comObj)
{
HRESULT hr = comObj->QueryInterface(IID_ISupportErrorInfo, (void**)&suppErrInfo);
if (SUCCEEDED(hr))
{
SysFreeString(desc);
SysFreeString(exTypeName);
SysFreeString(stackTrace);
type->Release();
exception->Release();
suppErrInfo->Release();
errorInfo->Release();
This code can be used with any COM object (i.e. object of type IUnkown), such as the
IRedRatLookup or ICCWRedRat3.
The AV device and signal data is stored in an XML file which can then be used in the
code below (with minimal error reporting see demo code for better error reporting).
// Create a COM signal DB for signal decoding.
ISignalDB* signalDB;
HRESULT hr = CoCreateInstance(CLSID_CCWSignalDB, NULL, CLSCTX_SERVER,
IID_ISignalDB, reinterpret_cast<void**>(&signalDB));
if (FAILED(hr))
fprintf(stderr, "CoCreateInstance of type \"ISignalDB\" failed.");
else
{
// Set filename of signal DB XML file
BSTR dbFileName = SysAllocString(OLESTR("D:\\Temp\\DeviceDB.xml"));
wprintf(L"Loading signal DB file: %s\n", dbFileName);
hr = signalDB->AddDeviceDB(dbFileName);
if (FAILED(hr))
fprintf(stderr, "Error loading signal DB file.");
SysFreeString(dbFileName);
}
// == USE THE SIGNAL DB ==
// ... and release when finished
if (signalDB) signalDB->Release();
The ISignalDB object is created directly using the COM CoCreateInstance call, the
filename is then passes to it which it then loads. This can then be used to lookup
signals for output:
void OutputIRSignal(ICCWRedRat3* rr3, ISignalDB* signalDB)
{
if ((rr3)&&(signalDB))
{
CCWModulatedSignal* outSig = new CCWModulatedSignal();
BSTR devName = SysAllocString(OLESTR("CD"));
BSTR sigName = SysAllocString(OLESTR("Pause"));
HRESULT hr = signalDB->GetSignal(devName, sigName, outSig);
if (FAILED(hr))
fprintf(stderr, "Failed to lookup signal in signal DB.\n");
else
{
hr = rr3->OutputModulatedSignal(outSig);
if (FAILED(hr))
fprintf(stderr, "Failed to output IR signal.\n");
else
wprintf(L"\n >>> Output signal: %s, %s\n\n", devName, sigName);
}
if (devName) SysFreeString(devName);
if (sigName) SysFreeString(sigName);
The first step is to pass the signal database object to the RedRat3 that will use it for
output. Following this, any signal in the DB can be output by passing the device and
signal name to the OutputSignal() method on ICCWRedRat3.
// == IMPORTANT ==
// == Disable RC signal input ==
rr3->put_RCDetectorEnabled(FALSE);
delete sigIn;
Once the event handler object is created, the RedRat3 remote control detector is
enabled. Incoming signals are handled in the IREventHandler object, so this thread
can simply sit and wait (using getchar() here) until remote control input should be
terminated.
Important: The remote control detector should be disabled before program
termination. If this is not done, the .NET layer remains awaiting IR signal data input
and will not terminate properly, and the RedRat3 will appear to hang when the
program is next started. Hopefully this will be sorted out soon!
So how is the event handler connected to the connection point, and how are the
incoming signal events handled?
The constructor of IREventHandler contains the code to connect to the event source:
// Attach to the event connection points.
HRESULT hRes = DispEventAdvise((IUnknown*)comRR3);
Once no more IR signal events are needed, then the application should disconnect
from the event source (found in the destructor of IREventHandler):
// Unattach from connection points.
DispEventUnadvise((IUnknown*)comRR3);
//
// Input from long-range remote control detector.
//
HRESULT __stdcall IREventHandler::RCSignalIn(const ICCWRedRat3* sender,
struct ISignalInEventArgs * e)
{
// This event could indicate an input signal, or that the detector
// has been enabled/disabled.
SignalEventAction action;
e->get_Action(&action);
switch (action)
{
case SignalEventAction_RC_DETECTOR_ENABLED:
printf("
--> In event: RC detector enabled.\n");
break;
case SignalEventAction_RC_DETECTOR_DISABLED:
printf("
--> In event: RC detector disabled.\n");
break;
case SignalEventAction_MODULATED_SIGNAL:
printf("
--> In event: Have RC signal.\n");
// If we have a signal DB, then see if we recognize the signal.
break;
case SignalEventAction_EXCEPTION:
printf("
--> In event: Have exception from signal input.\n");
break;
default:
// Ignore all other event types.
break;
}
return S_OK;
}
The ISignalInEventArgs object contains all event information, and the code above
uses the action attribute to print out information about the event.
Techy ote: The .NET design guidelines suggest that an event should have parameter
1 of type Object and parameter 2 of type EventArgs or subclass thereof. This turns out
to not be very helpful for COM clients as early-binding type information is not
available, so we have used custom event arguments here.
The above code uses the demo IREventHandler object. Basically the
GetModulatedSignal() method call initiates the process of signal input from the
learning detector, but the event handler receives the signal and adds it to the
database, so it is setup with the database to use (SetSignalDB()) and the name of the
signal when added to the DB (SetSignalame()).
This thread has to wait until the signal is input or it times-out, which is achieved here
by checking the event handler waiting flag using the GetWaiting() method.
Signal Recognition
The incoming signals can be compared against the signal DB, so allowing signal
recognition.
case SignalEventAction_MODULATED_SIGNAL:
printf("
--> In event: Have RC signal: ");
// If we have a signal DB, then see if we recognize the signal.
if (signalDB)
{
CCWModulatedSignal modSig;
BSTR sigKey;
HRESULT hr = e->get_ModulatedSignal(&modSig);
if (FAILED(hr))
fprintf(stderr, "Failed to read input IR signal\n");
else
{
hr = signalDB->DecodeSignal(modSig, &sigKey);
wprintf(L"Decoded signal->%s", sigKey);
}
}
break;
The DecodeSignal function gives a BSTR containing the device and signal name if the
signal has been recognized (sigKey in the above code). The information is of the
form: CD, Play, i.e. the two fields separated by a comma.
The above code is actually part of the incoming signal event handler, so as the signal
arrives it is recognized and then an appropriate action can be initiated.
Interfaces
IRedRatLookup
This is the entry point for discovery of RedRat3 and obtaining a RedRat3 object to
interact with (ICCWRedRat3).
interface IRedRatLookup : IDispatch {
HRESULT FindRedRat3s([out, retval] SAFEARRAY(BSTR)* pRetVal);
HRESULT GetRedRat3(
[in] BSTR rr3Name,
[out, retval] ICCWRedRat3** pRetVal);
HRESULT FindRedRat4s([out, retval] SAFEARRAY(BSTR)* pRetVal);
HRESULT GetRedRat4(
[in] BSTR rr4Name,
[out, retval] ICCWRedRat4** pRetVal);
};
ICCWRedRat3
Represents a physical RedRat3 device.
interface ICCWRedRat3 : IDispatch {
HRESULT MaxNumLengths([out, retval] long* pRetVal);
HRESULT MaxNumLengths([in] long pRetVal);
HRESULT SignalMemorySize([out, retval] long* pRetVal);
HRESULT SignalMemorySize([in] long pRetVal);
HRESULT RCDetectorEnabled([out, retval] VARIANT_BOOL* pRetVal);
HRESULT RCDetectorEnabled([in] VARIANT_BOOL pRetVal);
HRESULT ClearRCSignalInQueue();
HRESULT DeviceInformation([out, retval] CCWRR3DeviceInfo* pRetVal);
HRESULT LocationInformation([out, retval] CCWRR3LocationInfo* pRetVal);
HRESULT LocationInformation([in] CCWRR3LocationInfo pRetVal);
HRESULT FirmwareVersion([out, retval] BSTR* pRetVal);
HRESULT Blink();
HRESULT GetModulatedSignal([in] long timeout);
HRESULT CancelSignalInput();
HRESULT OutputModulatedSignal([in, out] CCWModulatedSignal outSig);
HRESULT OutputProntoSignal([in] BSTR prontoSignalData);
HRESULT OutputSignal([in] BSTR deviceName, [in] BSTR signalName);
HRESULT SetSignalDB([in] ISignalDB* signalDB);
HRESULT EndOfSignalTimeout([out, retval] double* pRetVal);
HRESULT EndOfSignalTimeout([in] double pRetVal);
HRESULT LengthMeasurementDelta([out, retval] long* pRetVal);
HRESULT LengthMeasurementDelta([in] long pRetVal);
HRESULT ModFreqPeriodsToMeasure([out, retval] long* pRetVal);
HRESULT ModFreqPeriodsToMeasure([in] long pRetVal);
};
ICCWRedRat4
interface ICCWRedRat4 : IDispatch {
HRESULT Connect();
HRESULT Disconnect();
HRESULT IsConnected([out, retval] VARIANT_BOOL* pRetVal);
HRESULT EnableIROutput([in] long output);
HRESULT DisableIROutput([in] long output);
HRESULT SetAllIROutputsEnabled([in] VARIANT_BOOL onOff);
HRESULT EnabledIROutputs([out, retval] SAFEARRAY(VARIANT_BOOL)*pRetVal);
HRESULT EnabledIROutputs([in] SAFEARRAY(VARIANT_BOOL) pRetVal);
HRESULT NoIROutputs([out, retval] long* pRetVal);
HRESULT MaxNumLengths([out, retval] long* pRetVal);
HRESULT MaxNumLengths([in] long pRetVal);
HRESULT SignalMemorySize([out, retval] long* pRetVal);
HRESULT SignalMemorySize([in] long pRetVal);
HRESULT RCDetectorEnabled([out, retval] VARIANT_BOOL* pRetVal);
HRESULT RCDetectorEnabled([in] VARIANT_BOOL pRetVal);
HRESULT ClearRCSignalInQueue();
HRESULT DeviceInformation([out, retval] CCWRR4DeviceInfo* pRetVal);
HRESULT LocationInformation([out, retval] CCWRR4LocationInfo* pRetVal);
HRESULT LocationInformation([in] CCWRR4LocationInfo pRetVal);
HRESULT FirmwareVersion([out, retval] BSTR* pRetVal);
HRESULT Blink();
HRESULT GetModulatedSignal([in] long timeout);
HRESULT CancelSignalInput();
HRESULT OutputModulatedSignal([in, out] CCWModulatedSignal* outSig);
HRESULT OutputIrDaSignal([in, out] CCWIrDaSignal* outSig);
HRESULT OutputProntoSignal([in] BSTR prontoSignalData);
HRESULT OutputSignal(
[in] BSTR deviceName,
[in] BSTR signalName);
HRESULT SetSignalDB([in] ISignalDB* signalDB);
HRESULT EndOfSignalTimeout([out, retval] double* pRetVal);
HRESULT EndOfSignalTimeout([in] double pRetVal);
HRESULT LengthMeasurementDelta([out, retval] long* pRetVal);
HRESULT LengthMeasurementDelta([in] long pRetVal);
HRESULT ModFreqPeriodsToMeasure([out, retval] long* pRetVal);
HRESULT ModFreqPeriodsToMeasure([in] long pRetVal);
};
ISignalDB
Object used for managing a database of signals. Has to be loaded with a set of precaptured signals in a device DB file see the Signal DB Utility for creation of such a
database file in XML format. The file data is passed in via the AddDeviceDB([in] BSTR
dbFileName) function. An input signal is then passed to the decoder via the
DecodeSignal function which returns a CCWSignalKey struct identifying the signal.
interface ISignalDB : IDispatch {
HRESULT AddDeviceDB([in] BSTR dbFileName);
HRESULT SaveDeviceDB([in] BSTR dbFileName);
HRESULT AddAVDevice([in] BSTR avDeviceName);
HRESULT AddAVDevice(
[in] BSTR avDeviceName
[in] VARIANT_BOOL readWrite);
HRESULT RemoveAVDevice([in] BSTR avDeviceName);
HRESULT GetAVDeviceInfo(
[in] BSTR avDeviceName,
[out, retval] CCWAVDeviceInfo* pRetVal);
HRESULT SetAVDeviceInfo([in] CCWAVDeviceInfo newAVDeviceInfo);
HRESULT GetDeviceNames([out, retval] SAFEARRAY(BSTR)* pRetVal);
HRESULT GetSignalNames(
[in] BSTR avDeviceName,
[out, retval] SAFEARRAY(BSTR)* pRetVal);
HRESULT AddSignal(
[in] BSTR devName,
[in, out] CCWModulatedSignal* newSig,
[in] VARIANT_BOOL overWrite);
HRESULT AddDoubleModSignal(
[in] BSTR avDeviceName,
IRR3Events
These events pass incoming signals from the RedRat3 to the application program.
dispinterface IRR3Events {
properties:
methods:
[id(0x00000001)]
void RCSignalIn(
[in] ICCWRedRat3* sender,
[in] ISignalInEventArgs* e);
[id(0x00000002)]
void LearningSignalIn(
[in] ICCWRedRat3* sender,
[in] ISignalInEventArgs* e);
};
IRR4Events
Used to pass incoming signals and other information to the application program from
the RedRat4 object.
dispinterface IRR4Events {
properties:
methods:
[id(0x00000001)]
void RCSignalIn(
[in] ICCWRedRat4* sender,
[in] ISignalInEventArgs* e);
[id(0x00000002)]
void LearningSignalIn(
ISignalInEventArgs
The events in IRR3Events pass two parameters, the first being the RedRat3 that
caused the event, and the second this object containing information about the event.
interface ISignalInEventArgs : IDispatch {
HRESULT Action([out, retval] SignalEventAction* pRetVal);
HRESULT ModulatedSignal([out, retval] CCWModulatedSignal* pRetVal);
HRESULT Exception([out, retval] _Exception** pRetVal);
HRESULT TimeStamp([out, retval] DATE* pRetVal);
HRESULT QueueSize([out, retval] long* pRetVal);
};
Structs
CCWModulatedSignal
struct tagCCWModulatedSignal {
BSTR name;
BSTR description;
double modFreq;
double intraSigPause;
long noRepeats;
SAFEARRAY(double) lengths;
SAFEARRAY(unsigned char) sigData;
long terminated;
SAFEARRAY(ToggleBit) toggleData;
} CCWModulatedSignal;
ToggleBit
A modulated signal can have data bits that toggle with one signal to the next.
struct tagToggleBit {
long bitNo;
long len1;
long len2;
} ToggleBit;
CCWDoubleModulatedSignal
When a single IR signal comprises two signals (sent alternately with every button
press) then this held in this struct. Can only be used for reading from the signal DB
and signal output, not signal creation.
struct tagCCWDoubleModulatedSignal {
long terminated;
BSTR name;
BSTR description;
CCWModulatedSignal signal1;
CCWModulatedSignal signal2;
} CCWDoubleModulatedSignal;
CCWIrDaSignal
struct tagCCWIrDaSignal {
BSTR name;
BSTR description;
double interSubPacketPause;
long noSubPackets;
SAFEARRAY(CCWSubPacket) subPacketArray;
CCWIrDaSignal;
CCWSubPacket
Constitutent part of an IrDa-like IR signal.
struct tagCCWSubPacket {
SAFEARRAY(single) data;
} CCWSubPacket;
CCWRR3DeviceInfo
Contains information about the USB device hardware.
struct tagCCWRR3DeviceInfo {
BSTR company;
BSTR productName;
long vendorID;
long productID;
long verMajor;
long verMinor;
BSTR serialNo;
} CCWRR3DeviceInfo;
CCWRR3LocationInfo
Used to hold information about the physical location of the device.
struct tagCCWRR3LocationInfo {
long serialNo;
BSTR name;
BSTR description;
} CCWRR3LocationInfo;
CCWRR4DeviceInfo
Contains information about the RedRa4.
struct tagCCWR43DeviceInfo {
BSTR company;
BSTR productName;
BSTR serialNo;
long verMajor;
long verMinor;
BSTR ipAddress;
BSTR macAddress;
} CCWRR4DeviceInfo;
CCWRR4LocationInfo
Used to hold information about the physical location of the device.
struct tagCCWRR4LocationInfo {
BSTR macAddress;
BSTR ipAddress;
BSTR name;
BSTR description;
} CCWRR4LocationInfo;
CCWAVDeviceInfo
Used to hold information about a particular AVDevice in the signal DB.
struct tagCCWAVDeviceInfo {
LPSTR name;
LPSTR manufacturer;
LPSTR deviceModelNumber;
LPSTR remoteModelNumber;
AVDeviceType AVDeviceType;
} CCWAVDeviceInfo;
Enumerations
When using enumerations, it is recommended that the descriptive value is used rather
than the number, for e.g. SignalEventAction_SELF_DETERMINE rather than the value 0.
SignalEventAction
When a signal in event is received, then this enumeration can be used to determine the
reason for the event.
enum {
SignalEventAction_SELF_DETERMINE,
SignalEventAction_MODULATED_SIGNAL,
SignalEventAction_DATA_PACKET,
SignalEventAction_EXCEPTION,
SignalEventAction_RC_DETECTOR_ENABLED,
SignalEventAction_RC_DETECTOR_DISABLED,
SignalEventAction_SIGNAL_ADDED,
SignalEventAction_SIGNAL_REMOVED,
SignalEventAction_SIGNAL_UPDATED
} SignalEventAction;
AVDeviceType
An AVDevice can be given one of the types listed below. This is intended to help (at
some point in the future) with narrowing signal DB searching or UI customization
based on device type.
enum {
AVDeviceType_TV,
AVDeviceType_VCR,
AVDeviceType_DVD,
AVDeviceType_CAMCORDER,
AVDeviceType_DVD_RECORDER,
AVDeviceType_PVR,
AVDeviceType_CD_PLAYER,
AVDeviceType_AMP,
AVDeviceType_TAPE_DECK,
AVDeviceType_TUNER,
AVDeviceType_MINI_DISK,
AVDeviceType_SAT_RECEIVER,
AVDeviceType_SET_TOP_BOX,
AVDeviceType_OTHER
} AVDeviceType;