using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using CookComputing.XmlRpc;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;
using System.Threading;
namespace FFControl
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class FFControl : System.Windows.Forms.Form
{
private Microsoft.DirectX.DirectInput.Device ffActuator;
private Boolean showFFOnly;
private int[] forceAxes;
private EffectObject eo;
private Effect constantVibrate;
private Thread queryThread;
private System.Windows.Forms.Timer queryTimer;
//Cut GUI Elements
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public FFControl()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
PopulateDeviceList();
queryThread =
new Thread
(new ThreadStart
(this.
xmlQuery));
feedbackAmountSlider.Enabled = false;
objectGUIDValue.Enabled = false;
xmlQueryButton.Enabled = false;
queryTimer =
new System.
Windows.
Forms.
Timer();
queryTimer.Interval = 3100;
queryTimer.
Tick +=
new System.
EventHandler(this.
startQueryThread);
feedbackAmountSlider.Maximum = 100;
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if(eo != null)
{
eo.Stop();
}
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
//Cut Layout Code
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.
Run(new FFControl
());
}
struct SecondLifeRPCValue
{
public string Channel;
public string StringValue;
public int IntValue;
};
[XmlRpcUrl("http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi")]
interface ISecondLifeRequest
{
[XmlRpcMethod("llRemoteData")]
//SecondLifeRPCValue llRemoteData(string Channel, string StringValue, int IntValue);
SecondLifeRPCValue llRemoteData(SecondLifeRPCValue sendVal);
}
private void quitButton_Click(object sender, System.EventArgs e)
{
Application.Exit();
}
private void PopulateDeviceList()
{
//Populate All devices
controlSelect.Items.Clear();
if(showFFOnly)
{
foreach(DeviceInstance di in Manager.GetDevices(DeviceClass.All, EnumDevicesFlags.ForceFeeback))
{
controlSelect.Items.Add(di.InstanceName);
}
}
else
{
foreach(DeviceInstance di in Manager.Devices)
{
controlSelect.Items.Add(di.InstanceName);
}
}
}
private void ffOnlyCheckBox_CheckedChanged(object sender, System.EventArgs e)
{
if(ffOnlyCheckBox.Checked)
{
showFFOnly = true;
}
else
{
showFFOnly = false;
}
PopulateDeviceList();
}
private void controlSelect_SelectedIndexChanged(object sender, System.EventArgs e)
{
if(ffActuator != null) ffActuator.Unacquire();
feedbackAmountSlider.Enabled = false;
objectGUIDValue.Enabled = false;
xmlQueryButton.Enabled = false;
foreach(DeviceInstance di in Manager.GetDevices(DeviceClass.All, EnumDevicesFlags.ForceFeeback))
{
if(((string)controlSelect.SelectedItem).CompareTo(di.InstanceName) == 0)
{
ffActuator =
new Device
(di.
InstanceGuid);
if(ffActuator == null)
{
throw new Exception
("Cannot instantiate joystick");
}
//set cooperative level.
ffActuator.SetCooperativeLevel(
this,
CooperativeLevelFlags.Exclusive | CooperativeLevelFlags.Background);
//Set axis mode absolute.
ffActuator.Properties.AxisModeAbsolute = true;
//Acquire joystick for capturing.
ffActuator.Acquire();
//Configure axes
foreach(DeviceObjectInstance doi in ffActuator.Objects)
{
//Set axes ranges.
if((doi.ObjectId & (int)DeviceObjectTypeFlags.Axis) != 0)
{
ffActuator.Properties.SetRange(
ParameterHow.ById,
doi.ObjectId,
new InputRange
(-
5000,
5000));
}
int[] temp;
// Get info about first two FF axii on the device
if ((doi.Flags & (int)ObjectInstanceFlags.Actuator) != 0)
{
if (forceAxes != null)
{
temp =
new int[forceAxes.
Length +
1];
forceAxes.CopyTo(temp,0);
forceAxes = temp;
}
else
{
}
// Store the offset of each axis.
forceAxes[forceAxes.Length - 1] = doi.Offset;
if (forceAxes.Length == 2)
{
break;
}
string path =
@"C:\temp\force.ffe";
EffectList el = null;
el = ffActuator.GetEffects(path,FileEffectsFlags.ModifyIfNeeded);
EffectObject feo = null;
foreach(FileEffect fe in el)
{
constantVibrate = fe.EffectStruct;
fe.EffectGuid,
fe.EffectStruct,
ffActuator);
try
{
feo.Download();
}
catch(Exception ex)
{
throw new Exception
("Could not download force feedback effect file.", ex
);
}
eo = feo;
break;
}
constantVibrate.Constant.Magnitude = 0;
eo.SetParameters(constantVibrate, EffectParameterFlags.TypeSpecificParams);
eo.Download();
eo.Start(1);
feedbackAmountSlider.Enabled = true;
objectGUIDValue.Enabled = true;
xmlQueryButton.Enabled = true;
}
}
break;
}
}
}
private void feedbackAmountSlider_Scroll(object sender, System.EventArgs e)
{
constantVibrate.Constant.Magnitude = (feedbackAmountSlider.Value*(10000/feedbackAmountSlider.Maximum));
eo.SetParameters(constantVibrate, EffectParameterFlags.TypeSpecificParams);
eo.Download();
}
private void xmlQueryButton_Click(object sender, System.EventArgs e)
{
if(queryTimer.Enabled)
{
queryTimer.Stop();
}
else
{
queryTimer.Start();
}
}
private void startQueryThread(object sender,EventArgs eArgs)
{
if(!queryThread.IsAlive)
{
queryThread = null;
queryThread =
new Thread
(new ThreadStart
(this.
xmlQuery));
Console.WriteLine("ThreadState: " + queryThread.ThreadState);
queryThread.Start();
}
}
private void xmlQuery()
{
if(objectGUIDValue.Text == "")
{
return;
}
ISecondLifeRequest rpcQuery =
(ISecondLifeRequest
)XmlRpcProxyGen.
Create(typeof(ISecondLifeRequest
));
try
{
SecondLifeRPCValue sendVal;
sendVal.Channel = objectGUIDValue.Text;
sendVal.StringValue = "Test";
sendVal.IntValue = 0;
SecondLifeRPCValue retVal = rpcQuery.llRemoteData(sendVal);
stringReturnBox.Text = retVal.StringValue;
intReturnBox.Text = Convert.ToString(retVal.IntValue, 10);
if(retVal.IntValue >= 0)
{
feedbackAmountSlider.Value = retVal.IntValue;
}
else
{
feedbackAmountSlider.Value = 0;
queryTimer.Stop();
}
}
catch (XmlRpcFaultException fex)
{
Console.WriteLine("Fault Response: {0} {1}",
fex.FaultCode, fex.FaultString);
stringReturnBox.Text = fex.FaultString;
}
}
}