1. using System;
  2. using System.Drawing;
  3. using System.Collections;
  4. using System.ComponentModel;
  5. using System.Windows.Forms;
  6. using System.Data;
  7. using CookComputing.XmlRpc;
  8. using Microsoft.DirectX;
  9. using Microsoft.DirectX.DirectInput;
  10. using System.Threading;
  11.  
  12. namespace FFControl
  13. {
  14.         /// <summary>
  15.         /// Summary description for Form1.
  16.         /// </summary>
  17.         public class FFControl : System.Windows.Forms.Form
  18.         {
  19.                 private Microsoft.DirectX.DirectInput.Device ffActuator;
  20.                 private Boolean showFFOnly;
  21.                 private int[] forceAxes;
  22.                 private EffectObject eo;
  23.                 private Effect constantVibrate;
  24.                 private Thread queryThread;
  25.                 private System.Windows.Forms.Timer queryTimer;
  26.  
  27.                 //Cut GUI Elements
  28.                 /// <summary>
  29.                 /// Required designer variable.
  30.                 /// </summary>
  31.                 private System.ComponentModel.Container components = null;
  32.  
  33.                 public FFControl()
  34.                 {
  35.                         //
  36.                         // Required for Windows Form Designer support
  37.                         //
  38.                         InitializeComponent();
  39.  
  40.                         //
  41.                         // TODO: Add any constructor code after InitializeComponent call
  42.                         //
  43.                         PopulateDeviceList();
  44.                         queryThread = new Thread(new ThreadStart(this.xmlQuery));
  45.                         feedbackAmountSlider.Enabled = false;
  46.                         objectGUIDValue.Enabled = false;
  47.                         xmlQueryButton.Enabled = false;
  48.                         queryTimer = new System.Windows.Forms.Timer();
  49.                         queryTimer.Interval = 3100;
  50.                         queryTimer.Tick += new System.EventHandler(this.startQueryThread);
  51.                         feedbackAmountSlider.Maximum = 100;
  52.                 }
  53.  
  54.                 /// <summary>
  55.                 /// Clean up any resources being used.
  56.                 /// </summary>
  57.                 protected override void Dispose( bool disposing )
  58.                 {
  59.                         if(eo != null)
  60.                         {
  61.                                 eo.Stop();
  62.                         }
  63.                         if( disposing )
  64.                         {
  65.                                 if (components != null)
  66.                                 {
  67.                                         components.Dispose();
  68.                                 }
  69.                         }
  70.                         base.Dispose( disposing );
  71.                 }
  72.  
  73.                 //Cut Layout Code
  74.  
  75.                 /// <summary>
  76.                 /// The main entry point for the application.
  77.                 /// </summary>
  78.                 [STAThread]
  79.                 static void Main()
  80.                 {
  81.                         Application.Run(new FFControl());       
  82.                 }
  83.  
  84.  
  85.                 struct SecondLifeRPCValue
  86.                 {
  87.                         public string Channel;
  88.                         public string StringValue;
  89.                         public int IntValue;
  90.                 };
  91.  
  92.                 [XmlRpcUrl("http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi")]
  93.                 interface ISecondLifeRequest
  94.                 {
  95.                         [XmlRpcMethod("llRemoteData")]
  96.                         //SecondLifeRPCValue llRemoteData(string Channel, string StringValue, int IntValue);
  97.                         SecondLifeRPCValue llRemoteData(SecondLifeRPCValue sendVal);
  98.                 }
  99.  
  100.                 private void quitButton_Click(object sender, System.EventArgs e)
  101.                 {
  102.                         Application.Exit();
  103.                 }
  104.  
  105.                 private void PopulateDeviceList()
  106.                 {
  107.                         //Populate All devices
  108.                         controlSelect.Items.Clear();
  109.                         if(showFFOnly)
  110.                         {
  111.                                 foreach(DeviceInstance di in Manager.GetDevices(DeviceClass.All, EnumDevicesFlags.ForceFeeback))
  112.                                 {
  113.                                         controlSelect.Items.Add(di.InstanceName);
  114.                                 }
  115.                         }
  116.                         else
  117.                         {
  118.                                 foreach(DeviceInstance di in Manager.Devices)
  119.                                 {
  120.                                         controlSelect.Items.Add(di.InstanceName);
  121.                                 }
  122.                         }
  123.  
  124.                 }
  125.  
  126.                 private void ffOnlyCheckBox_CheckedChanged(object sender, System.EventArgs e)
  127.                 {
  128.                         if(ffOnlyCheckBox.Checked)
  129.                         {
  130.                                 showFFOnly = true;
  131.                         }
  132.                         else
  133.                         {
  134.                                 showFFOnly = false;
  135.                         }
  136.                         PopulateDeviceList();
  137.                 }
  138.  
  139.                 private void controlSelect_SelectedIndexChanged(object sender, System.EventArgs e)
  140.                 {
  141.                         if(ffActuator != null)  ffActuator.Unacquire();
  142.                         feedbackAmountSlider.Enabled = false;
  143.                         objectGUIDValue.Enabled = false;
  144.                         xmlQueryButton.Enabled = false;
  145.                         foreach(DeviceInstance di in Manager.GetDevices(DeviceClass.All, EnumDevicesFlags.ForceFeeback))
  146.                         {
  147.                                 if(((string)controlSelect.SelectedItem).CompareTo(di.InstanceName) == 0)
  148.                                 {
  149.                                         ffActuator = new Device(di.InstanceGuid);
  150.                                         if(ffActuator == null)
  151.                                         {
  152.                                                 throw new Exception("Cannot instantiate joystick");
  153.                                         }
  154.                                         //set cooperative level.
  155.                                         ffActuator.SetCooperativeLevel(
  156.                                                 this,
  157.                                                 CooperativeLevelFlags.Exclusive | CooperativeLevelFlags.Background);
  158.  
  159.                                         //Set axis mode absolute.
  160.                                         ffActuator.Properties.AxisModeAbsolute = true;
  161.  
  162.                                         //Acquire joystick for capturing.
  163.                                         ffActuator.Acquire();
  164.  
  165.                                         //Configure axes
  166.                                         foreach(DeviceObjectInstance doi in ffActuator.Objects)
  167.                                         {
  168.  
  169.                                                 //Set axes ranges.
  170.                                                 if((doi.ObjectId & (int)DeviceObjectTypeFlags.Axis) != 0)
  171.                                                 {
  172.                                                         ffActuator.Properties.SetRange(
  173.                                                                 ParameterHow.ById,
  174.                                                                 doi.ObjectId,
  175.                                                                 new InputRange(-5000,5000));
  176.                                                 }
  177.  
  178.                                                 int[] temp;
  179.  
  180.                                                 // Get info about first two FF axii on the device
  181.                                                 if ((doi.Flags & (int)ObjectInstanceFlags.Actuator) != 0)
  182.                                                 {
  183.                                                         if (forceAxes != null)
  184.                                                         {
  185.                                                                 temp = new int[forceAxes.Length + 1];                   
  186.                                                                 forceAxes.CopyTo(temp,0);
  187.                                                                 forceAxes = temp;
  188.                                                         }
  189.                                                         else
  190.                                                         {
  191.                                                                 forceAxes = new int[1];
  192.                                                         }
  193.  
  194.                                                         // Store the offset of each axis.
  195.                                                         forceAxes[forceAxes.Length - 1] = doi.Offset;
  196.                                                         if (forceAxes.Length == 2)
  197.                                                         {
  198.                                                                 break;
  199.                                                         }
  200.  
  201.                                                         string path =
  202.                                                                 @"C:\temp\force.ffe";
  203.                                                         EffectList el = null;
  204.                                                         el = ffActuator.GetEffects(path,FileEffectsFlags.ModifyIfNeeded);
  205.                                                         EffectObject feo = null;
  206.                                                         foreach(FileEffect fe in el)
  207.                                                         {
  208.                                                                 constantVibrate = fe.EffectStruct;
  209.                                                                 feo = new EffectObject(
  210.                                                                           fe.EffectGuid,
  211.                                                                           fe.EffectStruct,
  212.                                                                           ffActuator);
  213.                                                                 try
  214.                                                                 {
  215.                                                                         feo.Download();
  216.                                                                 }
  217.                                                                 catch(Exception ex)
  218.                                                                 {
  219.                                                                         throw new Exception("Could not download force feedback effect file.", ex);
  220.                                                                 }
  221.                                                                 eo = feo;
  222.                                                                 break;
  223.                                                         }
  224.                                                         constantVibrate.Constant.Magnitude = 0;
  225.                                                         eo.SetParameters(constantVibrate, EffectParameterFlags.TypeSpecificParams);
  226.                                                         eo.Download();
  227.                                                         eo.Start(1);
  228.                                                         feedbackAmountSlider.Enabled = true;
  229.                                                         objectGUIDValue.Enabled = true;
  230.                                                         xmlQueryButton.Enabled = true;
  231.                                                 }
  232.                                         }
  233.                                         break;
  234.                                 }
  235.                         }
  236.                 }
  237.  
  238.                 private void feedbackAmountSlider_Scroll(object sender, System.EventArgs e)
  239.                 {
  240.                         constantVibrate.Constant.Magnitude = (feedbackAmountSlider.Value*(10000/feedbackAmountSlider.Maximum));
  241.                         eo.SetParameters(constantVibrate, EffectParameterFlags.TypeSpecificParams);
  242.                         eo.Download();
  243.                 }
  244.  
  245.                 private void xmlQueryButton_Click(object sender, System.EventArgs e)
  246.                 {
  247.                         if(queryTimer.Enabled)
  248.                         {
  249.                                 queryTimer.Stop();
  250.                         }
  251.                         else
  252.                         {
  253.                                 queryTimer.Start();
  254.                         }
  255.                        
  256.                 }
  257.  
  258.                 private void startQueryThread(object sender,EventArgs eArgs)
  259.                 {
  260.                         if(!queryThread.IsAlive)
  261.                         {
  262.                                 queryThread = null;
  263.                                 queryThread = new Thread(new ThreadStart(this.xmlQuery));
  264.                                 Console.WriteLine("ThreadState: " + queryThread.ThreadState);
  265.                                 queryThread.Start();
  266.                         }
  267.                 }
  268.  
  269.                 private void xmlQuery()
  270.                 {
  271.                         if(objectGUIDValue.Text == "")
  272.                         {
  273.                                 return;
  274.                         }
  275.                         ISecondLifeRequest rpcQuery = (ISecondLifeRequest)XmlRpcProxyGen.Create(typeof(ISecondLifeRequest));
  276.  
  277.                         try
  278.                         {
  279.                                 SecondLifeRPCValue sendVal;
  280.                                 sendVal.Channel = objectGUIDValue.Text;
  281.                                 sendVal.StringValue = "Test";
  282.                                 sendVal.IntValue = 0;
  283.                                 SecondLifeRPCValue retVal = rpcQuery.llRemoteData(sendVal);
  284.                                 stringReturnBox.Text = retVal.StringValue;
  285.                                 intReturnBox.Text = Convert.ToString(retVal.IntValue, 10);
  286.                                 if(retVal.IntValue >= 0)
  287.                                 {
  288.                                         feedbackAmountSlider.Value = retVal.IntValue;
  289.                                 }
  290.                                 else
  291.                                 {
  292.                                         feedbackAmountSlider.Value = 0;
  293.                                         queryTimer.Stop();
  294.                                 }
  295.                         }
  296.                         catch (XmlRpcFaultException fex)
  297.                         {
  298.                                 Console.WriteLine("Fault Response: {0} {1}",
  299.                                         fex.FaultCode, fex.FaultString);
  300.                                 stringReturnBox.Text = fex.FaultString;
  301.                         }
  302.  
  303.                 }
  304.  
  305.         }