Skip to content

Commit

Permalink
Add support to choose specify device playback by interface.
Browse files Browse the repository at this point in the history
	(You can now specify to play sound over seperate interfaces.)

+ Allow Actions to utilize fields in addition to type/value.
+ Fix right click crash in data grid view of profile editor.
+ Refactor and reorganize project source files.
  • Loading branch information
Robert Baykov committed Jan 14, 2016
1 parent 374d201 commit 792e4e6
Show file tree
Hide file tree
Showing 62 changed files with 381 additions and 256 deletions.
6 changes: 6 additions & 0 deletions GAVPI/ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
01.13.16
+ Add support to choose specify device playback by interface.
+ You can now specify to play sound over seperate interfaces.
+ Allow Actions to utilize fields in addition to type/value.
+ Fix right click crash in data grid view of profile editor.

14 changes: 9 additions & 5 deletions GAVPI/GAVPI.sln
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GAVPI", "GAVPI\GAVPI.csproj", "{DE850F8F-CE0C-4413-9C6B-5001989755EA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{84308259-3482-4829-A7E0-D81CD2CFBE1F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Notes", "Notes", "{C50B50BE-3AA7-46A5-A2ED-8066B3C5A6E4}"
ProjectSection(SolutionItems) = preProject
TO DO.txt = TO DO.txt
ChangeLog.txt = ChangeLog.txt
EndProjectSection
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Expand All @@ -22,7 +29,4 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
EndGlobal
216 changes: 91 additions & 125 deletions GAVPI/GAVPI/VI_Action_Sequence.cs → GAVPI/GAVPI/Core/Engine/Action.cs
Original file line number Diff line number Diff line change
@@ -1,116 +1,24 @@
using System;
using System.Collections.Generic;
using InputManager;
using NAudio.Wave;
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Speech.Synthesis;
using InputManager;
using NAudio.Wave;
using System.Threading;
using System.Windows.Forms;
using System.Xml;

/*
* A single action is composed of
* name - the name identifying the action
* sequence of Actions
* Actions are carried out sequentially one at time
*/
* Arbitrary abstract Action
* Currently one of
* Keyboard up/down/press
* Mouse up/down/press
* Wait
* ...add your own
* e.g. public partial class PlaySound() ...
*/

namespace GAVPI
{
public class VI_Action_Sequence : VI_TriggerEvent
{
// These type lists are used to populate ui elements,
// their (array string) value must match the class name specified bellow, ex : Action : Data_Set
// this is particularly important since the string will be cast to a class instance later.

public static List<string> PressAction_Types = new List<string>(
new string[] {
"KeyDown", "KeyUp", "KeyPress",
"MouseKeyDown","MouseKeyUp","MouseKeyPress"
});
public static List<string> SpeechAction_Types = new List<string>(
new string[] {
"Speak",
"Data_Speak"
});
public static List<string> PlaySoundAction_Types = new List<string>(
new string[] {
"Play_Sound"
});
public static List<string> TimingAction_Types = new List<string>(
new string[] {
"Wait"
});
public static List<string> DataAction_Types = new List<string>(
new string[] {
"Data_Set","Data_Decrement","Data_Increment"
});


public string name {get; set;}
public string type { get; set; }
public string comment { get; set; }

//sequences do not use value, but must have it as part of TriggerEvent interface
public string value { get; set; }

public List<Action> action_sequence;

public VI_Action_Sequence()
{
action_sequence = new List<Action>();
this.name = "new sequence";
this.type = this.GetType().Name;
this.value = null;
this.comment = "";
}

public VI_Action_Sequence(string name)
{
action_sequence = new List<Action>();
this.name = name;
this.type = this.GetType().Name;
this.value = null;
this.comment = "";
}
public List<Action> get_Action_sequence()
{
return this.action_sequence;
}
public void set_Action_sequence(List<Action> new_Action_sequence)
{
this.action_sequence = new_Action_sequence;
}

public void Add(Action new_Action)
{
action_sequence.Add(new_Action);
}
public void Remove(Action rm_Action)
{
action_sequence.Remove(rm_Action);
}
public void run()
{
foreach (Action action in action_sequence)
{
action.run();
// A little hotfix for starcitizen, it cant handle going fast.
Thread.Sleep(20);
}
}
}

/*
* Arbitrary abstract Action
* Currently one of
* Keyboard up/down/press
* Mouse up/down/press
* Wait
* ...add your own
* ig: public partial class PlaySound() ...
*/
public abstract class Action
{
public string type { get; set; }
Expand All @@ -128,6 +36,7 @@ public Action(string value)
this.type = this.GetType().Name;
}
}

public partial class KeyDown : Action
{
public KeyDown(string value) : base(value)
Expand All @@ -136,7 +45,7 @@ public KeyDown(string value) : base(value)
}
public override string value
{
get;set;
get; set;
}
public override void run()
{
Expand All @@ -145,7 +54,7 @@ public override void run()
}
public partial class KeyUp : Action
{
public KeyUp(string value): base(value)
public KeyUp(string value) : base(value)
{
this.value = value;
}
Expand All @@ -161,7 +70,7 @@ public override void run()
}
public partial class KeyPress : Action
{
public KeyPress(string value): base(value)
public KeyPress(string value) : base(value)
{
this.value = value;
}
Expand All @@ -178,7 +87,7 @@ public override void run()

public partial class MouseKeyDown : Action
{
public MouseKeyDown(string value): base(value)
public MouseKeyDown(string value) : base(value)
{
this.value = value;
}
Expand Down Expand Up @@ -255,15 +164,24 @@ public override string value
get;
set;
}

/*public static Speak readXML(XmlNode element, SpeechSynthesizer synth)
{
return (Speak)Activator.CreateInstance(
Type.GetType("GAVPI." + element.Attributes.GetNamedItem("type").Value),
element.Attributes.GetNamedItem("value").Value
);
}*/

public override void run()
{
try
{
Profile_Synthesis.SpeakAsync(value);
}
catch(Exception synth_err)
catch (Exception synth_err)
{
MessageBox.Show("Speech Profile_Synthesis Err : "+synth_err.Message,"Error",
MessageBox.Show("Speech Profile_Synthesis Err : " + synth_err.Message, "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation,
MessageBoxDefaultButton.Button1);
Expand All @@ -276,27 +194,72 @@ public partial class Play_Sound : Action
{
// Optional : WMP
// WMPLib.WindowsMediaPlayer player;
IWavePlayer waveOutDevice;

IWavePlayer wavePlayer;
AudioFileReader audioFileReader;
int playBackDeviceID;

public Play_Sound(string filename)
public const int defaultDeviceID = -1;

/* Extending actions to multiple values is a job for another day,
* for now we will simply serialize the deviceid and filename as such:
* ID|filename
* Deliminator is | since it is an invalid filename character, if no delim or other error fallback to default device.
* */
public Play_Sound(string filename,int deviceID)
{
this.value = filename;
this.playBackDeviceID = deviceID;

try
{
// Optional : WMP
// player = new WMPLib.WindowsMediaPlayer();
waveOutDevice = new WaveOut();

audioFileReader = new AudioFileReader(filename);
waveOutDevice.Init(audioFileReader);
WaveOut wavout = new WaveOut();
wavout.DeviceNumber = playBackDeviceID;
wavePlayer = wavout;
audioFileReader = new AudioFileReader(this.value);
}
catch (Exception e)
{
// TODO : Notify error.
}
}

public int getDeviceID()
{
return playBackDeviceID;
}

/*
* Instead of using an encoding hack, we modify the action parsing/saving cases in the profile code.
public static Tuple<int, string> decodeFilename(string encoded_filename)
{
const char delim = '|';
// No delim present, this is probably just the filename from an old profile.
if (!encoded_filename.Contains(delim))
{
return new Tuple<int, string>(defaultDeviceID, encoded_filename);
}
else
{
int decodedID;
string[] decoded = encoded_filename.Split(delim);
if (decoded.Length == 2 && Int32.TryParse(decoded[0], out decodedID))
{
return new Tuple<int, string>(decodedID, decoded[1]);
}
else
{
return new Tuple<int, string>(defaultDeviceID, encoded_filename);
}
}
}
public static string encodeFilename(int deviceID, string filename)
{
return deviceID.ToString() + delim + filename;
}*/

public override string value
{
get;
Expand All @@ -309,7 +272,10 @@ public override void run()
// Optional : WMP
// player.URL = this.value;
// player.controls.play();
waveOutDevice.Play();

// Device ID cannot be changed after init, so we will init here in case there is a live update.
wavePlayer.Init(audioFileReader);
wavePlayer.Play();
}
catch (Exception e)
{
Expand All @@ -320,10 +286,10 @@ public override void run()
#endregion

#region Data Actions
public partial class Data_Decrement : Action
public partial class Data_Decrement : Action
{
VI_Data data;
public Data_Decrement( VI_Data data, string value) : base(value)
public Data_Decrement(VI_Data data, string value) : base(value)
{
this.value = value;
}
Expand All @@ -334,7 +300,7 @@ public override string value
}
public override void run()
{

}
}
public partial class Data_Increment : Action
Expand Down Expand Up @@ -387,7 +353,7 @@ public partial class Data_Speak : Action
public Data_Speak(SpeechSynthesizer Profile_Synthesis, VI_Data data)
{
this.Profile_Synthesis = Profile_Synthesis;
this.data = data;
this.data = data;
}

public override string value
Expand Down Expand Up @@ -448,5 +414,5 @@ public override void run()
// }
//}

#endregion
#endregion
}
Loading

0 comments on commit 792e4e6

Please sign in to comment.