Add project

This commit is contained in:
Allen Wolf
2024-01-10 16:03:20 -06:00
parent 2af2696421
commit 94a14ba2ce
32 changed files with 37177 additions and 0 deletions

25
LICENSE Executable file
View File

@ -0,0 +1,25 @@
The MIT License (MIT)
Copyright (c) 2017 Jitnaught
Copyright (c) 2019 EmbarassingUsername
Copyright (c) 2020 ZenitH-AT
Contributors: tgebauer, Richard Schwab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

90
README.md Executable file
View File

@ -0,0 +1,90 @@
# JN Soundboard - ZenitH-AT Fork
A program written in C# using the NAudio library that uses hotkeys to play sounds into a chosen sound device. It is similar to [EXP Soundboard](https://sourceforge.net/projects/expsoundboard/), except that JN Soundboard is not as cross-platform as EXP, but, there are more features in JN than EXP.
A fork of EmbarassingUsername's fork of Jitnaught's JN Soundboard in order to add more features and fix some issues.
My (ZenitH-AT) main goal with this fork was to make JN Soundboard into a "set and forget" program, with all options being remembered across launches and the ability to start the program with windows in a tray icon, as well as allow for custom sound volume (to easily match it with your microphone if using the loopback feature).
## Features:
* Can play MP3, WAV, WMA, M4A, and AC3 audio files.
* Play sounds through any sound device. (speakers, virtual audio cable, etc.)
* Microphone loopback (loops microphone sound through playback device). Allows you to also use your real mic at the same time as the soundboard.
* Add, edit, remove, and clear hotkeys.
* Can play a random sound from a list of sounds. Just select multiple files when adding a hotkey!
* Restrict hotkey so that the hotkey is only played when a certain window is in the foreground.
* Save and load hotkeys to XML file.
* Hotkey that stops currently playing sound.
* Hotkeys that load XML files containing sound hotkeys.
* Auto press your game or chat program's push-to-talk key when playing a sound.
* Text-to-speech WAV file creator.
* Optional second audio output so you can hear the sound playing.
## Requires:
* .NET Framework 4.6
* NAudio
## How to play sounds through your speakers or headphones only:
1. Set the "Speakers or Virtual Cable" device to your speakers or headphones then load and play sounds.
## How to play sound through your microphone so that people in your game or chat program can hear them:
In Windows, a playback device is normally a set of speakers or headphones, but it can also be a virtual cable. A virtual cable acts like a playback device, but is connected behind the scenes to a virtual microphone. Thus, an output device can masquerade as an input device. This lets applications like the soundboard "speak" through your games and chat applications, as long as you set the virtual cable as your microphone in Windows or in the app. In order to use your real microphone to chat at the same time, we have to "loopback" your microphone into the virtual output device. (If you were to loopback your mic to your speakers or headphones, instead, you would hear yourself speak. If you do this with your speakers, though, it might cause feedback.)
1. You will need to install a virtual audio cable. It will act as an audio output that sends played sounds to its virtual microphone. I recommend [VB-CABLE](https://www.vb-audio.com/Cable/index.htm)).
2. Set the "Speakers or Virtual Cable" device to the virtual audio output cable. E.g., "CABLE Input (VB-Audio Virtual Cable)".
3. (Optional) Set the microphone loopback device to your real microphone. This will mix your real mic in with the virtual mic so that you can speak *and* play sounds. Note: Loopback only occurs when the "Enable Hotkeys and Loopback" checkbox is checked.
4. (Optional) If you would also like to have the sounds played through your speakers or headphones, set Playback Device 2 to that device.
5. Make sure the virtual microphone (e.g., "CABLE Output (VB-Audio Virtual Cable)") is either your default microphone in Windows or set as the desired microphone in the game or application that is going to use it.
## Screenshots:
![Main window](https://ibb.co/sHksxX2)
![Add/edit sound window](https://ibb.co/3YqPCDD)
![Settings window](https://ibb.co/dbHRkrh)
![Text-to-speech window](https://ibb.co/qr77TFP)
## EmbarassingUsername's changes:
* Added second sound output for also playing the sounds to yourself while playing them through the virtual cable.
* Added gender selector for Text-to-Speech (TTS) dialog.
* Added a Preview button to the TTS dialog along with a Stop button.
* TTS dialog text is now multi-line.
* TTS dialog now prompts for a filename instead of using the text as the filename.
* Added tooltips to audio device selectors with quick instructions.
* Relabeled device selectors in main form to be more clear.
* Added "clear" buttons to all key-input text boxes. It was not obvious that Esc would clear them.
* Fixed Esc button closing the Add Hotkey dialog (instead of clearing the hotkey) when the keys textbox has focus.
* Forced dialogs to open in the center of the main window.
* Forced main window to open in center of screen.
* Removed the requirement that there be hotkeys defined in order to enable the main checkbox. This is so Loopback can be tested even without there being hotkeys defined.
* In Settings dialog, prevented the "Stop all sounds hotkey" textbox from automatically having focus when opening the settings.
* Adjusted some popup messages to make them more simple and/or clear.
* Added detailed information and instructions to README regarding using a virtual cable.
* Rearranged the main form slightly; added explanatory text to the main Enabled checkbox.
* Fixed some button alignments.
* Refactored some of the code.
## ZenitH-AT's changes:
* Added start with windows and start minimised to settings.
* Program now only allows for one instance at a time.
* Added open and exit buttons to the tray icon.
* All options are saved as settings automatically so that they are remembered between launches.
* Device and window selector refreshes will reselect the last item if still present after the reload.
* Enable hotkeys and enable loopback are now separate buttons.
* Launching the program will start loopback without needing to untick and retick the checkbox.
* Added a scrollable sound volume control to the main form and add/edit sound form (the slider in the main form only affects sounds without custom volumes).
* Fixed several bugs related to the TTS form.
* TTS form now uses a checkbox to add to list, rather than use a different button.
* TTS form now allows the user to set a window restriction and custom volume.
* Fixed a few issues related to XML validation.
* XML saving now uses a timer to prevent file in use errors when saving settings (allows for more settings to be saved and push to talk hotkey timer to be reduced)
* Improved the responsiveness of key fields without causing clicking the field to set the key (timer interval is temporarily lowered after first timer tick until leaving the field)
* All keys fields no longer show context menus to make setting a key as right click easier (ShortcutsEnabled false).
* Reimplemented the Keys enum to include definitions for every key possible. LuaMacros users rejoice!
* Centralised redundant code in various areas (e.g. window listing and key combination code).
* Adjusted UI sizing, padding, tab stops and so on.
* Adjusted/added some tooltips.
* Fixed additional minor issues and inconsistencies.
* Refactored some of the code.

287
src/AddEditHotkeyForm.Designer.cs generated Executable file
View File

@ -0,0 +1,287 @@
namespace JNSoundboard
{
partial class AddEditHotkeyForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AddEditHotkeyForm));
this.btnOK = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.tbLocation = new System.Windows.Forms.TextBox();
this.labelKeys = new System.Windows.Forms.Label();
this.labelLocation = new System.Windows.Forms.Label();
this.btnBrowseSoundLocation = new System.Windows.Forms.Button();
this.keysTimer = new System.Windows.Forms.Timer(this.components);
this.btnReloadWindows = new System.Windows.Forms.Button();
this.cbWindows = new System.Windows.Forms.ComboBox();
this.clearHotkey = new System.Windows.Forms.Button();
this.pnAddEditSound = new System.Windows.Forms.Panel();
this.nSoundVolume = new System.Windows.Forms.NumericUpDown();
this.vsSoundVolume = new NAudio.Gui.VolumeSlider();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.tbName = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.tbKeys = new System.Windows.Forms.TextBox();
this.pnAddEditSound.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nSoundVolume)).BeginInit();
this.SuspendLayout();
//
// btnOK
//
this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnOK.Location = new System.Drawing.Point(114, 237);
this.btnOK.Margin = new System.Windows.Forms.Padding(3, 10, 3, 3);
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size(75, 23);
this.btnOK.TabIndex = 8;
this.btnOK.Text = "OK";
this.btnOK.UseVisualStyleBackColor = true;
this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(195, 237);
this.btnCancel.Margin = new System.Windows.Forms.Padding(3, 10, 3, 3);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 9;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// tbLocation
//
this.tbLocation.Location = new System.Drawing.Point(12, 74);
this.tbLocation.Name = "tbLocation";
this.tbLocation.Size = new System.Drawing.Size(213, 20);
this.tbLocation.TabIndex = 1;
//
// labelKeys
//
this.labelKeys.AutoSize = true;
this.labelKeys.Location = new System.Drawing.Point(12, 102);
this.labelKeys.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0);
this.labelKeys.Name = "labelKeys";
this.labelKeys.Size = new System.Drawing.Size(30, 13);
this.labelKeys.TabIndex = 4;
this.labelKeys.Text = "Keys";
//
// labelLocation
//
this.labelLocation.AutoSize = true;
this.labelLocation.Location = new System.Drawing.Point(12, 58);
this.labelLocation.Name = "labelLocation";
this.labelLocation.Size = new System.Drawing.Size(76, 13);
this.labelLocation.TabIndex = 11;
this.labelLocation.Text = "Location of file";
//
// btnBrowseSoundLocation
//
this.btnBrowseSoundLocation.Location = new System.Drawing.Point(231, 73);
this.btnBrowseSoundLocation.Name = "btnBrowseSoundLocation";
this.btnBrowseSoundLocation.Size = new System.Drawing.Size(24, 22);
this.btnBrowseSoundLocation.TabIndex = 2;
this.btnBrowseSoundLocation.Text = "...";
this.btnBrowseSoundLocation.UseVisualStyleBackColor = true;
this.btnBrowseSoundLocation.Click += new System.EventHandler(this.btnBrowseSoundLocation_Click);
//
// keysTimer
//
this.keysTimer.Tick += new System.EventHandler(this.keysTimer_Tick);
//
// btnReloadWindows
//
this.btnReloadWindows.Image = ((System.Drawing.Image)(resources.GetObject("btnReloadWindows.Image")));
this.btnReloadWindows.Location = new System.Drawing.Point(219, 59);
this.btnReloadWindows.Name = "btnReloadWindows";
this.btnReloadWindows.Size = new System.Drawing.Size(22, 23);
this.btnReloadWindows.TabIndex = 7;
this.btnReloadWindows.UseVisualStyleBackColor = true;
this.btnReloadWindows.Click += new System.EventHandler(this.btnReloadWindows_Click);
//
// cbWindows
//
this.cbWindows.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.cbWindows.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
this.cbWindows.FormattingEnabled = true;
this.cbWindows.Location = new System.Drawing.Point(0, 60);
this.cbWindows.Name = "cbWindows";
this.cbWindows.Size = new System.Drawing.Size(213, 21);
this.cbWindows.TabIndex = 6;
//
// clearHotkey
//
this.clearHotkey.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.clearHotkey.ForeColor = System.Drawing.Color.Red;
this.clearHotkey.Location = new System.Drawing.Point(231, 117);
this.clearHotkey.Name = "clearHotkey";
this.clearHotkey.Size = new System.Drawing.Size(22, 22);
this.clearHotkey.TabIndex = 4;
this.clearHotkey.Text = "X";
this.clearHotkey.UseVisualStyleBackColor = true;
this.clearHotkey.Click += new System.EventHandler(this.clearHotkey_Click);
//
// pnAddEditSound
//
this.pnAddEditSound.Controls.Add(this.nSoundVolume);
this.pnAddEditSound.Controls.Add(this.vsSoundVolume);
this.pnAddEditSound.Controls.Add(this.label3);
this.pnAddEditSound.Controls.Add(this.label2);
this.pnAddEditSound.Controls.Add(this.btnReloadWindows);
this.pnAddEditSound.Controls.Add(this.cbWindows);
this.pnAddEditSound.Location = new System.Drawing.Point(12, 146);
this.pnAddEditSound.Name = "pnAddEditSound";
this.pnAddEditSound.Size = new System.Drawing.Size(258, 81);
this.pnAddEditSound.TabIndex = 4;
//
// nSoundVolume
//
this.nSoundVolume.Location = new System.Drawing.Point(219, 16);
this.nSoundVolume.Name = "nSoundVolume";
this.nSoundVolume.Size = new System.Drawing.Size(39, 20);
this.nSoundVolume.TabIndex = 5;
this.nSoundVolume.Value = new decimal(new int[] {
100,
0,
0,
0});
this.nSoundVolume.ValueChanged += new System.EventHandler(this.nSoundVolume_ValueChanged);
//
// vsSoundVolume
//
this.vsSoundVolume.Location = new System.Drawing.Point(0, 16);
this.vsSoundVolume.Name = "vsSoundVolume";
this.vsSoundVolume.Size = new System.Drawing.Size(213, 20);
this.vsSoundVolume.TabIndex = 100;
this.vsSoundVolume.TabStop = false;
this.vsSoundVolume.VolumeChanged += new System.EventHandler(this.vsSoundVolume_VolumeChanged);
this.vsSoundVolume.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.vsSoundVolume_MouseWheel);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(0, 0);
this.label3.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(79, 13);
this.label3.TabIndex = 7;
this.label3.Text = "Custom volume";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(0, 44);
this.label2.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(138, 13);
this.label2.TabIndex = 6;
this.label2.Text = "Restrict to a certain window";
//
// tbName
//
this.tbName.Location = new System.Drawing.Point(12, 31);
this.tbName.Name = "tbName";
this.tbName.Size = new System.Drawing.Size(213, 20);
this.tbName.TabIndex = 0;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 15);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(69, 13);
this.label1.TabIndex = 10;
this.label1.Text = "Sound Name";
//
// tbKeys
//
this.tbKeys.BackColor = System.Drawing.SystemColors.Control;
this.tbKeys.Location = new System.Drawing.Point(15, 117);
this.tbKeys.Name = "tbKeys";
this.tbKeys.Size = new System.Drawing.Size(210, 20);
this.tbKeys.TabIndex = 12;
this.tbKeys.Enter += new System.EventHandler(this.tbKeys_Enter);
this.tbKeys.Leave += new System.EventHandler(this.tbKeys_Leave);
//
// AddEditHotkeyForm
//
this.AcceptButton = this.btnOK;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(282, 272);
this.Controls.Add(this.label1);
this.Controls.Add(this.tbName);
this.Controls.Add(this.pnAddEditSound);
this.Controls.Add(this.clearHotkey);
this.Controls.Add(this.btnBrowseSoundLocation);
this.Controls.Add(this.labelLocation);
this.Controls.Add(this.labelKeys);
this.Controls.Add(this.tbLocation);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOK);
this.Controls.Add(this.tbKeys);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AddEditHotkeyForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Add/edit sound";
this.Load += new System.EventHandler(this.AddEditSoundKeys_Load);
this.pnAddEditSound.ResumeLayout(false);
this.pnAddEditSound.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nSoundVolume)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button btnOK;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.TextBox tbLocation;
private System.Windows.Forms.Label labelKeys;
private System.Windows.Forms.Label labelLocation;
private System.Windows.Forms.Button btnBrowseSoundLocation;
private System.Windows.Forms.Timer keysTimer;
private System.Windows.Forms.Button btnReloadWindows;
private System.Windows.Forms.ComboBox cbWindows;
private System.Windows.Forms.Button clearHotkey;
private System.Windows.Forms.Panel pnAddEditSound;
private NAudio.Gui.VolumeSlider vsSoundVolume;
private System.Windows.Forms.NumericUpDown nSoundVolume;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox tbName;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox tbKeys;
}
}

308
src/AddEditHotkeyForm.cs Executable file
View File

@ -0,0 +1,308 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace JNSoundboard
{
public partial class AddEditHotkeyForm : Form
{
MainForm mainForm;
SettingsForm settingsForm;
internal static string lastWindow = "";
internal static float lastSoundVolume = 1;
internal string[] editStrings = null;
internal float editVolume;
internal int editIndex = -1;
public AddEditHotkeyForm()
{
InitializeComponent();
}
private void AddEditSoundKeys_Load(object sender, EventArgs e)
{
if (SettingsForm.addingEditingLoadXMLFile)
{
//resize and hide components unrelated to settings form
this.Size = new Size(282, 176);
pnAddEditSound.Visible = false;
settingsForm = Application.OpenForms[1] as SettingsForm;
this.Text = "Add/edit keys and XML location";
if (editIndex != -1)
{
tbName.Text = editStrings[0];
tbKeys.Text = editStrings[1];
lastWindow = editStrings[2];
tbLocation.Text = editStrings[3];
}
}
else
{
mainForm = Application.OpenForms[0] as MainForm;
labelLocation.Text += "(s) (use ; to separate multiple locations)";
labelKeys.Text += " (optional)";
if (editIndex != -1)
{
tbLocation.Text = editStrings[3];
tbKeys.Text = editStrings[1];
tbName.Text = editStrings[0];
} else if (editIndex == -2)
{
tbLocation.Text = editStrings[3];
tbName.Text = editStrings[0];
}
vsSoundVolume.Volume = (editIndex != -1 && editIndex != -2) ? editVolume : lastSoundVolume;
Helper.getWindows(cbWindows);
string windowToSelect = (editIndex != -1 && editIndex != -2) ? editStrings[2] : lastWindow;
Helper.selectWindow(cbWindows, windowToSelect);
}
}
private void btnOK_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(tbLocation.Text))
{
MessageBox.Show("Location is empty");
return;
}
if (SettingsForm.addingEditingLoadXMLFile && string.IsNullOrWhiteSpace(tbKeys.Text))
{
MessageBox.Show("No keys entered");
return;
}
string[] soundLocations = null;
string fileNames;
string errorMessage;
if (!SettingsForm.addingEditingLoadXMLFile)
{
if (Helper.stringToFileLocationsArray(tbLocation.Text, out soundLocations, out errorMessage))
{
if (soundLocations.Any(x => string.IsNullOrWhiteSpace(x) || !File.Exists(x)))
{
MessageBox.Show("One or more files do not exist");
this.Close();
return;
}
}
if (soundLocations == null)
{
MessageBox.Show(errorMessage);
return;
}
}
fileNames = tbLocation.Text;//Helper.fileLocationsArrayToString(new string[] { tbLocation.Text }); //fix this later
//MessageBox.Show(fileNames);
if (String.IsNullOrWhiteSpace(tbName.Text))
if (fileNames.IndexOf(';') > -1)
{
string firstFile = fileNames.Substring(0, fileNames.IndexOf(';'));
//MessageBox.Show(firstFile);
tbName.Text = firstFile.Substring(firstFile.LastIndexOf('\\') + 1, firstFile.Length - (firstFile.LastIndexOf('\\') + 1)) + $"(+{fileNames.Count(c => (c == ';'))})";
}
else
tbName.Text = fileNames.Substring(fileNames.LastIndexOf('\\') + 1, fileNames.Length - (fileNames.LastIndexOf('\\' ) + 1));
//MessageBox.Show(tbName.Text);
if (!Helper.stringToKeysArray(tbKeys.Text, out Keyboard.Keys[] keysArray, out _)) keysArray = new Keyboard.Keys[] { };
if (SettingsForm.addingEditingLoadXMLFile)
{
fileNames = Helper.fileLocationsArrayToString(new string[] { tbLocation.Text });
if (editIndex != -1 && editIndex != -2)
{
settingsForm.lvKeysLocations.Items[editIndex].Text = tbKeys.Text;
settingsForm.lvKeysLocations.Items[editIndex].SubItems[1].Text = tbLocation.Text;
settingsForm.lvKeysLocations.Items[editIndex].ToolTipText = fileNames;
settingsForm.loadXMLFilesList[editIndex].Keys = keysArray;
settingsForm.loadXMLFilesList[editIndex].XMLLocation = tbLocation.Text;
}
else
{
var item = new ListViewItem(tbKeys.Text);
item.SubItems.Add(tbLocation.Text);
item.ToolTipText = fileNames;
settingsForm.lvKeysLocations.Items.Add(item);
settingsForm.loadXMLFilesList.Add(new XMLSettings.LoadXMLFile(keysArray, tbLocation.Text));
}
}
else
{
fileNames = Helper.getFileNamesTooltip(soundLocations);
string volumeString = vsSoundVolume.Volume == 1 ? "" : Helper.linearVolumeToString(vsSoundVolume.Volume);
string windowText = (cbWindows.SelectedIndex > 0) ? cbWindows.Text : "";
if (editIndex != -1 && editIndex != -2)
{
mainForm.lvKeySounds.Items[editIndex].SubItems[0].Text = tbName.Text;
mainForm.lvKeySounds.Items[editIndex].SubItems[1].Text = tbKeys.Text;
mainForm.lvKeySounds.Items[editIndex].SubItems[2].Text = volumeString;
mainForm.lvKeySounds.Items[editIndex].SubItems[3].Text = windowText;
mainForm.lvKeySounds.Items[editIndex].SubItems[4].Text = tbLocation.Text;
mainForm.lvKeySounds.Items[editIndex].ToolTipText = fileNames;
mainForm.soundHotkeys[editIndex] = new XMLSettings.SoundHotkey(tbName.Text, keysArray, vsSoundVolume.Volume, windowText, soundLocations);
}
else
{
//var newItem = new ListViewItem(tbKeys.Text);
var newItem = new ListViewItem(tbName.Text);
newItem.SubItems.Add(tbKeys.Text);
newItem.SubItems.Add(volumeString);
newItem.SubItems.Add(windowText);
newItem.SubItems.Add(tbLocation.Text);
newItem.ToolTipText = fileNames;
mainForm.lvKeySounds.Items.Add(newItem);
mainForm.soundHotkeys.Add(new XMLSettings.SoundHotkey(tbName.Text, keysArray, vsSoundVolume.Volume, windowText, soundLocations));
}
mainForm.sortHotkeys();
//remember last used options
lastSoundVolume = vsSoundVolume.Volume;
lastWindow = cbWindows.Text;
}
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnBrowseSoundLocation_Click(object sender, EventArgs e)
{
var diag = new OpenFileDialog();
diag.Multiselect = !SettingsForm.addingEditingLoadXMLFile;
diag.Filter = (SettingsForm.addingEditingLoadXMLFile ? "XML file containing keys and sounds|*.xml" : "Supported audio formats|*.mp3;*.m4a;*.wav;*.wma;*.ac3;*.aiff;*.mp2|All files|*.*");
var result = diag.ShowDialog();
if (result == DialogResult.OK)
{
string text = "";
for (int i = 0; i < diag.FileNames.Length; i++)
{
string fileName = diag.FileNames[i];
if (fileName != "") text += (i == 0 ? "" : ";") + fileName;
}
tbLocation.Text = text;
}
}
private void tbKeys_Enter(object sender, EventArgs e)
{
keysTimer.Enabled = true;
}
private void tbKeys_Leave(object sender, EventArgs e)
{
keysTimer.Enabled = false;
keysTimer.Interval = 100;
}
private int lastAmountPressed = 0;
private void keysTimer_Tick(object sender, EventArgs e)
{
keysTimer.Interval = 10; //lowering the interval to avoid missing key presses (e.g. when an input is corrected)
var keysData = Keyboard.getKeys(lastAmountPressed, tbKeys.Text);
lastAmountPressed = keysData.Item1;
tbKeys.Text = keysData.Item2;
}
private void btnReloadWindows_Click(object sender, EventArgs e)
{
Helper.getWindows(cbWindows);
}
private void clearHotkey_Click( object sender, EventArgs e )
{
tbKeys.Text = "";
}
private bool volumeChangedBySlider = false;
private bool volumeChangedByField = false;
public void vsSoundVolume_VolumeChanged(object sender, EventArgs e)
{
//prevent infinite or skipped changes
if (volumeChangedByField)
{
volumeChangedByField = false;
return;
}
volumeChangedBySlider = true;
nSoundVolume.Value = Helper.linearVolumeToInteger(vsSoundVolume.Volume);
}
public void vsSoundVolume_MouseWheel(object sender, MouseEventArgs e)
{
vsSoundVolume.Volume = Helper.getNewSoundVolume(vsSoundVolume.Volume, e.Delta);
}
public void nSoundVolume_ValueChanged(object sender, EventArgs e)
{
//prevent infinite or skipped changes
if (volumeChangedBySlider)
{
volumeChangedBySlider = false;
return;
}
volumeChangedByField = true;
vsSoundVolume.Volume = (float)(nSoundVolume.Value / 100);
}
}
}

6309
src/AddEditHotkeyForm.resx Executable file

File diff suppressed because it is too large Load Diff

6
src/App.config Executable file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
</configuration>

151
src/AudioPlaybackEngine.cs Executable file
View File

@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using NAudio.Wave;
using NAudio.Wave.SampleProviders;
using System.Linq;
using System.Windows.Forms;
namespace JNSoundboard
{
class AudioPlaybackEngine : IDisposable
{
public MainForm mainForm;
private IWavePlayer outputDevice;
private readonly MixingSampleProvider mixer;
private IDictionary<string, CachedSound> cachedSounds = new Dictionary<string, CachedSound>();
public MainForm.VolumeType VType;
public AudioPlaybackEngine(MainForm.VolumeType vType, int sampleRate = 44100, int channelCount = 2)
{
mixer = new MixingSampleProvider(WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channelCount));
mixer.ReadFully = true;
mixer.MixerInputEnded += OnMixerInputEnded;
VType = vType;
}
public event EventHandler AllInputEnded;
private void OnMixerInputEnded(object sender, SampleProviderEventArgs e) //add a specific event for the PlaySound override using RawSourceWaveStream when it actually works
{
if (mainForm.LoopSound)
{
float soundVolume;
if (VType == MainForm.VolumeType.Private)
soundVolume = mainForm.vsPrivateVolume.Volume;
else
soundVolume = mainForm.vsPublicVolume.Volume;
PlaySound(mainForm.lastPlayedSound, soundVolume);
}
// check if there are any inputs left
// OnMixerInputEnded gets invoked before the corresponding source is removed from the List so there should be exactly one source left
if (mixer.MixerInputs.Count() == 1)
{
AllInputEnded?.Invoke(this, EventArgs.Empty);
}
}
public void Init(int deviceNumber)
{
if (outputDevice != null) outputDevice.Dispose();
var output = new WaveOutEvent();
output.DeviceNumber = deviceNumber;
output.Init(mixer);
output.Play();
outputDevice = output;
}
public void GetMainFormReference()
{
if (mainForm == null)
mainForm = Application.OpenForms[0] as MainForm;
}
public void PlaySound(RawSourceWaveStream reader, float volume = 1)
{
GetMainFormReference();
if (volume == 0)
return;
if (mainForm.AudioBoost)
volume *= 5;
SampleChannel sc = new SampleChannel(reader);
sc.Volume = volume;
System.Windows.Forms.MessageBox.Show("WORKING " + reader.Length);
mixer.AddMixerInput(sc); //plays apparently, but hearing nothing
}
public void PlaySound(string fileName, float volume = 1)
{
GetMainFormReference();
if (volume == 0)
return;
if (mainForm.AudioBoost)
volume *= 5;
var input = new AudioFileReader(fileName);
//mainForm.lastPlayedSound =
CachedSound cachedSound = null;
if (!cachedSounds.TryGetValue(fileName, out cachedSound))
{
cachedSound = new CachedSound(fileName);
cachedSounds.Add(fileName, cachedSound);
}
var resultingSampleProvider = new VolumeSampleProvider(new CachedSoundSampleProvider(cachedSound));
resultingSampleProvider.Volume = volume;
AddMixerInput(resultingSampleProvider);
}
public void StopAllSounds()
{
mixer.RemoveAllMixerInputs();
}
private ISampleProvider ConvertToRightChannelCount(ISampleProvider input)
{
if (input.WaveFormat.Channels == mixer.WaveFormat.Channels)
{
return input;
}
if (input.WaveFormat.Channels == 1 && mixer.WaveFormat.Channels == 2)
{
return new MonoToStereoSampleProvider(input);
}
throw new NotImplementedException("Not yet implemented this channel count conversion");
}
private void AddMixerInput(ISampleProvider input)
{
var resampled = new WdlResamplingSampleProvider(input, mixer.WaveFormat.SampleRate);
mixer.AddMixerInput(ConvertToRightChannelCount(resampled));
}
public void Dispose()
{
if (outputDevice != null)
{
outputDevice.Dispose();
outputDevice = null;
}
}
}
}

34
src/CachedSound.cs Executable file
View File

@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Linq;
using NAudio.Wave;
// https://mark-dot-net.blogspot.de/2014/02/fire-and-forget-audio-playback-with.html
// Mark Heath 2014
namespace JNSoundboard
{
class CachedSound
{
public float[] AudioData { get; private set; }
public WaveFormat WaveFormat { get; private set; }
public CachedSound(string audioFileName)
{
using (var audioFileReader = new AudioFileReader(audioFileName))
{
// TODO: could add resampling in here if required
WaveFormat = audioFileReader.WaveFormat;
var wholeFile = new List<float>((int)(audioFileReader.Length / 4));
var readBuffer = new float[audioFileReader.WaveFormat.SampleRate * audioFileReader.WaveFormat.Channels];
int samplesRead;
while ((samplesRead = audioFileReader.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
wholeFile.AddRange(readBuffer.Take(samplesRead));
}
AudioData = wholeFile.ToArray();
}
}
}
}

View File

@ -0,0 +1,30 @@
using System;
using NAudio.Wave;
namespace JNSoundboard
{
class CachedSoundSampleProvider : ISampleProvider
{
private readonly CachedSound cachedSound;
private long position;
public CachedSoundSampleProvider(CachedSound cachedSound)
{
this.cachedSound = cachedSound;
}
public int Read(float[] buffer, int offset, int count)
{
var availableSamples = cachedSound.AudioData.Length - position;
var samplesToCopy = Math.Min(availableSamples, count);
Array.Copy(cachedSound.AudioData, position, buffer, offset, samplesToCopy);
position += samplesToCopy;
return (int)samplesToCopy;
}
public WaveFormat WaveFormat { get { return cachedSound.WaveFormat; } }
}
}

355
src/Helper.cs Executable file
View File

@ -0,0 +1,355 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32;
namespace JNSoundboard
{
class Helper
{
[DllImport("user32.dll")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
internal static extern IntPtr GetForegroundWindow();
internal static bool isForegroundWindow(string windowTitle)
{
IntPtr foregroundWindow = GetForegroundWindow();
return isForegroundWindow(foregroundWindow, windowTitle);
}
internal static bool isForegroundWindow(IntPtr foregroundWindow, string windowTitle)
{
IntPtr window = FindWindow(null, windowTitle);
if (window == IntPtr.Zero) return false; //not found
return foregroundWindow == window;
}
internal static string userGetXmlLocation()
{
SaveFileDialog diag = new SaveFileDialog();
diag.Filter = "XML file containing keys and sounds|*.xml";
var result = diag.ShowDialog();
if (result == DialogResult.OK)
{
return diag.FileName;
}
else return null;
}
internal static bool stringToKey(string keyString, out Keyboard.Keys key)
{
if (keyString.Contains("VK_"))
{
//key has no name
keyString = keyString.Substring(keyString.LastIndexOf('_') + 1);
try
{
key = (Keyboard.Keys)int.Parse(keyString, System.Globalization.NumberStyles.HexNumber);
return true;
}
catch
{
key = 0;
return false;
}
}
else if (Enum.TryParse(keyString, out key))
{
return true;
}
else
{
return false;
}
}
internal static string keysArrayToString(Keyboard.Keys[] keysArray)
{
if (keysArray == null) return "";
string keysString = "";
int i = 0;
foreach (Keyboard.Keys key in keysArray)
{
keysString += key.ToString() + (i++ == keysArray.Length - 1 ? "" : "+");
}
return keysString;
}
internal static string[] keysArrayToStringArray(Keyboard.Keys[] keysArray)
{
var keysList = new List<string>();
foreach (Keyboard.Keys key in keysArray)
{
keysList.Add(key.ToString());
}
return keysList.ToArray();
}
internal static bool stringToKeysArray(string keysString, out Keyboard.Keys[] keysArray, out string errorMessage)
{
errorMessage = "";
if (keysString.Contains("+"))
{
string[] stringArray = keysString.Split('+');
var keysList = new List<Keyboard.Keys>();
foreach (string keyString in stringArray)
{
if (stringToKey(keyString, out Keyboard.Keys key))
{
keysList.Add(key);
}
else
{
errorMessage = "Key string \"" + keyString + "\" doesn't exist";
keysArray = null;
return false;
}
}
keysArray = keysList.ToArray();
return true;
}
else
{
if (stringToKey(keysString, out Keyboard.Keys key))
{
keysArray = new Keyboard.Keys[] { key };
return true;
}
else
{
errorMessage = "Key string \"" + keysString + "\" doesn't exist";
keysArray = null;
return false;
}
}
}
internal static bool stringArrayToKeysArray(string[] stringArray, out Keyboard.Keys[] keysArray, out string errorMessage)
{
errorMessage = "";
if (stringArray == null) {
keysArray = new Keyboard.Keys[] { 0 };
return true;
}
var keysList = new List<Keyboard.Keys>();
foreach (string keyString in stringArray)
{
if (stringToKey(keyString, out Keyboard.Keys key))
{
keysList.Add(key);
}
else
{
errorMessage = "Key string \"" + keyString + "\" doesn't exist";
keysArray = null;
return false;
}
}
keysArray = keysList.ToArray();
return true;
}
internal static bool stringToFileLocationsArray(string fileLocationsString, out string[] fileLocations, out string errorMessage)
{
errorMessage = "";
if (fileLocationsString.Contains(";"))
{
string[] sLocations = fileLocationsString.Split(';');
var lLocations = new List<string>();
for (int i = 0; i < sLocations.Length; i++)
{
if (File.Exists(sLocations[i]))
{
lLocations.Add(sLocations[i]);
}
else
{
errorMessage = "File \"" + sLocations[i] + "\" does not exist";
fileLocations = null;
return false;
}
}
fileLocations = lLocations.ToArray();
return true;
}
else
{
if (File.Exists(fileLocationsString))
{
fileLocations = new string[] { fileLocationsString };
return true;
}
else
{
errorMessage = "File \"" + fileLocationsString + "\" does not exist";
fileLocations = null;
return false;
}
}
}
internal static string fileLocationsArrayToString(string[] fileLocations)
{
string temp = "";
int sLength = fileLocations.Length;
for (int i = 0; i < sLength; i++)
{
temp += fileLocations[i].ToString() + (i == sLength - 1 ? "" : ";");
}
return temp;
}
internal static string getFileNamesTooltip(string[] fileLocations)
{
string soundNames = "";
for (int i = 0; i < fileLocations.Length - 1; i++)
{
soundNames += Path.GetFileNameWithoutExtension(fileLocations[i]) + "\n";
}
return soundNames += Path.GetFileNameWithoutExtension(fileLocations[fileLocations.Length - 1]);
}
internal static string cleanFileName(string fileName)
{
return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), ""));
}
internal static void getWindows(ComboBox cbWindows)
{
string oldWindow = cbWindows.Text;
cbWindows.Items.Clear();
cbWindows.Items.Add("[Any window]");
cbWindows.SelectedIndex = 0;
Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist)
{
if (!string.IsNullOrEmpty(process.MainWindowTitle))
{
cbWindows.Items.Add(process.MainWindowTitle);
//keep selection if program still in list
if (oldWindow == process.MainWindowTitle)
{
cbWindows.SelectedItem = process.MainWindowTitle;
}
}
}
}
internal static void selectWindow(ComboBox cbWindows, string windowToSelect)
{
if (windowToSelect != "")
{
int index = cbWindows.Items.IndexOf(windowToSelect);
if (index != -1)
{
//select the item
cbWindows.SelectedIndex = index;
}
else
{
//add and select the item
cbWindows.Items.Add(windowToSelect);
cbWindows.SelectedIndex = cbWindows.Items.Count - 1;
}
}
}
internal static void setStartup(bool StartWithWindows)
{
RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
if (StartWithWindows && key.GetValue("JN Soundboard") == null)
{
key.SetValue("JN Soundboard", Application.ExecutablePath.ToString());
}
else if (key.GetValue("JN Soundboard") != null)
{
key.DeleteValue("JN Soundboard");
}
}
internal static int linearVolumeToInteger(float linearVolume)
{
return linearVolume > 0.1 ? (int)Math.Round(linearVolume * 100) : (int)Math.Ceiling(linearVolume * 100);
}
internal static string linearVolumeToString(float linearVolume)
{
double decibels = NAudio.Utils.Decibels.LinearToDecibels(linearVolume);
int linearInteger = linearVolumeToInteger(linearVolume);
return string.Format("{0:N2} dB ({1})", decibels, linearInteger);
}
internal static float getNewSoundVolume(float oldVolume, int delta)
{
float[] increments = { 0, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1 };
if (delta > 0 && oldVolume < 1)
{
for (int i = 1; i < increments.Length; i++)
{
if (oldVolume < increments[i]) return increments[i];
}
}
else if (delta < 0 && oldVolume > 0)
{
for (int i = increments.Length - 2; i >= 0; i--)
{
if (oldVolume > increments[i]) return increments[i];
}
}
return oldVolume;
}
}
}

170
src/JNSoundboard.csproj Executable file
View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{791CE5FC-FB35-4471-A28E-B5A5E99E9355}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>JNSoundboard</RootNamespace>
<AssemblyName>JNSoundboard</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
<Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup />
<PropertyGroup>
<ApplicationIcon>jn-icon.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<Optimize>true</Optimize>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="NAudio, Version=1.10.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\NAudio.1.10.0\lib\net35\NAudio.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Speech" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Serialization" />
</ItemGroup>
<ItemGroup>
<Compile Include="AddEditHotkeyForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AddEditHotkeyForm.Designer.cs">
<DependentUpon>AddEditHotkeyForm.cs</DependentUpon>
</Compile>
<Compile Include="AudioPlaybackEngine.cs" />
<Compile Include="CachedSound.cs" />
<Compile Include="CachedSoundSampleProvider.cs" />
<Compile Include="Helper.cs" />
<Compile Include="Keyboard.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="XMLSettings.cs" />
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SettingsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="SettingsForm.Designer.cs">
<DependentUpon>SettingsForm.cs</DependentUpon>
</Compile>
<Compile Include="TextToSpeechForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="TextToSpeechForm.Designer.cs">
<DependentUpon>TextToSpeechForm.cs</DependentUpon>
</Compile>
<EmbeddedResource Include="AddEditHotkeyForm.resx">
<DependentUpon>AddEditHotkeyForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="SettingsForm.resx">
<DependentUpon>SettingsForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="TextToSpeechForm.resx">
<DependentUpon>TextToSpeechForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<None Include="LICENSE" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<None Include="README.md" />
<None Include="reload.png" />
</ItemGroup>
<ItemGroup>
<Content Include="jn-icon.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

34
src/JNSoundboard.sln Executable file
View File

@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JNSoundboard", "JNSoundboard.csproj", "{791CE5FC-FB35-4471-A28E-B5A5E99E9355}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Debug|Any CPU.Build.0 = Debug|Any CPU
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Debug|x64.ActiveCfg = Debug|x64
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Debug|x64.Build.0 = Debug|x64
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Debug|x86.ActiveCfg = Debug|x86
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Debug|x86.Build.0 = Debug|x86
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Release|Any CPU.ActiveCfg = Release|Any CPU
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Release|Any CPU.Build.0 = Release|Any CPU
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Release|x64.ActiveCfg = Release|x64
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Release|x64.Build.0 = Release|x64
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Release|x86.ActiveCfg = Release|x86
{791CE5FC-FB35-4471-A28E-B5A5E99E9355}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

422
src/Keyboard.cs Executable file
View File

@ -0,0 +1,422 @@
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Windows.Forms;
namespace JNSoundboard
{
public class Keyboard
{
const int INPUT_MOUSE = 0;
const int INPUT_KEYBOARD = 1;
const int INPUT_HARDWARE = 2;
const uint KEYEVENTF_KEYDOWN = 0x0000;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_UNICODE = 0x0004;
const uint KEYEVENTF_SCANCODE = 0x0008;
struct INPUT
{
public int type;
public InputUnion u;
}
[StructLayout(LayoutKind.Explicit)]
struct InputUnion
{
[FieldOffset(0)]
public MOUSEINPUT mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public uint uMsg;
public ushort wParamL;
public ushort wParamH;
}
[DllImport("user32.dll", SetLastError = true)]
private static extern short GetKeyState(ushort virtualKeyCode);
internal static bool IsKeyDown(Keys keyCode)
{
short keyState = GetKeyState((ushort)keyCode);
return keyState < 0;
}
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
[DllImport("user32.dll")]
static extern IntPtr GetMessageExtraInfo();
[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);
const uint MAPVK_VK_TO_VSC = 0x00;
public static bool sendKey(Keys key, bool keyDown)
{
INPUT[] inputs =
{
new INPUT
{
type = INPUT_KEYBOARD,
u = new InputUnion
{
ki = new KEYBDINPUT()
{
wVk = 0,
wScan = (ushort)MapVirtualKey((uint)key, MAPVK_VK_TO_VSC),
dwFlags = ((keyDown ? KEYEVENTF_KEYDOWN : KEYEVENTF_KEYUP) | KEYEVENTF_SCANCODE),
dwExtraInfo = GetMessageExtraInfo(),
time = (keyDown ? unchecked ((uint)-1) : 0)
}
}
}
};
return SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT))) > 0;
}
public static Tuple<int, string> getKeys(int lastAmountPressed, string currentKeys)
{
int amountPressed = 0;
string newKeys = (currentKeys == "") ? "" : currentKeys;
if (!IsKeyDown(Keys.Escape))
{
var pressedKeys = new List<Keys>();
foreach (Keys key in Enum.GetValues(typeof(Keys)))
{
if (IsKeyDown(key))
{
amountPressed++;
pressedKeys.Add(key);
}
}
if (amountPressed > lastAmountPressed)
{
newKeys = Helper.keysArrayToString(pressedKeys.ToArray());
}
lastAmountPressed = amountPressed;
}
else
{
newKeys = "";
}
return Tuple.Create(lastAmountPressed, newKeys);
}
public enum Keys
{
Modifiers = -65536,
None = 0,
LButton = 1,
RButton = 2,
Cancel = 3,
MButton = 4,
XButton1 = 5,
XButton2 = 6,
VK_07 = 7, //MenuMaskKey, cannot be bound
Back = 8,
Tab = 9,
LineFeed = 10,
VK_0B = 11, //Reserved
Clear = 12,
Return = 13,
Enter = 13,
VK_0E = 14, //Undefined
VK_0F = 15, //Undefined
ShiftKey = 16,
ControlKey = 17,
Menu = 18,
Pause = 19,
Capital = 20,
CapsLock = 20,
KanaMode = 21,
HanguelMode = 21,
HangulMode = 21,
VK_16 = 22, //Undefined
JunjaMode = 23,
FinalMode = 24,
HanjaMode = 25,
KanjiMode = 25,
VK_1A = 26, //Undefined
Escape = 27,
IMEConvert = 28,
IMENonconvert = 29,
IMEAccept = 30,
IMEAceept = 30,
IMEModeChange = 31,
Space = 32,
Prior = 33,
PageUp = 33,
Next = 34,
PageDown = 34,
End = 35,
Home = 36,
Left = 37,
Up = 38,
Right = 39,
Down = 40,
Select = 41,
Print = 42,
Execute = 43,
Snapshot = 44,
PrintScreen = 44,
Insert = 45,
Delete = 46,
Help = 47,
D0 = 48,
D1 = 49,
D2 = 50,
D3 = 51,
D4 = 52,
D5 = 53,
D6 = 54,
D7 = 55,
D8 = 56,
D9 = 57,
VK_3A = 58, //Undefined
VK_3B = 59, //Undefined
VK_3C = 60, //Undefined
VK_3D = 61, //Undefined
VK_3E = 62, //Undefined
VK_3F = 63, //Undefined
VK_40 = 64, //Undefined
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LWin = 91,
RWin = 92,
Apps = 93,
VK_5E = 94, //Reserved
Sleep = 95,
NumPad0 = 96,
NumPad1 = 97,
NumPad2 = 98,
NumPad3 = 99,
NumPad4 = 100,
NumPad5 = 101,
NumPad6 = 102,
NumPad7 = 103,
NumPad8 = 104,
NumPad9 = 105,
Multiply = 106,
Add = 107,
Separator = 108,
Subtract = 109,
Decimal = 110,
Divide = 111,
F1 = 112,
F2 = 113,
F3 = 114,
F4 = 115,
F5 = 116,
F6 = 117,
F7 = 118,
F8 = 119,
F9 = 120,
F10 = 121,
F11 = 122,
F12 = 123,
F13 = 124,
F14 = 125,
F15 = 126,
F16 = 127,
F17 = 128,
F18 = 129,
F19 = 130,
F20 = 131,
F21 = 132,
F22 = 133,
F23 = 134,
F24 = 135,
VK_88 = 136, //Unassigned
VK_89 = 137, //Unassigned
VK_8A = 138, //Unassigned
VK_8B = 139, //Unassigned
VK_8C = 140, //Unassigned
VK_8D = 141, //Unassigned
VK_8E = 142, //Unassigned
VK_8F = 143, //NumLock
NumLock = 144,
Scroll = 145,
VK_92 = 146, //OEM Specific
VK_93 = 147, //OEM Specific
VK_94 = 148, //OEM Specific
VK_95 = 149, //OEM Specific
VK_96 = 150, //OEM Specific
VK_97 = 151, //Unassigned
VK_98 = 152, //Unassigned
VK_99 = 153, //Unassigned
VK_9A = 154, //Unassigned
VK_9B = 155, //Menu
VK_9C = 156, //Unassigned
VK_9D = 157, //Unassigned
VK_9E = 158, //Unassigned
VK_9F = 159, //Unassigned
LShiftKey = 160,
RShiftKey = 161,
LControlKey = 162,
RControlKey = 163,
LMenu = 164,
RMenu = 165,
BrowserBack = 166,
BrowserForward = 167,
BrowserRefresh = 168,
BrowserStop = 169,
BrowserSearch = 170,
BrowserFavorites = 171,
BrowserHome = 172,
VolumeMute = 173,
VolumeDown = 174,
VolumeUp = 175,
MediaNextTrack = 176,
MediaPreviousTrack = 177,
MediaStop = 178,
MediaPlayPause = 179,
LaunchMail = 180,
SelectMedia = 181,
LaunchApplication1 = 182,
LaunchApplication2 = 183,
VK_B8 = 184, //Reserved
VK_B9 = 185, //Reserved
OemSemicolon = 186,
Oem1 = 186,
Oemplus = 187,
Oemcomma = 188,
OemMinus = 189,
OemPeriod = 190,
OemQuestion = 191,
Oem2 = 191,
Oemtilde = 192,
Oem3 = 192,
VK_C1 = 193, //Cut
VK_C2 = 194, //Copy
VK_C3 = 195, //Paste
VK_C4 = 196, //Select All
VK_C5 = 197, //Find
VK_C6 = 198, //New
VK_C7 = 199, //Print
VK_C8 = 200, //Save
VK_C9 = 201, //Reserved
VK_CA = 202, //Reserved
VK_CB = 203, //Reserved
VK_CC = 204, //Reserved
VK_CD = 205, //Reserved
VK_CE = 206, //Reserved
VK_CF = 207, //Reserved
VK_D0 = 208, //Close Window
VK_D1 = 209, //Lock PC
VK_D2 = 210, //Open Explorer
VK_D3 = 211, //Run
VK_D4 = 212, //Show Desktop
VK_D5 = 213, //LButton
VK_D6 = 214, //RButton
VK_D7 = 215, //MButton
VK_D8 = 216, //Scroll Up
VK_D9 = 217, //Scroll Down
VK_DA = 218, //Unassigned
OemOpenBrackets = 219,
Oem4 = 219,
OemPipe = 220,
Oem5 = 220,
OemCloseBrackets = 221,
Oem6 = 221,
OemQuotes = 222,
Oem7 = 222,
Oem8 = 223,
VK_E0 = 224, //Reserved
VK_E1 = 225, //OEM Specific
OemBackslash = 226,
Oem102 = 226,
VK_E3 = 227, //OEM Specific
VK_E4 = 228, //00
ProcessKey = 229,
VK_E6 = 230, //OEM Specific
Packet = 231,
VK_E8 = 232, //Unassigned
VK_E9 = 233, //OEM Specific
VK_EA = 234, //OEM Specific
VK_EB = 235, //OEM Specific
VK_EC = 236, //OEM Specific
VK_ED = 237, //OEM Specific
VK_EE = 238, //OEM Specific
VK_EF = 239, //OEM Specific
VK_F0 = 240, //OEM Specific
VK_F1 = 241, //OEM Specific
VK_F2 = 242, //OEM Specific
VK_F3 = 243, //OEM Specific
VK_F4 = 244, //OEM Specific
VK_F5 = 245, //OEM Specific
Attn = 246,
Crsel = 247,
Exsel = 248,
EraseEof = 249,
Play = 250,
Zoom = 251,
NoName = 252,
Pa1 = 253,
OemClear = 254,
KeyCode = 65535,
Shift = 65536,
Control = 131072,
Alt = 262144
}
}
}

777
src/MainForm.Designer.cs generated Executable file
View File

@ -0,0 +1,777 @@
namespace JNSoundboard
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.lblPlayback1 = new System.Windows.Forms.Label();
this.cbPlaybackDevices1 = new System.Windows.Forms.ComboBox();
this.cbEnableHotkeys = new System.Windows.Forms.CheckBox();
this.mainTimer = new System.Windows.Forms.Timer(this.components);
this.btnSave = new System.Windows.Forms.Button();
this.btnRemove = new System.Windows.Forms.Button();
this.btnEdit = new System.Windows.Forms.Button();
this.btnAdd = new System.Windows.Forms.Button();
this.lvKeySounds = new System.Windows.Forms.ListView();
this.chName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.chKeys = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.chVolume = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.chWindow = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.chLocation = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.btnLoad = new System.Windows.Forms.Button();
this.btnReloadDevices = new System.Windows.Forms.Button();
this.btnClear = new System.Windows.Forms.Button();
this.btnSaveAs = new System.Windows.Forms.Button();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.texttospeechToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.checkForUpdateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.lblLoopback = new System.Windows.Forms.Label();
this.cbLoopbackDevices = new System.Windows.Forms.ComboBox();
this.btnPlaySelectedSound = new System.Windows.Forms.Button();
this.btnStopAllSounds = new System.Windows.Forms.Button();
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.gbPushToTalk = new System.Windows.Forms.GroupBox();
this.clearHotkey = new System.Windows.Forms.Button();
this.btnReloadWindows = new System.Windows.Forms.Button();
this.cbEnablePushToTalk = new System.Windows.Forms.CheckBox();
this.label3 = new System.Windows.Forms.Label();
this.tbPushToTalkKey = new System.Windows.Forms.TextBox();
this.cbWindows = new System.Windows.Forms.ComboBox();
this.label4 = new System.Windows.Forms.Label();
this.gbAudioDevices = new System.Windows.Forms.GroupBox();
this.cbPlaybackDevices2 = new System.Windows.Forms.ComboBox();
this.label6 = new System.Windows.Forms.Label();
this.lblPlayback2 = new System.Windows.Forms.Label();
this.pushToTalkKeyTimer = new System.Windows.Forms.Timer(this.components);
this.cbEnableLoopback = new System.Windows.Forms.CheckBox();
this.vsPublicVolume = new NAudio.Gui.VolumeSlider();
this.nPublicVolume = new System.Windows.Forms.NumericUpDown();
this.gbSoundboard = new System.Windows.Forms.GroupBox();
this.cbAudioBoost = new System.Windows.Forms.CheckBox();
this.label2 = new System.Windows.Forms.Label();
this.nPrivateVolume = new System.Windows.Forms.NumericUpDown();
this.label1 = new System.Windows.Forms.Label();
this.vsPrivateVolume = new NAudio.Gui.VolumeSlider();
this.saveSettingsTimer = new System.Windows.Forms.Timer(this.components);
this.btnAddDirectory = new System.Windows.Forms.Button();
this.cbLoopSound = new System.Windows.Forms.CheckBox();
this.menuStrip1.SuspendLayout();
this.contextMenuStrip1.SuspendLayout();
this.gbPushToTalk.SuspendLayout();
this.gbAudioDevices.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nPublicVolume)).BeginInit();
this.gbSoundboard.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nPrivateVolume)).BeginInit();
this.SuspendLayout();
//
// lblPlayback1
//
this.lblPlayback1.AutoSize = true;
this.lblPlayback1.Location = new System.Drawing.Point(8, 21);
this.lblPlayback1.Margin = new System.Windows.Forms.Padding(5, 5, 3, 3);
this.lblPlayback1.Name = "lblPlayback1";
this.lblPlayback1.Size = new System.Drawing.Size(126, 13);
this.lblPlayback1.TabIndex = 5;
this.lblPlayback1.Text = "Speakers or Virtual Cable";
//
// cbPlaybackDevices1
//
this.cbPlaybackDevices1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbPlaybackDevices1.FormattingEnabled = true;
this.cbPlaybackDevices1.Location = new System.Drawing.Point(142, 18);
this.cbPlaybackDevices1.Margin = new System.Windows.Forms.Padding(5, 5, 3, 3);
this.cbPlaybackDevices1.Name = "cbPlaybackDevices1";
this.cbPlaybackDevices1.Size = new System.Drawing.Size(176, 21);
this.cbPlaybackDevices1.TabIndex = 11;
//
// cbEnableHotkeys
//
this.cbEnableHotkeys.AutoSize = true;
this.cbEnableHotkeys.Location = new System.Drawing.Point(8, 17);
this.cbEnableHotkeys.Margin = new System.Windows.Forms.Padding(5, 5, 3, 3);
this.cbEnableHotkeys.Name = "cbEnableHotkeys";
this.cbEnableHotkeys.Size = new System.Drawing.Size(101, 17);
this.cbEnableHotkeys.TabIndex = 16;
this.cbEnableHotkeys.Text = "Enable Hotkeys";
this.cbEnableHotkeys.UseVisualStyleBackColor = true;
this.cbEnableHotkeys.CheckedChanged += new System.EventHandler(this.cbEnableHotkeys_CheckedChanged);
//
// mainTimer
//
this.mainTimer.Interval = 50;
this.mainTimer.Tick += new System.EventHandler(this.mainTimer_Tick);
//
// btnSave
//
this.btnSave.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnSave.Location = new System.Drawing.Point(93, 321);
this.btnSave.Margin = new System.Windows.Forms.Padding(3, 3, 3, 5);
this.btnSave.Name = "btnSave";
this.btnSave.Size = new System.Drawing.Size(75, 23);
this.btnSave.TabIndex = 8;
this.btnSave.Text = "Save";
this.btnSave.UseVisualStyleBackColor = true;
this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
//
// btnRemove
//
this.btnRemove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnRemove.Location = new System.Drawing.Point(572, 147);
this.btnRemove.Name = "btnRemove";
this.btnRemove.Size = new System.Drawing.Size(75, 35);
this.btnRemove.TabIndex = 4;
this.btnRemove.Text = "Remove";
this.btnRemove.UseVisualStyleBackColor = true;
this.btnRemove.Click += new System.EventHandler(this.btnRemove_Click);
//
// btnEdit
//
this.btnEdit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnEdit.Location = new System.Drawing.Point(572, 109);
this.btnEdit.Name = "btnEdit";
this.btnEdit.Size = new System.Drawing.Size(75, 35);
this.btnEdit.TabIndex = 3;
this.btnEdit.Text = "Edit";
this.btnEdit.UseVisualStyleBackColor = true;
this.btnEdit.Click += new System.EventHandler(this.btnEdit_Click);
//
// btnAdd
//
this.btnAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnAdd.Location = new System.Drawing.Point(572, 27);
this.btnAdd.Name = "btnAdd";
this.btnAdd.Size = new System.Drawing.Size(75, 35);
this.btnAdd.TabIndex = 1;
this.btnAdd.Text = "Add";
this.btnAdd.UseVisualStyleBackColor = true;
this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click);
//
// lvKeySounds
//
this.lvKeySounds.Alignment = System.Windows.Forms.ListViewAlignment.Default;
this.lvKeySounds.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lvKeySounds.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.chName,
this.chKeys,
this.chVolume,
this.chWindow,
this.chLocation});
this.lvKeySounds.FullRowSelect = true;
this.lvKeySounds.GridLines = true;
this.lvKeySounds.HideSelection = false;
this.lvKeySounds.Location = new System.Drawing.Point(12, 27);
this.lvKeySounds.MultiSelect = false;
this.lvKeySounds.Name = "lvKeySounds";
this.lvKeySounds.ShowItemToolTips = true;
this.lvKeySounds.Size = new System.Drawing.Size(554, 288);
this.lvKeySounds.TabIndex = 0;
this.lvKeySounds.UseCompatibleStateImageBehavior = false;
this.lvKeySounds.View = System.Windows.Forms.View.Details;
this.lvKeySounds.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.lvKeySounds_MouseDoubleClick);
//
// chName
//
this.chName.Text = "Name";
this.chName.Width = 180;
//
// chKeys
//
this.chKeys.Text = "Keys";
this.chKeys.Width = 100;
//
// chVolume
//
this.chVolume.Text = "Volume";
this.chVolume.Width = 85;
//
// chWindow
//
this.chWindow.Text = "Window";
this.chWindow.Width = 100;
//
// chLocation
//
this.chLocation.Text = "Location";
this.chLocation.Width = 265;
//
// btnLoad
//
this.btnLoad.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnLoad.Location = new System.Drawing.Point(12, 321);
this.btnLoad.Margin = new System.Windows.Forms.Padding(3, 3, 3, 5);
this.btnLoad.Name = "btnLoad";
this.btnLoad.Size = new System.Drawing.Size(75, 23);
this.btnLoad.TabIndex = 7;
this.btnLoad.Text = "Load";
this.btnLoad.UseVisualStyleBackColor = true;
this.btnLoad.Click += new System.EventHandler(this.btnLoad_Click);
//
// btnReloadDevices
//
this.btnReloadDevices.Image = ((System.Drawing.Image)(resources.GetObject("btnReloadDevices.Image")));
this.btnReloadDevices.Location = new System.Drawing.Point(324, 17);
this.btnReloadDevices.Margin = new System.Windows.Forms.Padding(3, 5, 5, 5);
this.btnReloadDevices.Name = "btnReloadDevices";
this.btnReloadDevices.Size = new System.Drawing.Size(23, 23);
this.btnReloadDevices.TabIndex = 14;
this.btnReloadDevices.UseVisualStyleBackColor = true;
this.btnReloadDevices.Click += new System.EventHandler(this.btnReloadDevices_Click);
//
// btnClear
//
this.btnClear.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnClear.Location = new System.Drawing.Point(572, 185);
this.btnClear.Name = "btnClear";
this.btnClear.Size = new System.Drawing.Size(75, 35);
this.btnClear.TabIndex = 5;
this.btnClear.Text = "Clear";
this.btnClear.UseVisualStyleBackColor = true;
this.btnClear.Click += new System.EventHandler(this.btnClear_Click);
//
// btnSaveAs
//
this.btnSaveAs.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnSaveAs.Location = new System.Drawing.Point(174, 321);
this.btnSaveAs.Margin = new System.Windows.Forms.Padding(3, 3, 3, 5);
this.btnSaveAs.Name = "btnSaveAs";
this.btnSaveAs.Size = new System.Drawing.Size(75, 23);
this.btnSaveAs.TabIndex = 9;
this.btnSaveAs.Text = "Save As";
this.btnSaveAs.UseVisualStyleBackColor = true;
this.btnSaveAs.Click += new System.EventHandler(this.btnSaveAs_Click);
//
// menuStrip1
//
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.settingsToolStripMenuItem,
this.texttospeechToolStripMenuItem,
this.checkForUpdateToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(659, 24);
this.menuStrip1.TabIndex = 17;
this.menuStrip1.Text = "menuStrip1";
this.menuStrip1.Click += new System.EventHandler(this.form_Click);
//
// settingsToolStripMenuItem
//
this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
this.settingsToolStripMenuItem.Text = "Settings";
this.settingsToolStripMenuItem.Click += new System.EventHandler(this.settingsToolStripMenuItem_Click);
//
// texttospeechToolStripMenuItem
//
this.texttospeechToolStripMenuItem.Name = "texttospeechToolStripMenuItem";
this.texttospeechToolStripMenuItem.Size = new System.Drawing.Size(98, 20);
this.texttospeechToolStripMenuItem.Text = "Text-to-speech";
this.texttospeechToolStripMenuItem.Click += new System.EventHandler(this.texttospeechToolStripMenuItem_Click);
//
// checkForUpdateToolStripMenuItem
//
this.checkForUpdateToolStripMenuItem.Name = "checkForUpdateToolStripMenuItem";
this.checkForUpdateToolStripMenuItem.Size = new System.Drawing.Size(110, 20);
this.checkForUpdateToolStripMenuItem.Text = "Check for update";
this.checkForUpdateToolStripMenuItem.Click += new System.EventHandler(this.checkForUpdateToolStripMenuItem_Click);
//
// lblLoopback
//
this.lblLoopback.AutoSize = true;
this.lblLoopback.Location = new System.Drawing.Point(8, 48);
this.lblLoopback.Margin = new System.Windows.Forms.Padding(5);
this.lblLoopback.Name = "lblLoopback";
this.lblLoopback.Size = new System.Drawing.Size(114, 13);
this.lblLoopback.TabIndex = 18;
this.lblLoopback.Text = "Microphone Loopback";
//
// cbLoopbackDevices
//
this.cbLoopbackDevices.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbLoopbackDevices.FormattingEnabled = true;
this.cbLoopbackDevices.Location = new System.Drawing.Point(142, 45);
this.cbLoopbackDevices.Margin = new System.Windows.Forms.Padding(5, 3, 5, 3);
this.cbLoopbackDevices.Name = "cbLoopbackDevices";
this.cbLoopbackDevices.Size = new System.Drawing.Size(176, 21);
this.cbLoopbackDevices.TabIndex = 12;
//
// btnPlaySelectedSound
//
this.btnPlaySelectedSound.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnPlaySelectedSound.Location = new System.Drawing.Point(572, 223);
this.btnPlaySelectedSound.Name = "btnPlaySelectedSound";
this.btnPlaySelectedSound.Size = new System.Drawing.Size(75, 35);
this.btnPlaySelectedSound.TabIndex = 6;
this.btnPlaySelectedSound.Text = "Play sound";
this.btnPlaySelectedSound.UseVisualStyleBackColor = true;
this.btnPlaySelectedSound.Click += new System.EventHandler(this.btnPlaySound_Click);
//
// btnStopAllSounds
//
this.btnStopAllSounds.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnStopAllSounds.Location = new System.Drawing.Point(572, 261);
this.btnStopAllSounds.Name = "btnStopAllSounds";
this.btnStopAllSounds.Size = new System.Drawing.Size(75, 35);
this.btnStopAllSounds.TabIndex = 7;
this.btnStopAllSounds.Text = "Stop all sounds";
this.btnStopAllSounds.UseVisualStyleBackColor = true;
this.btnStopAllSounds.Click += new System.EventHandler(this.btnStopAllSounds_Click);
//
// notifyIcon1
//
this.notifyIcon1.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;
this.notifyIcon1.BalloonTipText = "Minimised to the tray.";
this.notifyIcon1.BalloonTipTitle = "JN Soundboard";
this.notifyIcon1.ContextMenuStrip = this.contextMenuStrip1;
this.notifyIcon1.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon1.Icon")));
this.notifyIcon1.Text = "JN Soundboard";
this.notifyIcon1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.notifyIcon1_MouseUp);
//
// contextMenuStrip1
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.openToolStripMenuItem,
this.exitToolStripMenuItem});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(104, 48);
//
// openToolStripMenuItem
//
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
this.openToolStripMenuItem.Size = new System.Drawing.Size(103, 22);
this.openToolStripMenuItem.Text = "Open";
this.openToolStripMenuItem.Click += new System.EventHandler(this.Open_Click);
//
// exitToolStripMenuItem
//
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
this.exitToolStripMenuItem.Size = new System.Drawing.Size(103, 22);
this.exitToolStripMenuItem.Text = "Exit";
this.exitToolStripMenuItem.Click += new System.EventHandler(this.Exit_Click);
//
// gbPushToTalk
//
this.gbPushToTalk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.gbPushToTalk.Controls.Add(this.clearHotkey);
this.gbPushToTalk.Controls.Add(this.btnReloadWindows);
this.gbPushToTalk.Controls.Add(this.cbEnablePushToTalk);
this.gbPushToTalk.Controls.Add(this.label3);
this.gbPushToTalk.Controls.Add(this.tbPushToTalkKey);
this.gbPushToTalk.Controls.Add(this.cbWindows);
this.gbPushToTalk.Controls.Add(this.label4);
this.gbPushToTalk.Location = new System.Drawing.Point(373, 434);
this.gbPushToTalk.Name = "gbPushToTalk";
this.gbPushToTalk.Size = new System.Drawing.Size(274, 91);
this.gbPushToTalk.TabIndex = 19;
this.gbPushToTalk.TabStop = false;
this.gbPushToTalk.Text = "Auto activate push to talk";
this.gbPushToTalk.Click += new System.EventHandler(this.form_Click);
//
// clearHotkey
//
this.clearHotkey.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.clearHotkey.ForeColor = System.Drawing.Color.Red;
this.clearHotkey.Location = new System.Drawing.Point(244, 17);
this.clearHotkey.Margin = new System.Windows.Forms.Padding(3, 5, 5, 3);
this.clearHotkey.Name = "clearHotkey";
this.clearHotkey.Size = new System.Drawing.Size(22, 22);
this.clearHotkey.TabIndex = 21;
this.clearHotkey.Text = "X";
this.clearHotkey.UseVisualStyleBackColor = true;
this.clearHotkey.Click += new System.EventHandler(this.clearHotkey_Click);
//
// btnReloadWindows
//
this.btnReloadWindows.Image = ((System.Drawing.Image)(resources.GetObject("btnReloadWindows.Image")));
this.btnReloadWindows.Location = new System.Drawing.Point(244, 43);
this.btnReloadWindows.Margin = new System.Windows.Forms.Padding(3, 3, 5, 3);
this.btnReloadWindows.Name = "btnReloadWindows";
this.btnReloadWindows.Size = new System.Drawing.Size(22, 23);
this.btnReloadWindows.TabIndex = 23;
this.btnReloadWindows.UseVisualStyleBackColor = true;
this.btnReloadWindows.Click += new System.EventHandler(this.btnReloadWindows_Click);
//
// cbEnablePushToTalk
//
this.cbEnablePushToTalk.AutoSize = true;
this.cbEnablePushToTalk.Location = new System.Drawing.Point(8, 71);
this.cbEnablePushToTalk.Margin = new System.Windows.Forms.Padding(5, 3, 3, 5);
this.cbEnablePushToTalk.Name = "cbEnablePushToTalk";
this.cbEnablePushToTalk.Size = new System.Drawing.Size(59, 17);
this.cbEnablePushToTalk.TabIndex = 24;
this.cbEnablePushToTalk.Text = "Enable";
this.cbEnablePushToTalk.UseVisualStyleBackColor = true;
this.cbEnablePushToTalk.CheckedChanged += new System.EventHandler(this.cbEnablePushToTalk_CheckedChanged);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(8, 21);
this.label3.Margin = new System.Windows.Forms.Padding(5, 5, 3, 3);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(25, 13);
this.label3.TabIndex = 1;
this.label3.Text = "Key";
//
// tbPushToTalkKey
//
this.tbPushToTalkKey.Location = new System.Drawing.Point(62, 18);
this.tbPushToTalkKey.Name = "tbPushToTalkKey";
this.tbPushToTalkKey.ReadOnly = true;
this.tbPushToTalkKey.ShortcutsEnabled = false;
this.tbPushToTalkKey.Size = new System.Drawing.Size(176, 20);
this.tbPushToTalkKey.TabIndex = 20;
this.tbPushToTalkKey.Enter += new System.EventHandler(this.tbPushToTalkKey_Enter);
this.tbPushToTalkKey.Leave += new System.EventHandler(this.tbPushToTalkKey_Leave);
//
// cbWindows
//
this.cbWindows.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.cbWindows.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
this.cbWindows.FormattingEnabled = true;
this.cbWindows.Location = new System.Drawing.Point(62, 44);
this.cbWindows.Margin = new System.Windows.Forms.Padding(5, 3, 5, 3);
this.cbWindows.Name = "cbWindows";
this.cbWindows.Size = new System.Drawing.Size(176, 21);
this.cbWindows.TabIndex = 22;
this.cbWindows.Leave += new System.EventHandler(this.cbWindows_Leave);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(8, 47);
this.label4.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(46, 13);
this.label4.TabIndex = 2;
this.label4.Text = "Window";
//
// gbAudioDevices
//
this.gbAudioDevices.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.gbAudioDevices.Controls.Add(this.cbPlaybackDevices2);
this.gbAudioDevices.Controls.Add(this.label6);
this.gbAudioDevices.Controls.Add(this.lblPlayback2);
this.gbAudioDevices.Controls.Add(this.lblPlayback1);
this.gbAudioDevices.Controls.Add(this.lblLoopback);
this.gbAudioDevices.Controls.Add(this.btnReloadDevices);
this.gbAudioDevices.Controls.Add(this.cbPlaybackDevices1);
this.gbAudioDevices.Controls.Add(this.cbLoopbackDevices);
this.gbAudioDevices.Location = new System.Drawing.Point(12, 352);
this.gbAudioDevices.Name = "gbAudioDevices";
this.gbAudioDevices.Size = new System.Drawing.Size(355, 173);
this.gbAudioDevices.TabIndex = 10;
this.gbAudioDevices.TabStop = false;
this.gbAudioDevices.Text = "Soundboard Audio devices";
this.gbAudioDevices.Click += new System.EventHandler(this.form_Click);
//
// cbPlaybackDevices2
//
this.cbPlaybackDevices2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbPlaybackDevices2.FormattingEnabled = true;
this.cbPlaybackDevices2.Location = new System.Drawing.Point(142, 95);
this.cbPlaybackDevices2.Margin = new System.Windows.Forms.Padding(5);
this.cbPlaybackDevices2.Name = "cbPlaybackDevices2";
this.cbPlaybackDevices2.Size = new System.Drawing.Size(176, 21);
this.cbPlaybackDevices2.TabIndex = 13;
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(139, 69);
this.label6.Margin = new System.Windows.Forms.Padding(3, 0, 3, 8);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(141, 13);
this.label6.TabIndex = 20;
this.label6.Text = "(do not choose virtual cable)";
//
// lblPlayback2
//
this.lblPlayback2.AutoSize = true;
this.lblPlayback2.Location = new System.Drawing.Point(8, 98);
this.lblPlayback2.Margin = new System.Windows.Forms.Padding(5);
this.lblPlayback2.Name = "lblPlayback2";
this.lblPlayback2.Size = new System.Drawing.Size(97, 13);
this.lblPlayback2.TabIndex = 19;
this.lblPlayback2.Text = "Playback Device 2";
//
// pushToTalkKeyTimer
//
this.pushToTalkKeyTimer.Tick += new System.EventHandler(this.pushToTalkKeyTimer_Tick);
//
// cbEnableLoopback
//
this.cbEnableLoopback.AutoSize = true;
this.cbEnableLoopback.Location = new System.Drawing.Point(115, 17);
this.cbEnableLoopback.Margin = new System.Windows.Forms.Padding(3, 5, 5, 3);
this.cbEnableLoopback.Name = "cbEnableLoopback";
this.cbEnableLoopback.Size = new System.Drawing.Size(110, 17);
this.cbEnableLoopback.TabIndex = 17;
this.cbEnableLoopback.Text = "Enable Loopback";
this.cbEnableLoopback.UseVisualStyleBackColor = true;
this.cbEnableLoopback.CheckedChanged += new System.EventHandler(this.cbEnableLoopback_CheckedChanged);
//
// vsPublicVolume
//
this.vsPublicVolume.Location = new System.Drawing.Point(8, 49);
this.vsPublicVolume.Margin = new System.Windows.Forms.Padding(5, 3, 3, 5);
this.vsPublicVolume.Name = "vsPublicVolume";
this.vsPublicVolume.Size = new System.Drawing.Size(213, 20);
this.vsPublicVolume.TabIndex = 100;
this.vsPublicVolume.TabStop = false;
this.vsPublicVolume.VolumeChanged += new System.EventHandler(this.vsPublicVolume_VolumeChanged);
this.vsPublicVolume.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.vsPublicVolume_MouseWheel);
//
// nPublicVolume
//
this.nPublicVolume.Location = new System.Drawing.Point(223, 49);
this.nPublicVolume.Margin = new System.Windows.Forms.Padding(3, 3, 5, 5);
this.nPublicVolume.Name = "nPublicVolume";
this.nPublicVolume.Size = new System.Drawing.Size(39, 20);
this.nPublicVolume.TabIndex = 101;
this.nPublicVolume.Value = new decimal(new int[] {
100,
0,
0,
0});
this.nPublicVolume.ValueChanged += new System.EventHandler(this.nPublicVolume_ValueChanged);
//
// gbSoundboard
//
this.gbSoundboard.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.gbSoundboard.Controls.Add(this.cbAudioBoost);
this.gbSoundboard.Controls.Add(this.label2);
this.gbSoundboard.Controls.Add(this.nPrivateVolume);
this.gbSoundboard.Controls.Add(this.label1);
this.gbSoundboard.Controls.Add(this.vsPrivateVolume);
this.gbSoundboard.Controls.Add(this.cbEnableLoopback);
this.gbSoundboard.Controls.Add(this.cbEnableHotkeys);
this.gbSoundboard.Controls.Add(this.vsPublicVolume);
this.gbSoundboard.Controls.Add(this.nPublicVolume);
this.gbSoundboard.Location = new System.Drawing.Point(373, 321);
this.gbSoundboard.Name = "gbSoundboard";
this.gbSoundboard.Size = new System.Drawing.Size(274, 113);
this.gbSoundboard.TabIndex = 15;
this.gbSoundboard.TabStop = false;
this.gbSoundboard.Text = "Soundboard";
this.gbSoundboard.Click += new System.EventHandler(this.form_Click);
//
// cbAudioBoost
//
this.cbAudioBoost.AutoSize = true;
this.cbAudioBoost.Location = new System.Drawing.Point(223, 17);
this.cbAudioBoost.Margin = new System.Windows.Forms.Padding(3, 5, 5, 3);
this.cbAudioBoost.Name = "cbAudioBoost";
this.cbAudioBoost.Size = new System.Drawing.Size(37, 17);
this.cbAudioBoost.TabIndex = 107;
this.cbAudioBoost.Text = "5x";
this.cbAudioBoost.UseVisualStyleBackColor = true;
this.cbAudioBoost.CheckedChanged += new System.EventHandler(this.cbAudioBoost_CheckedChanged);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(11, 36);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(164, 13);
this.label2.TabIndex = 104;
this.label2.Text = "Public Volume (Speakers or VAC)";
//
// nPrivateVolume
//
this.nPrivateVolume.Location = new System.Drawing.Point(224, 84);
this.nPrivateVolume.Margin = new System.Windows.Forms.Padding(3, 3, 5, 5);
this.nPrivateVolume.Name = "nPrivateVolume";
this.nPrivateVolume.Size = new System.Drawing.Size(39, 20);
this.nPrivateVolume.TabIndex = 106;
this.nPrivateVolume.Value = new decimal(new int[] {
100,
0,
0,
0});
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(11, 70);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(177, 13);
this.label1.TabIndex = 103;
this.label1.Text = "Private Volume (Playback Device 2)";
//
// vsPrivateVolume
//
this.vsPrivateVolume.Location = new System.Drawing.Point(8, 85);
this.vsPrivateVolume.Margin = new System.Windows.Forms.Padding(5, 3, 3, 5);
this.vsPrivateVolume.Name = "vsPrivateVolume";
this.vsPrivateVolume.Size = new System.Drawing.Size(213, 20);
this.vsPrivateVolume.TabIndex = 102;
this.vsPrivateVolume.TabStop = false;
this.vsPrivateVolume.VolumeChanged += new System.EventHandler(this.vsPrivateVolume_VolumeChanged);
this.vsPrivateVolume.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.vsPrivateVolume_MouseWheel);
//
// saveSettingsTimer
//
this.saveSettingsTimer.Interval = 1000;
this.saveSettingsTimer.Tick += new System.EventHandler(this.saveSettingsTimer_Tick);
//
// btnAddDirectory
//
this.btnAddDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnAddDirectory.Location = new System.Drawing.Point(572, 68);
this.btnAddDirectory.Name = "btnAddDirectory";
this.btnAddDirectory.Size = new System.Drawing.Size(75, 35);
this.btnAddDirectory.TabIndex = 2;
this.btnAddDirectory.Text = "Add Directory";
this.btnAddDirectory.UseVisualStyleBackColor = true;
this.btnAddDirectory.Click += new System.EventHandler(this.btnAddDirectory_Click);
//
// cbLoopSound
//
this.cbLoopSound.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cbLoopSound.AutoSize = true;
this.cbLoopSound.Location = new System.Drawing.Point(583, 304);
this.cbLoopSound.Margin = new System.Windows.Forms.Padding(3, 5, 5, 3);
this.cbLoopSound.Name = "cbLoopSound";
this.cbLoopSound.Size = new System.Drawing.Size(50, 17);
this.cbLoopSound.TabIndex = 108;
this.cbLoopSound.Text = "Loop";
this.cbLoopSound.UseVisualStyleBackColor = true;
this.cbLoopSound.CheckedChanged += new System.EventHandler(this.cbLoopSound_CheckedChanged);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(659, 537);
this.Controls.Add(this.cbLoopSound);
this.Controls.Add(this.btnAddDirectory);
this.Controls.Add(this.gbSoundboard);
this.Controls.Add(this.gbAudioDevices);
this.Controls.Add(this.gbPushToTalk);
this.Controls.Add(this.btnStopAllSounds);
this.Controls.Add(this.btnPlaySelectedSound);
this.Controls.Add(this.btnSaveAs);
this.Controls.Add(this.btnClear);
this.Controls.Add(this.btnLoad);
this.Controls.Add(this.btnSave);
this.Controls.Add(this.btnRemove);
this.Controls.Add(this.btnEdit);
this.Controls.Add(this.btnAdd);
this.Controls.Add(this.lvKeySounds);
this.Controls.Add(this.menuStrip1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MainMenuStrip = this.menuStrip1;
this.MinimumSize = new System.Drawing.Size(675, 576);
this.Name = "MainForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "JN Soundboard";
this.Click += new System.EventHandler(this.form_Click);
this.Resize += new System.EventHandler(this.frmMain_Resize);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.contextMenuStrip1.ResumeLayout(false);
this.gbPushToTalk.ResumeLayout(false);
this.gbPushToTalk.PerformLayout();
this.gbAudioDevices.ResumeLayout(false);
this.gbAudioDevices.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nPublicVolume)).EndInit();
this.gbSoundboard.ResumeLayout(false);
this.gbSoundboard.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nPrivateVolume)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblPlayback1;
private System.Windows.Forms.ComboBox cbPlaybackDevices1;
private System.Windows.Forms.CheckBox cbEnableHotkeys;
internal System.Windows.Forms.Timer mainTimer;
private System.Windows.Forms.Button btnSave;
private System.Windows.Forms.Button btnRemove;
private System.Windows.Forms.Button btnEdit;
private System.Windows.Forms.Button btnAdd;
internal System.Windows.Forms.ListView lvKeySounds;
private System.Windows.Forms.Button btnLoad;
private System.Windows.Forms.Button btnReloadDevices;
internal System.Windows.Forms.ColumnHeader chKeys;
internal System.Windows.Forms.ColumnHeader chLocation;
private System.Windows.Forms.Button btnClear;
private System.Windows.Forms.Button btnSaveAs;
private System.Windows.Forms.MenuStrip menuStrip1;
private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem;
private System.Windows.Forms.Label lblLoopback;
private System.Windows.Forms.ComboBox cbLoopbackDevices;
private System.Windows.Forms.Button btnPlaySelectedSound;
private System.Windows.Forms.Button btnStopAllSounds;
private System.Windows.Forms.NotifyIcon notifyIcon1;
private System.Windows.Forms.GroupBox gbPushToTalk;
private System.Windows.Forms.CheckBox cbEnablePushToTalk;
private System.Windows.Forms.ComboBox cbWindows;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox tbPushToTalkKey;
private System.Windows.Forms.GroupBox gbAudioDevices;
private System.Windows.Forms.ToolStripMenuItem texttospeechToolStripMenuItem;
private System.Windows.Forms.Button btnReloadWindows;
private System.Windows.Forms.Timer pushToTalkKeyTimer;
internal System.Windows.Forms.ColumnHeader chWindow;
private System.Windows.Forms.ToolStripMenuItem checkForUpdateToolStripMenuItem;
private System.Windows.Forms.ComboBox cbPlaybackDevices2;
private System.Windows.Forms.Label lblPlayback2;
private System.Windows.Forms.Button clearHotkey;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
private System.Windows.Forms.CheckBox cbEnableLoopback;
private System.Windows.Forms.NumericUpDown nPublicVolume;
private System.Windows.Forms.GroupBox gbSoundboard;
private System.Windows.Forms.Timer saveSettingsTimer;
internal System.Windows.Forms.ColumnHeader chVolume;
private System.Windows.Forms.ColumnHeader chName;
private System.Windows.Forms.Button btnAddDirectory;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.NumericUpDown nPrivateVolume;
private System.Windows.Forms.CheckBox cbAudioBoost;
public System.Windows.Forms.CheckBox cbLoopSound;
public NAudio.Gui.VolumeSlider vsPublicVolume;
public NAudio.Gui.VolumeSlider vsPrivateVolume;
}
}

1444
src/MainForm.cs Executable file

File diff suppressed because it is too large Load Diff

12512
src/MainForm.resx Executable file

File diff suppressed because it is too large Load Diff

32
src/Program.cs Executable file
View File

@ -0,0 +1,32 @@
using System;
using System.Runtime.InteropServices; //GuidAttribute
using System.Reflection; //Assembly
using System.Threading; //Mutex
using System.Windows.Forms;
namespace JNSoundboard
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
using (Mutex mutex = new Mutex(false, @"Global\" + appGuid))
{
//prevent multiple instances
if (!mutex.WaitOne(0, false)) return;
GC.Collect();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
}

35
src/Properties/AssemblyInfo.cs Executable file
View File

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("JN Soundboard")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("JN Soundboard")]
[assembly: AssemblyCopyright("Copyright © Jitnaught 2017, EmbarassingUsername 2019, ZenitH-AT 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("19061049-9D75-4CFA-83BD-104292313E10")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.1.0")]
[assembly: AssemblyFileVersion("1.2.1.0")]

63
src/Properties/Resources.Designer.cs generated Executable file
View File

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace JNSoundboard.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JNSoundboard.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

120
src/Properties/Resources.resx Executable file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

26
src/Properties/Settings.Designer.cs generated Executable file
View File

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace JNSoundboard.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

275
src/SettingsForm.Designer.cs generated Executable file
View File

@ -0,0 +1,275 @@
namespace JNSoundboard
{
partial class SettingsForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingsForm));
this.label1 = new System.Windows.Forms.Label();
this.tbStopSoundKeys = new System.Windows.Forms.TextBox();
this.lvKeysLocations = new System.Windows.Forms.ListView();
this.chKeys = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.chXMLLocation = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.btnOK = new System.Windows.Forms.Button();
this.btnAdd = new System.Windows.Forms.Button();
this.btnEdit = new System.Windows.Forms.Button();
this.btnRemove = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.keysTimer = new System.Windows.Forms.Timer(this.components);
this.gbKeysLocations = new System.Windows.Forms.GroupBox();
this.cbMinimiseToTray = new System.Windows.Forms.CheckBox();
this.clearHotkey = new System.Windows.Forms.Button();
this.cbStartWithWindows = new System.Windows.Forms.CheckBox();
this.cbStartMinimised = new System.Windows.Forms.CheckBox();
this.gbKeysLocations.SuspendLayout();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(104, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Stop all sounds keys";
//
// tbStopSoundKeys
//
this.tbStopSoundKeys.Location = new System.Drawing.Point(12, 25);
this.tbStopSoundKeys.Name = "tbStopSoundKeys";
this.tbStopSoundKeys.ReadOnly = true;
this.tbStopSoundKeys.ShortcutsEnabled = false;
this.tbStopSoundKeys.Size = new System.Drawing.Size(213, 20);
this.tbStopSoundKeys.TabIndex = 0;
this.tbStopSoundKeys.Enter += new System.EventHandler(this.tbStopSoundKeys_Enter);
this.tbStopSoundKeys.Leave += new System.EventHandler(this.tbStopSoundKeys_Leave);
//
// lvKeysLocations
//
this.lvKeysLocations.Alignment = System.Windows.Forms.ListViewAlignment.Default;
this.lvKeysLocations.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lvKeysLocations.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.chKeys,
this.chXMLLocation});
this.lvKeysLocations.FullRowSelect = true;
this.lvKeysLocations.GridLines = true;
this.lvKeysLocations.HideSelection = false;
this.lvKeysLocations.Location = new System.Drawing.Point(6, 19);
this.lvKeysLocations.MultiSelect = false;
this.lvKeysLocations.Name = "lvKeysLocations";
this.lvKeysLocations.ShowItemToolTips = true;
this.lvKeysLocations.Size = new System.Drawing.Size(420, 128);
this.lvKeysLocations.TabIndex = 3;
this.lvKeysLocations.UseCompatibleStateImageBehavior = false;
this.lvKeysLocations.View = System.Windows.Forms.View.Details;
this.lvKeysLocations.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.lvKeysLocations_MouseDoubleClick);
//
// chKeys
//
this.chKeys.Text = "Keys";
this.chKeys.Width = 150;
//
// chXMLLocation
//
this.chXMLLocation.Text = "XML location";
this.chXMLLocation.Width = 266;
//
// btnOK
//
this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnOK.Location = new System.Drawing.Point(288, 319);
this.btnOK.Margin = new System.Windows.Forms.Padding(3, 10, 3, 3);
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size(75, 23);
this.btnOK.TabIndex = 10;
this.btnOK.Text = "OK";
this.btnOK.UseVisualStyleBackColor = true;
this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
//
// btnAdd
//
this.btnAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnAdd.Location = new System.Drawing.Point(6, 153);
this.btnAdd.Name = "btnAdd";
this.btnAdd.Size = new System.Drawing.Size(75, 23);
this.btnAdd.TabIndex = 4;
this.btnAdd.Text = "Add";
this.btnAdd.UseVisualStyleBackColor = true;
this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click);
//
// btnEdit
//
this.btnEdit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnEdit.Location = new System.Drawing.Point(87, 153);
this.btnEdit.Name = "btnEdit";
this.btnEdit.Size = new System.Drawing.Size(75, 23);
this.btnEdit.TabIndex = 5;
this.btnEdit.Text = "Edit";
this.btnEdit.UseVisualStyleBackColor = true;
this.btnEdit.Click += new System.EventHandler(this.btnEdit_Click);
//
// btnRemove
//
this.btnRemove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnRemove.Location = new System.Drawing.Point(168, 153);
this.btnRemove.Name = "btnRemove";
this.btnRemove.Size = new System.Drawing.Size(75, 23);
this.btnRemove.TabIndex = 6;
this.btnRemove.Text = "Remove";
this.btnRemove.UseVisualStyleBackColor = true;
this.btnRemove.Click += new System.EventHandler(this.btnRemove_Click);
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(369, 319);
this.btnCancel.Margin = new System.Windows.Forms.Padding(3, 10, 3, 3);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 11;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// keysTimer
//
this.keysTimer.Tick += new System.EventHandler(this.keysTimer_Tick);
//
// gbKeysLocations
//
this.gbKeysLocations.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.gbKeysLocations.Controls.Add(this.lvKeysLocations);
this.gbKeysLocations.Controls.Add(this.btnAdd);
this.gbKeysLocations.Controls.Add(this.btnRemove);
this.gbKeysLocations.Controls.Add(this.btnEdit);
this.gbKeysLocations.Location = new System.Drawing.Point(12, 53);
this.gbKeysLocations.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.gbKeysLocations.Name = "gbKeysLocations";
this.gbKeysLocations.Size = new System.Drawing.Size(432, 182);
this.gbKeysLocations.TabIndex = 2;
this.gbKeysLocations.TabStop = false;
this.gbKeysLocations.Text = "Load XML file with keys";
//
// cbMinimiseToTray
//
this.cbMinimiseToTray.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.cbMinimiseToTray.AutoSize = true;
this.cbMinimiseToTray.Location = new System.Drawing.Point(12, 289);
this.cbMinimiseToTray.Name = "cbMinimiseToTray";
this.cbMinimiseToTray.Size = new System.Drawing.Size(214, 17);
this.cbMinimiseToTray.TabIndex = 9;
this.cbMinimiseToTray.Text = "Send application to tray when minimised";
this.cbMinimiseToTray.UseVisualStyleBackColor = true;
//
// clearHotkey
//
this.clearHotkey.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.clearHotkey.ForeColor = System.Drawing.Color.Red;
this.clearHotkey.Location = new System.Drawing.Point(231, 24);
this.clearHotkey.Name = "clearHotkey";
this.clearHotkey.Size = new System.Drawing.Size(22, 22);
this.clearHotkey.TabIndex = 1;
this.clearHotkey.Text = "X";
this.clearHotkey.UseVisualStyleBackColor = true;
this.clearHotkey.Click += new System.EventHandler(this.clearHotkey_Click);
//
// cbStartWithWindows
//
this.cbStartWithWindows.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.cbStartWithWindows.AutoSize = true;
this.cbStartWithWindows.Location = new System.Drawing.Point(12, 266);
this.cbStartWithWindows.Name = "cbStartWithWindows";
this.cbStartWithWindows.Size = new System.Drawing.Size(171, 17);
this.cbStartWithWindows.TabIndex = 8;
this.cbStartWithWindows.Text = "Start application with Windows";
this.cbStartWithWindows.UseVisualStyleBackColor = true;
//
// cbStartMinimised
//
this.cbStartMinimised.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.cbStartMinimised.AutoSize = true;
this.cbStartMinimised.Location = new System.Drawing.Point(12, 243);
this.cbStartMinimised.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.cbStartMinimised.Name = "cbStartMinimised";
this.cbStartMinimised.Size = new System.Drawing.Size(150, 17);
this.cbStartMinimised.TabIndex = 7;
this.cbStartMinimised.Text = "Start application minimised";
this.cbStartMinimised.UseVisualStyleBackColor = true;
//
// SettingsForm
//
this.AcceptButton = this.btnOK;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(456, 354);
this.Controls.Add(this.cbStartMinimised);
this.Controls.Add(this.cbStartWithWindows);
this.Controls.Add(this.clearHotkey);
this.Controls.Add(this.cbMinimiseToTray);
this.Controls.Add(this.gbKeysLocations);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOK);
this.Controls.Add(this.tbStopSoundKeys);
this.Controls.Add(this.label1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(472, 393);
this.Name = "SettingsForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Soundboard Settings";
this.gbKeysLocations.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox tbStopSoundKeys;
internal System.Windows.Forms.ListView lvKeysLocations;
internal System.Windows.Forms.ColumnHeader chKeys;
internal System.Windows.Forms.ColumnHeader chXMLLocation;
private System.Windows.Forms.Button btnOK;
private System.Windows.Forms.Button btnAdd;
private System.Windows.Forms.Button btnEdit;
private System.Windows.Forms.Button btnRemove;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Timer keysTimer;
private System.Windows.Forms.GroupBox gbKeysLocations;
private System.Windows.Forms.CheckBox cbMinimiseToTray;
private System.Windows.Forms.Button clearHotkey;
private System.Windows.Forms.CheckBox cbStartWithWindows;
private System.Windows.Forms.CheckBox cbStartMinimised;
}
}

153
src/SettingsForm.cs Executable file
View File

@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace JNSoundboard
{
public partial class SettingsForm : Form
{
internal List<XMLSettings.LoadXMLFile> loadXMLFilesList = new List<XMLSettings.LoadXMLFile>(XMLSettings.soundboardSettings.LoadXMLFiles); //list so can dynamically add/remove
internal static bool addingEditingLoadXMLFile = false;
public SettingsForm()
{
InitializeComponent();
for (int i = 0; i < loadXMLFilesList.Count; i++)
{
string xmlLocation = loadXMLFilesList[i].XMLLocation;
bool keysLengthCorrect = loadXMLFilesList[i].Keys.Length > 0;
bool xmlLocationUnempty = !string.IsNullOrWhiteSpace(xmlLocation);
if (!keysLengthCorrect && !xmlLocationUnempty) //remove if empty
{
loadXMLFilesList.RemoveAt(i);
i--;
continue;
}
var item = new ListViewItem((keysLengthCorrect ? string.Join("+", loadXMLFilesList[i].Keys) : ""));
item.SubItems.Add((xmlLocationUnempty ? xmlLocation : ""));
item.ToolTipText = Helper.getFileNamesTooltip(new string[] { xmlLocation });
lvKeysLocations.Items.Add(item);
}
tbStopSoundKeys.Text = Helper.keysArrayToString(XMLSettings.soundboardSettings.StopSoundKeys);
cbStartWithWindows.Checked = XMLSettings.soundboardSettings.StartWithWindows;
cbStartMinimised.Checked = XMLSettings.soundboardSettings.StartMinimised;
cbMinimiseToTray.Checked = XMLSettings.soundboardSettings.MinimiseToTray;
}
private void btnAdd_Click(object sender, EventArgs e)
{
addingEditingLoadXMLFile = true;
var form = new AddEditHotkeyForm();
form.ShowDialog();
addingEditingLoadXMLFile = false;
}
private void btnEdit_Click(object sender, EventArgs e)
{
if (lvKeysLocations.SelectedIndices.Count > 0)
{
addingEditingLoadXMLFile = true;
var form = new AddEditHotkeyForm();
form.editIndex = lvKeysLocations.SelectedIndices[0];
form.editStrings = new string[] { lvKeysLocations.SelectedItems[0].Text, lvKeysLocations.SelectedItems[0].SubItems[1].Text };
form.ShowDialog();
addingEditingLoadXMLFile = false;
}
}
private void btnRemove_Click(object sender, EventArgs e)
{
if (lvKeysLocations.SelectedIndices.Count > 0 && MessageBox.Show("Are you sure?", "Are you sure?", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
int index = lvKeysLocations.SelectedIndices[0];
lvKeysLocations.Items.RemoveAt(index);
loadXMLFilesList.RemoveAt(index);
}
}
private void btnOK_Click(object sender, EventArgs e)
{
if (!Helper.stringToKeysArray(tbStopSoundKeys.Text, out Keyboard.Keys[] keysArray, out _)) keysArray = new Keyboard.Keys[] { };
if (loadXMLFilesList.Count == 0 || loadXMLFilesList.All(x => x.Keys.Length > 0 && !string.IsNullOrWhiteSpace(x.XMLLocation) && File.Exists(x.XMLLocation)))
{
XMLSettings.soundboardSettings.StopSoundKeys = keysArray;
XMLSettings.soundboardSettings.LoadXMLFiles = loadXMLFilesList.ToArray();
XMLSettings.soundboardSettings.StartWithWindows = cbStartWithWindows.Checked;
Helper.setStartup(XMLSettings.soundboardSettings.StartWithWindows);
XMLSettings.soundboardSettings.StartMinimised = cbStartMinimised.Checked;
XMLSettings.soundboardSettings.MinimiseToTray = cbMinimiseToTray.Checked;
XMLSettings.SaveSoundboardSettingsXML();
this.Close();
}
else
{
MessageBox.Show("One or more entries either have no keys added, the location is empty, or the file the location points to does not exist");
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
private void lvKeysLocations_MouseDoubleClick(object sender, MouseEventArgs e)
{
btnEdit_Click(null, null);
}
private void tbStopSoundKeys_Enter(object sender, EventArgs e)
{
keysTimer.Enabled = true;
}
private void tbStopSoundKeys_Leave(object sender, EventArgs e)
{
keysTimer.Enabled = false;
keysTimer.Interval = 100;
}
private int lastAmountPressed = 0;
private void keysTimer_Tick(object sender, EventArgs e)
{
keysTimer.Interval = 10; //lowering the interval to avoid missing key presses (e.g. when an input is corrected)
var keysData = Keyboard.getKeys(lastAmountPressed, tbStopSoundKeys.Text);
lastAmountPressed = keysData.Item1;
tbStopSoundKeys.Text = keysData.Item2;
}
private void clearHotkey_Click(object sender, EventArgs e)
{
tbStopSoundKeys.Text = "";
}
}
}

6296
src/SettingsForm.resx Executable file

File diff suppressed because it is too large Load Diff

370
src/TextToSpeechForm.Designer.cs generated Executable file
View File

@ -0,0 +1,370 @@
namespace JNSoundboard
{
partial class TextToSpeechForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TextToSpeechForm));
this.label3 = new System.Windows.Forms.Label();
this.vsSoundVolume = new NAudio.Gui.VolumeSlider();
this.cbAddToList = new System.Windows.Forms.CheckBox();
this.preview = new System.Windows.Forms.Button();
this.btnCreateWAV = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.tbKeys = new System.Windows.Forms.TextBox();
this.btnCancel = new System.Windows.Forms.Button();
this.keysTimer = new System.Windows.Forms.Timer(this.components);
this.nSoundVolume = new System.Windows.Forms.NumericUpDown();
this.label5 = new System.Windows.Forms.Label();
this.cbWindows = new System.Windows.Forms.ComboBox();
this.btnReloadWindows = new System.Windows.Forms.Button();
this.label4 = new System.Windows.Forms.Label();
this.cbGender = new System.Windows.Forms.ComboBox();
this.clearHotkey = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.tbText = new System.Windows.Forms.TextBox();
this.label6 = new System.Windows.Forms.Label();
this.tbName = new System.Windows.Forms.TextBox();
this.stopPreview = new System.Windows.Forms.Button();
this.btnPlayThroughMic = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.nSoundVolume)).BeginInit();
this.SuspendLayout();
//
// label3
//
this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 266);
this.label3.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(79, 13);
this.label3.TabIndex = 116;
this.label3.Text = "Custom volume";
//
// vsSoundVolume
//
this.vsSoundVolume.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.vsSoundVolume.Location = new System.Drawing.Point(12, 282);
this.vsSoundVolume.Name = "vsSoundVolume";
this.vsSoundVolume.Size = new System.Drawing.Size(213, 20);
this.vsSoundVolume.TabIndex = 117;
this.vsSoundVolume.TabStop = false;
this.vsSoundVolume.VolumeChanged += new System.EventHandler(this.vsSoundVolume_VolumeChanged);
this.vsSoundVolume.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.vsSoundVolume_MouseWheel);
//
// cbAddToList
//
this.cbAddToList.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.cbAddToList.AutoSize = true;
this.cbAddToList.Location = new System.Drawing.Point(12, 197);
this.cbAddToList.Margin = new System.Windows.Forms.Padding(3, 10, 3, 3);
this.cbAddToList.Name = "cbAddToList";
this.cbAddToList.Size = new System.Drawing.Size(72, 17);
this.cbAddToList.TabIndex = 105;
this.cbAddToList.Text = "Add to list";
this.cbAddToList.UseVisualStyleBackColor = true;
this.cbAddToList.CheckedChanged += new System.EventHandler(this.cbAddToList_CheckedChanged);
//
// preview
//
this.preview.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.preview.AutoSize = true;
this.preview.Location = new System.Drawing.Point(161, 161);
this.preview.Name = "preview";
this.preview.Size = new System.Drawing.Size(75, 23);
this.preview.TabIndex = 104;
this.preview.Text = "Preview";
this.preview.UseVisualStyleBackColor = true;
this.preview.Click += new System.EventHandler(this.preview_Click);
//
// btnCreateWAV
//
this.btnCreateWAV.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCreateWAV.Location = new System.Drawing.Point(141, 360);
this.btnCreateWAV.Margin = new System.Windows.Forms.Padding(3, 10, 3, 3);
this.btnCreateWAV.Name = "btnCreateWAV";
this.btnCreateWAV.Size = new System.Drawing.Size(100, 23);
this.btnCreateWAV.TabIndex = 112;
this.btnCreateWAV.Text = "Create WAV";
this.btnCreateWAV.UseVisualStyleBackColor = true;
this.btnCreateWAV.Click += new System.EventHandler(this.btnCreateWAV_Click);
//
// label2
//
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 222);
this.label2.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(76, 13);
this.label2.TabIndex = 109;
this.label2.Text = "Keys (optional)";
//
// tbKeys
//
this.tbKeys.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.tbKeys.Location = new System.Drawing.Point(12, 238);
this.tbKeys.Name = "tbKeys";
this.tbKeys.ReadOnly = true;
this.tbKeys.ShortcutsEnabled = false;
this.tbKeys.Size = new System.Drawing.Size(213, 20);
this.tbKeys.TabIndex = 106;
this.tbKeys.Enter += new System.EventHandler(this.tbKeys_Enter);
this.tbKeys.Leave += new System.EventHandler(this.tbKeys_Leave);
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.Location = new System.Drawing.Point(247, 360);
this.btnCancel.Margin = new System.Windows.Forms.Padding(3, 10, 3, 3);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 113;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// keysTimer
//
this.keysTimer.Tick += new System.EventHandler(this.keysTimer_Tick);
//
// nSoundVolume
//
this.nSoundVolume.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.nSoundVolume.Location = new System.Drawing.Point(231, 282);
this.nSoundVolume.Name = "nSoundVolume";
this.nSoundVolume.Size = new System.Drawing.Size(39, 20);
this.nSoundVolume.TabIndex = 108;
this.nSoundVolume.Value = new decimal(new int[] {
100,
0,
0,
0});
this.nSoundVolume.ValueChanged += new System.EventHandler(this.nSoundVolume_ValueChanged);
//
// label5
//
this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(12, 310);
this.label5.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(138, 13);
this.label5.TabIndex = 115;
this.label5.Text = "Restrict to a certain window";
//
// cbWindows
//
this.cbWindows.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.cbWindows.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.cbWindows.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
this.cbWindows.FormattingEnabled = true;
this.cbWindows.Location = new System.Drawing.Point(12, 326);
this.cbWindows.Name = "cbWindows";
this.cbWindows.Size = new System.Drawing.Size(213, 21);
this.cbWindows.TabIndex = 110;
//
// btnReloadWindows
//
this.btnReloadWindows.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnReloadWindows.Image = ((System.Drawing.Image)(resources.GetObject("btnReloadWindows.Image")));
this.btnReloadWindows.Location = new System.Drawing.Point(231, 325);
this.btnReloadWindows.Name = "btnReloadWindows";
this.btnReloadWindows.Size = new System.Drawing.Size(22, 23);
this.btnReloadWindows.TabIndex = 111;
this.btnReloadWindows.UseVisualStyleBackColor = true;
this.btnReloadWindows.Click += new System.EventHandler(this.btnReloadWindows_Click);
//
// label4
//
this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(12, 147);
this.label4.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(42, 13);
this.label4.TabIndex = 114;
this.label4.Text = "Gender";
//
// cbGender
//
this.cbGender.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.cbGender.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbGender.FormattingEnabled = true;
this.cbGender.Items.AddRange(new object[] {
"Male",
"Female"});
this.cbGender.Location = new System.Drawing.Point(12, 163);
this.cbGender.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.cbGender.Name = "cbGender";
this.cbGender.Size = new System.Drawing.Size(120, 21);
this.cbGender.TabIndex = 103;
this.cbGender.SelectedIndexChanged += new System.EventHandler(this.cbGender_SelectedIndexChanged);
//
// clearHotkey
//
this.clearHotkey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.clearHotkey.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.clearHotkey.ForeColor = System.Drawing.Color.Red;
this.clearHotkey.Location = new System.Drawing.Point(231, 237);
this.clearHotkey.Name = "clearHotkey";
this.clearHotkey.Size = new System.Drawing.Size(22, 22);
this.clearHotkey.TabIndex = 107;
this.clearHotkey.Text = "X";
this.clearHotkey.UseVisualStyleBackColor = true;
this.clearHotkey.Click += new System.EventHandler(this.clearHotkey_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 58);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(28, 13);
this.label1.TabIndex = 102;
this.label1.Text = "Text";
//
// tbText
//
this.tbText.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.tbText.Location = new System.Drawing.Point(12, 74);
this.tbText.Multiline = true;
this.tbText.Name = "tbText";
this.tbText.Size = new System.Drawing.Size(310, 65);
this.tbText.TabIndex = 101;
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(9, 13);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(35, 13);
this.label6.TabIndex = 118;
this.label6.Text = "Name";
//
// tbName
//
this.tbName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.tbName.Location = new System.Drawing.Point(12, 29);
this.tbName.Multiline = true;
this.tbName.Name = "tbName";
this.tbName.Size = new System.Drawing.Size(310, 20);
this.tbName.TabIndex = 100;
//
// stopPreview
//
this.stopPreview.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.stopPreview.AutoSize = true;
this.stopPreview.Location = new System.Drawing.Point(242, 162);
this.stopPreview.Name = "stopPreview";
this.stopPreview.Size = new System.Drawing.Size(80, 23);
this.stopPreview.TabIndex = 119;
this.stopPreview.Text = "Stop Preview";
this.stopPreview.UseVisualStyleBackColor = true;
this.stopPreview.Click += new System.EventHandler(this.stopPreview_Click);
//
// btnPlayThroughMic
//
this.btnPlayThroughMic.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnPlayThroughMic.AutoSize = true;
this.btnPlayThroughMic.Location = new System.Drawing.Point(161, 190);
this.btnPlayThroughMic.Name = "btnPlayThroughMic";
this.btnPlayThroughMic.Size = new System.Drawing.Size(161, 23);
this.btnPlayThroughMic.TabIndex = 120;
this.btnPlayThroughMic.Text = "Play Through Mic";
this.btnPlayThroughMic.UseVisualStyleBackColor = true;
this.btnPlayThroughMic.Click += new System.EventHandler(this.btnPlayThroughMic_Click);
//
// TextToSpeechForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(334, 394);
this.Controls.Add(this.btnPlayThroughMic);
this.Controls.Add(this.stopPreview);
this.Controls.Add(this.tbName);
this.Controls.Add(this.label6);
this.Controls.Add(this.label3);
this.Controls.Add(this.vsSoundVolume);
this.Controls.Add(this.cbAddToList);
this.Controls.Add(this.preview);
this.Controls.Add(this.btnCreateWAV);
this.Controls.Add(this.label2);
this.Controls.Add(this.tbKeys);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.nSoundVolume);
this.Controls.Add(this.label5);
this.Controls.Add(this.cbWindows);
this.Controls.Add(this.btnReloadWindows);
this.Controls.Add(this.label4);
this.Controls.Add(this.cbGender);
this.Controls.Add(this.clearHotkey);
this.Controls.Add(this.label1);
this.Controls.Add(this.tbText);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(350, 385);
this.Name = "TextToSpeechForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Text-to-speech";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.TextToSpeechForm_FormClosing);
this.Load += new System.EventHandler(this.TTS_Load);
((System.ComponentModel.ISupportInitialize)(this.nSoundVolume)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label3;
private NAudio.Gui.VolumeSlider vsSoundVolume;
private System.Windows.Forms.CheckBox cbAddToList;
private System.Windows.Forms.Button preview;
private System.Windows.Forms.Button btnCreateWAV;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox tbKeys;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Timer keysTimer;
private System.Windows.Forms.NumericUpDown nSoundVolume;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.ComboBox cbWindows;
private System.Windows.Forms.Button btnReloadWindows;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.ComboBox cbGender;
private System.Windows.Forms.Button clearHotkey;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox tbText;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox tbName;
private System.Windows.Forms.Button stopPreview;
private System.Windows.Forms.Button btnPlayThroughMic;
}
}

270
src/TextToSpeechForm.cs Executable file
View File

@ -0,0 +1,270 @@
using NAudio.Wave;
using System;
using System.Diagnostics;
using System.IO;
using System.Speech.AudioFormat;
using System.Speech.Synthesis;
using System.Windows.Forms;
namespace JNSoundboard
{
public partial class TextToSpeechForm : Form
{
MainForm mainForm;
SpeechSynthesizer synth = new SpeechSynthesizer();
Prompt previewPrompt;
internal static int lastGenderIndex = 0;
internal static bool lastAddToListChecked = false;
internal static string lastWindow = "";
internal static float lastSoundVolume = 1;
public VoiceGender Gender { get; set; } = VoiceGender.Neutral;
public TextToSpeechForm()
{
InitializeComponent();
}
private void TTS_Load(object sender, EventArgs e)
{
mainForm = Application.OpenForms[0] as MainForm;
cbGender.SelectedIndex = lastGenderIndex;
Gender = (VoiceGender)cbGender.SelectedIndex + 1; //1 = Male; 2 = Female
cbAddToList.Checked = lastAddToListChecked;
tbKeys.Enabled = lastAddToListChecked;
clearHotkey.Enabled = lastAddToListChecked;
cbWindows.Enabled = lastAddToListChecked;
btnReloadWindows.Enabled = lastAddToListChecked;
vsSoundVolume.Enabled = lastAddToListChecked;
nSoundVolume.Enabled = lastAddToListChecked;
vsSoundVolume.Volume = lastSoundVolume;
Helper.getWindows(cbWindows);
Helper.selectWindow(cbWindows, lastWindow);
}
private void btnCreateWAV_Click(object sender, EventArgs e)
{
string[] fileLocation;
if (!string.IsNullOrWhiteSpace(tbText.Text))
{
//show dialog
var diag = new SaveFileDialog();
diag.Filter = "WAV files|*.wav";
if (diag.ShowDialog() == DialogResult.OK)
{
fileLocation = new string[] { diag.FileName };
}
else
{
return;
}
}
else
{
MessageBox.Show("No text entered");
return;
}
//create file
synth.SelectVoiceByHints(Gender, VoiceAge.NotSet);
synth.SetOutputToWaveFile(fileLocation[0]);
PromptBuilder builder = new PromptBuilder();
builder.AppendText(tbText.Text);
synth.Speak(builder);
synth.Dispose();
synth = null;
if (cbAddToList.Checked)
{
//add to list
if (!Helper.stringToKeysArray(tbKeys.Text, out Keyboard.Keys[] keysArray, out _)) keysArray = new Keyboard.Keys[] { };
string windowText = (cbWindows.SelectedIndex > 0) ? cbWindows.Text : "";
mainForm.soundHotkeys.Add(new XMLSettings.SoundHotkey(tbName.Text, keysArray, vsSoundVolume.Volume, windowText, fileLocation));
var newItem = new ListViewItem(tbKeys.Text);
newItem.SubItems.Add(vsSoundVolume.Volume == 1 ? "" : Helper.linearVolumeToString(vsSoundVolume.Volume));
newItem.SubItems.Add(windowText);
newItem.SubItems.Add(fileLocation[0]);
newItem.ToolTipText = Helper.getFileNamesTooltip(fileLocation);
mainForm.lvKeySounds.Items.Add(newItem);
mainForm.sortHotkeys();
//remember last used options
lastWindow = cbWindows.Text;
lastSoundVolume = vsSoundVolume.Volume;
}
//remember last used options
lastGenderIndex = cbGender.SelectedIndex;
lastAddToListChecked = cbAddToList.Checked;
MessageBox.Show("Saved: " + fileLocation[0]);
this.Close(); //don't know if this wasn't added before or if I deleted it or what...
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (previewPrompt != null) StopPreview();
this.Close();
}
private void tbKeys_Enter(object sender, EventArgs e)
{
keysTimer.Enabled = true;
}
private void tbKeys_Leave(object sender, EventArgs e)
{
keysTimer.Enabled = false;
keysTimer.Interval = 100;
}
int lastAmountPressed = 0;
private void keysTimer_Tick(object sender, EventArgs e)
{
keysTimer.Interval = 10; //lowering the interval to avoid missing key presses (e.g. when an input is corrected)
var keysData = Keyboard.getKeys(lastAmountPressed, tbKeys.Text);
lastAmountPressed = keysData.Item1;
tbKeys.Text = keysData.Item2;
}
private void clearHotkey_Click(object sender, EventArgs e)
{
tbKeys.Text = "";
}
private void preview_Click(object sender, EventArgs e)
{
StopPreview();
if (!string.IsNullOrWhiteSpace(tbText.Text))
{
synth.SelectVoiceByHints(Gender, VoiceAge.NotSet);
previewPrompt = synth.SpeakAsync(tbText.Text);
}
}
private void cbGender_SelectedIndexChanged(object sender, EventArgs e)
{
Gender = (VoiceGender)cbGender.SelectedIndex + 1; //1 = Male; 2 = Female
}
private void stopPreview_Click(object sender, EventArgs e)
{
StopPreview();
}
private void StopPreview()
{
if (synth.State == SynthesizerState.Speaking) synth.SpeakAsyncCancel(previewPrompt);
}
private void btnReloadWindows_Click(object sender, EventArgs e)
{
Helper.getWindows(cbWindows);
}
private void cbAddToList_CheckedChanged(object sender, EventArgs e)
{
tbKeys.Enabled = cbAddToList.Checked;
clearHotkey.Enabled = cbAddToList.Checked;
cbWindows.Enabled = cbAddToList.Checked;
btnReloadWindows.Enabled = cbAddToList.Checked;
vsSoundVolume.Enabled = cbAddToList.Checked;
nSoundVolume.Enabled = cbAddToList.Checked;
}
private bool volumeChangedBySlider = false;
private bool volumeChangedByField = false;
public void vsSoundVolume_VolumeChanged(object sender, EventArgs e)
{
//prevent infinite or skipped changes
if (volumeChangedByField)
{
volumeChangedByField = false;
return;
}
volumeChangedBySlider = true;
nSoundVolume.Value = Helper.linearVolumeToInteger(vsSoundVolume.Volume);
}
public void vsSoundVolume_MouseWheel(object sender, MouseEventArgs e)
{
vsSoundVolume.Volume = Helper.getNewSoundVolume(vsSoundVolume.Volume, e.Delta);
}
public void nSoundVolume_ValueChanged(object sender, EventArgs e)
{
//prevent infinite or skipped changes
if (volumeChangedBySlider)
{
volumeChangedBySlider = false;
return;
}
volumeChangedByField = true;
vsSoundVolume.Volume = (float)(nSoundVolume.Value / 100);
}
MemoryStream ms;
NAudio.Wave.RawSourceWaveStream rsws;
SpeechAudioFormatInfo synthFormat;
private void btnPlayThroughMic_Click(object sender, EventArgs e)
{
if (synthFormat == null)
{
synthFormat = new SpeechAudioFormatInfo(44100, AudioBitsPerSample.Sixteen, AudioChannel.Mono);//SpeechAudioFormatInfo(EncodingFormat.Pcm, 88200, 16, 1, 16000, 2, null);
}
ms?.Dispose();
rsws?.Dispose();
ms = new MemoryStream();
synth.SetOutputToWaveStream(ms);
synth.Speak(tbText.Text);
rsws = new RawSourceWaveStream(ms, WaveFormat.CreateIeeeFloatWaveFormat(44100, 2));
//using (RawSourceWaveStream rsws = new RawSourceWaveStream(ms, WaveFormat.CreateIeeeFloatWaveFormat(44100, 2)))// new WaveFormat(41000, 16, 1)))
//using (NAudio.Wave.WaveFileReader wfr = new NAudio.Wave.WaveFileReader(ms))
mainForm.stopPlayback();
mainForm.playSound(rsws, 1, MainForm.VolumeType.Private);
mainForm.playSound(rsws, 1, MainForm.VolumeType.Public);
//wfr = new NAudio.Wave.WaveFileReader(ms);
}
private void TextToSpeechForm_FormClosing(object sender, FormClosingEventArgs e)
{
ms?.Dispose();
rsws?.Dispose();
}
}
}

6309
src/TextToSpeechForm.resx Executable file

File diff suppressed because it is too large Load Diff

263
src/XMLSettings.cs Executable file
View File

@ -0,0 +1,263 @@
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
namespace JNSoundboard
{
public class XMLSettings
{
readonly static SoundboardSettings DEFAULT_SOUNDBOARD_SETTINGS = new SoundboardSettings(new Keyboard.Keys[] { }, new LoadXMLFile[] { new LoadXMLFile(new Keyboard.Keys[] { }, "") }, false, false, true, true, true, 1, 1, false, new Keyboard.Keys { }, "", "", "", "", "");
internal static SoundboardSettings soundboardSettings = new SoundboardSettings();
public const int MaxVolume = 5;
//saving XML files like this makes the XML messy, but it works
#region Keys and sounds settings
public class SoundHotkey
{
public string SoundName;
public Keyboard.Keys[] Keys;
public float SoundVolume;
public string WindowTitle;
public string[] SoundLocations;
public SoundHotkey() { }
public SoundHotkey(string soundName, Keyboard.Keys[] keys, float soundVolume, string windowTitle, string[] soundLocations)
{
SoundName = soundName;
Keys = keys;
SoundVolume = soundVolume;
WindowTitle = windowTitle;
SoundLocations = soundLocations;
}
}
[Serializable]
public class Settings
{
public SoundHotkey[] SoundHotkeys;
public Settings() { }
public Settings(SoundHotkey[] soundHotkeys)
{
SoundHotkeys = soundHotkeys;
}
}
#endregion
#region Soundboard settings
public class LoadXMLFile
{
public Keyboard.Keys[] Keys;
public string XMLLocation;
public LoadXMLFile() { }
public LoadXMLFile(Keyboard.Keys[] keys, string xmlLocation)
{
Keys = keys;
XMLLocation = xmlLocation;
}
}
[Serializable]
public class SoundboardSettings
{
public Keyboard.Keys AutoPushToTalkKey;
public Keyboard.Keys[] StopSoundKeys;
public LoadXMLFile[] LoadXMLFiles;
public bool StartWithWindows, StartMinimised, MinimiseToTray, EnableHotkeys, EnableLoopback, EnableAutoPushToTalk;
public string AutoPushToTalkWindow, LastPlaybackDevice, LastPlaybackDevice2, LastLoopbackDevice, LastXMLFile;
public float PrivateVolume;
public float PublicVolume;
public SoundboardSettings() { }
public SoundboardSettings(Keyboard.Keys[] stopSoundKeys, LoadXMLFile[] loadXMLFiles, bool startWithWindows, bool startMinimised, bool minimiseToTray, bool enableHotkeys, bool enableLoopback, float privateVolume, float publicVolume,
bool enableAutoPushToTalk, Keyboard.Keys autoPushToTalkKey, string autoPushToTalkWindow, string lastPlaybackDevice, string lastPlaybackDevice2, string lastLoopbackDevice, string lastXMLFile)
{
StopSoundKeys = stopSoundKeys;
LoadXMLFiles = loadXMLFiles;
StartWithWindows = startWithWindows;
StartMinimised = startMinimised;
MinimiseToTray = minimiseToTray;
EnableHotkeys = enableHotkeys;
EnableLoopback = enableLoopback;
PrivateVolume = privateVolume;
PublicVolume = publicVolume;
EnableAutoPushToTalk = enableAutoPushToTalk;
AutoPushToTalkKey = autoPushToTalkKey;
AutoPushToTalkWindow = autoPushToTalkWindow;
LastPlaybackDevice = lastPlaybackDevice;
LastPlaybackDevice2 = lastPlaybackDevice2;
LastLoopbackDevice = lastLoopbackDevice;
LastXMLFile = lastXMLFile;
}
}
#endregion
internal static void WriteXML(object kl, string xmlLocation)
{
XmlSerializer serializer = new XmlSerializer(kl.GetType());
using (MemoryStream memStream = new MemoryStream())
{
using (StreamWriter stream = new StreamWriter(memStream, Encoding.Unicode))
{
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
using (var writer = XmlWriter.Create(stream, settings))
{
var emptyNamepsaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
serializer.Serialize(writer, kl, emptyNamepsaces);
int count = (int)memStream.Length;
byte[] arr = new byte[count];
memStream.Seek(0, SeekOrigin.Begin);
memStream.Read(arr, 0, count);
using (BinaryWriter binWriter = new BinaryWriter(File.Open(xmlLocation, FileMode.Create)))
{
binWriter.Write(arr);
}
}
}
}
}
internal static object ReadXML(Type type, string xmlLocation)
{
var serializer = new XmlSerializer(type);
using (var reader = XmlReader.Create(xmlLocation))
{
if (serializer.CanDeserialize(reader))
{
return serializer.Deserialize(reader);
}
else return null;
}
}
internal static void SaveSoundboardSettingsXML()
{
//a proper mitigation technique for rapid calls to this function should be implemented
try { WriteXML(soundboardSettings, Path.GetDirectoryName(Application.ExecutablePath) + "\\settings.xml"); }
catch { }
}
internal static void LoadSoundboardSettingsXML()
{
string filePath = Path.GetDirectoryName(Application.ExecutablePath) + "\\settings.xml";
if (File.Exists(filePath))
{
try
{
SoundboardSettings settings = (SoundboardSettings)ReadXML(typeof(SoundboardSettings), filePath);
bool settingsInvalid = false;
//validation start
if (settings.StopSoundKeys == null)
{
settings.StopSoundKeys = new Keyboard.Keys[] { };
settingsInvalid = true;
}
if (settings.LoadXMLFiles == null)
{
settings.LoadXMLFiles = new LoadXMLFile[] { };
settingsInvalid = true;
}
if (settings.AutoPushToTalkWindow == null)
{
settings.AutoPushToTalkWindow = "";
settingsInvalid = true;
}
if (settings.LastPlaybackDevice == null)
{
settings.LastPlaybackDevice = "";
settingsInvalid = true;
}
if (settings.LastPlaybackDevice2 == null)
{
settings.LastPlaybackDevice2 = "";
settingsInvalid = true;
}
if (settings.LastLoopbackDevice == null)
{
settings.LastLoopbackDevice = "";
settingsInvalid = true;
}
if (settings.LastXMLFile == null)
{
settings.LastXMLFile = "";
settingsInvalid = true;
}
if (settings.PrivateVolume < 0)
{
settings.PrivateVolume = 0;
settingsInvalid = true;
}
else if (settings.PrivateVolume > MaxVolume)
{
settings.PrivateVolume = MaxVolume;
settingsInvalid = true;
}
if (settings.PublicVolume < 0)
{
settings.PublicVolume = 0;
settingsInvalid = true;
}
else if (settings.PublicVolume > MaxVolume)
{
settings.PublicVolume = MaxVolume;
settingsInvalid = true;
}
//validation end
soundboardSettings = settings;
if (settingsInvalid)
{
//recreate settings.xml with the corrected values
SaveSoundboardSettingsXML();
}
}
catch
{
MessageBox.Show("Settings file invalid, using default settings");
WriteXML(DEFAULT_SOUNDBOARD_SETTINGS, filePath);
soundboardSettings = DEFAULT_SOUNDBOARD_SETTINGS;
}
}
else
{
WriteXML(DEFAULT_SOUNDBOARD_SETTINGS, filePath);
soundboardSettings = DEFAULT_SOUNDBOARD_SETTINGS;
}
}
}
}

BIN
src/jn-icon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

4
src/packages.config Executable file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NAudio" version="1.10.0" targetFramework="net46" />
</packages>

BIN
src/reload.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B