Skip to content

Commit fdb1e44

Browse files
authored
Merge pull request #3 from arithex/work
Work
2 parents b61ed74 + 50e8131 commit fdb1e44

10 files changed

Lines changed: 186 additions & 228 deletions

File tree

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2021 arithex
3+
Copyright (c) 2021, Airtex Industries
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ This is still just a crude prototype -- but I'd like to get feedback and hear id
1313

1414
## Change Log ##
1515

16+
#### v1.1.2021.522:
17+
18+
- Allow sound effects to be overridden with custom wav files.
19+
- Also allow mouse wheelbutton to mapped to a keyboard scancode --
20+
- only suitable for press-and-hold keys (because a short-tap will always set throttle to 50% and reset fov).
21+
- but works great for the `SimHotasShift` callback, to take advantage of secondary stick buttons without sacrificing one of them.
22+
- eg: `<add key="ScancodeForMouseWheelButton" value="0x39"/><!-- [spacebar] -->`
23+
1624
#### v1.1:
1725

1826
- Implemented rudimentary tracking of throttle-lever position, and audible feedback when your throttle hits the minimum/maximum extent (and push-through afterburner detent).
@@ -96,4 +104,4 @@ That should be more stable, supportable, and allow the mousewheel to return to i
96104
Other changes in progress:
97105

98106
- use BMS shared memory interface to only hook the mouse while in 3D pit
99-
- optional overlay to display throttle position, rpm, ftit, brake
107+
- optional overlay to display throttle position, rpm, ftit, brake, etc

src/App.config

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,14 @@
3838
(optional) Audio feedback for passing through AB detent, and hitting min/max extent range of throttle.
3939
Note: currently these absolute positions are estimated, and may not always be reliable.
4040
-->
41-
<add key="IdleStopSound" value="throttleExtent"/>
42-
<add key="BurnerDetentUpSound" value="throttleDetent"/>
43-
<add key="BurnerDetentDownSound" value="throttleDetent"/>
44-
<add key="MaxBurnerSound" value="throttleExtent"/>
41+
<add key="IdleStopSound" value="res://Sounds/throttleExtent.wav"/>
42+
<add key="BurnerDetentUpSound" value="res://Sounds/throttleDetent.wav"/>
43+
<add key="BurnerDetentDownSound" value="res://Sounds/throttleDetent.wav"/>
44+
<add key="MaxBurnerSound" value="res://Sounds/throttleExtent.wav"/>
4545

4646
<!--
4747
(bonus-feature) Remap mouse x-buttons to (unshifted) keybd scancodes.. because why not.
48+
List of hex scancodes: https://gist.github.com/arithex/3e953d1eb096afe58ce05ba6846493e4
4849
-->
4950
<add key="ScancodeForMouseXButton1" value="0xC7"/><!--[Home]: UHF push-to-talk-->
5051
<add key="ScancodeForMouseXButton2" value="0xCF"/><!--[End]: VHF push-to-talk-->

src/Config.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,24 @@ public static string MaxBurnerSound
138138
}
139139
}
140140

141+
//----------------------------------------
142+
public static byte? ScancodeForMouseWheelButton
143+
{
144+
get
145+
{
146+
string configValue = ConfigurationManager.AppSettings["ScancodeForMouseWheelButton"];
147+
148+
if (String.IsNullOrEmpty(configValue))
149+
return null;
150+
151+
uint value = _ParseUInt32(configValue);
152+
if (value > 255)
153+
throw new ConfigurationErrorsException("Scancode must be in range [0x00-0xFF]");
154+
155+
return (byte)value;
156+
}
157+
}
158+
141159
//----------------------------------------
142160
public static byte? ScancodeForMouseXButton1
143161
{

src/DragWheel.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<Reference Include="Microsoft.CSharp" />
4242
</ItemGroup>
4343
<ItemGroup>
44+
<Compile Include="ResourceLoader.cs" />
4445
<Compile Include="Sounds.cs" />
4546
<Compile Include="Config.cs" />
4647
<Compile Include="ThrottleAbsolutePosTracker.cs" />
@@ -59,7 +60,6 @@
5960
<ItemGroup>
6061
<EmbeddedResource Include="Sounds\throttleDetent.wav" />
6162
<EmbeddedResource Include="Sounds\throttleExtent.wav" />
62-
<EmbeddedResource Include="Sounds.resx" />
6363
</ItemGroup>
6464
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
6565
</Project>

src/Properties/AssemblyInfo.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
[assembly: AssemblyConfiguration("")]
1313
[assembly: AssemblyCompany("")]
1414
[assembly: AssemblyProduct("DragWheel")]
15-
[assembly: AssemblyCopyright("Copyright © Airtex Industries 2021")]
15+
[assembly: AssemblyCopyright("Copyright © 2021, Airtex Industries")]
1616
[assembly: AssemblyTrademark("")]
1717
[assembly: AssemblyCulture("")]
1818

@@ -35,8 +35,8 @@
3535
// You can specify all the values or you can default the Build and Revision Numbers
3636
// by using the '*' as shown below:
3737
// [assembly: AssemblyVersion("1.0.*")]
38-
[assembly: AssemblyVersion("1.1.2021.418")]
39-
[assembly: AssemblyFileVersion("1.1.2021.418")]
38+
[assembly: AssemblyVersion("1.1.2021.522")]
39+
[assembly: AssemblyFileVersion("1.1.2021.522")]
4040

4141
// Don't probe satellites for en-US resources.
4242
[assembly: NeutralResourcesLanguageAttribute("en-US")]

src/RawInputMouseHandler.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace DragWheel
55
internal class RawInputMouseHandler
66
{
77
int? _configuredMouseButton;
8-
byte? _xbutton1Scancode, _xbutton2Scancode;
8+
byte? _wheelbuttonScancode, _xbutton1Scancode, _xbutton2Scancode;
99

1010
bool[] _mouseButtons;
1111
int _dx, _dy;
@@ -26,6 +26,7 @@ public RawInputMouseHandler( IntPtr hWnd )
2626
DragActivated = false;
2727

2828
_configuredMouseButton = Config.MouseButton;
29+
_wheelbuttonScancode = Config.ScancodeForMouseWheelButton;
2930
_xbutton1Scancode = Config.ScancodeForMouseXButton1;
3031
_xbutton2Scancode = Config.ScancodeForMouseXButton2;
3132

@@ -83,6 +84,11 @@ void OnMouseButton( int buttonId, bool isPressed )
8384
ThrottleAbsolutePosTracker.TrackMiddleClick(isPressed, Environment.TickCount);
8485

8586
// Bonus feature: map mouse x-buttons to keyboard scancodes.
87+
if (_wheelbuttonScancode.HasValue && buttonId == 2)
88+
{
89+
Console.WriteLine("WB key [{0:X}]: {1}", _wheelbuttonScancode.Value, isPressed);
90+
Win32.SendInput.SendKeystroke(_wheelbuttonScancode.Value, isPressed);
91+
}
8692
if (_xbutton1Scancode.HasValue && buttonId == 3)
8793
{
8894
Console.WriteLine("XB1 key [{0:X}]: {1}", _xbutton1Scancode.Value, isPressed);

src/ResourceLoader.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
using System.IO;
3+
using System.Reflection;
4+
using System.Resources;
5+
using System.Globalization;
6+
7+
namespace DragWheel
8+
{
9+
internal class ResourceLoader
10+
{
11+
Assembly _currAssem = null;
12+
13+
public ResourceLoader( )
14+
{
15+
_currAssem = Assembly.GetExecutingAssembly();
16+
}
17+
18+
public Stream TryLoadResourceBinary( string name )
19+
{
20+
string resPrefix = @"res://";
21+
22+
if (name.StartsWith(resPrefix))
23+
{
24+
// Convert eg. "res://Sounds/throttleExtent.wav" to "DragWheel.Sounds.throttleExtent.wav"
25+
string defaultNamespace = typeof(ResourceLoader).Namespace;
26+
string resname = defaultNamespace + "." + name.Substring(resPrefix.Length).Replace('/', '.');
27+
28+
return _currAssem.GetManifestResourceStream(resname);
29+
}
30+
else
31+
{
32+
if (File.Exists(name))
33+
return File.OpenRead(name);
34+
35+
return null;
36+
}
37+
}
38+
39+
public string TryLoadResourceUtf8String( string name )
40+
{
41+
Stream stream = TryLoadResourceBinary(name);
42+
if (stream == null)
43+
return null;
44+
45+
using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
46+
{
47+
string text = reader.ReadToEnd();
48+
return text;
49+
}
50+
}
51+
52+
}
53+
}

src/Sounds.cs

Lines changed: 89 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,89 @@
1-
using System;
2-
using System.IO;
3-
using System.Media;
4-
using System.Resources;
5-
6-
namespace DragWheel
7-
{
8-
internal static class Sounds
9-
{
10-
//--------------------------------------------------------------
11-
static SoundPlayer s_playerIdleStop = null;
12-
static SoundPlayer s_playerBurnerDetentUp = null;
13-
static SoundPlayer s_playerBurnerDetentDown = null;
14-
static SoundPlayer s_playerMaxBurner = null;
15-
16-
static Sounds( )
17-
{
18-
ResourceManager resmgr = new ResourceManager(typeof(Sounds));
19-
20-
string soundIdleStop = Config.IdleStopSound;
21-
if (!String.IsNullOrEmpty(soundIdleStop))
22-
{
23-
Stream wavStream = resmgr.GetStream(soundIdleStop);
24-
s_playerIdleStop = new SoundPlayer(wavStream);
25-
}
26-
27-
string soundBurnerDetentUp = Config.BurnerDetentUpSound;
28-
if (!String.IsNullOrEmpty(soundBurnerDetentUp))
29-
{
30-
Stream wavStream = resmgr.GetStream(soundBurnerDetentUp);
31-
s_playerBurnerDetentUp = new SoundPlayer(wavStream);
32-
}
33-
34-
string soundBurnerDetentDown = Config.BurnerDetentDownSound;
35-
if (!String.IsNullOrEmpty(soundBurnerDetentDown))
36-
{
37-
Stream wavStream = resmgr.GetStream(soundBurnerDetentDown);
38-
s_playerBurnerDetentDown = new SoundPlayer(wavStream);
39-
}
40-
41-
string soundMaxBurner = Config.MaxBurnerSound;
42-
if (!String.IsNullOrEmpty(soundMaxBurner))
43-
{
44-
Stream wavStream = resmgr.GetStream(soundMaxBurner);
45-
s_playerMaxBurner = new SoundPlayer(wavStream);
46-
}
47-
}
48-
49-
//----------------------------------------
50-
public static void PlayIdleStop( )
51-
{
52-
if (s_playerIdleStop != null)
53-
s_playerIdleStop.Play();
54-
}
55-
56-
//----------------------------------------
57-
public static void PlayBurnerDetentUp( )
58-
{
59-
if (s_playerBurnerDetentUp != null)
60-
s_playerBurnerDetentUp.Play();
61-
}
62-
63-
//----------------------------------------
64-
public static void PlayBurnerDetentDown( )
65-
{
66-
if (s_playerBurnerDetentDown != null)
67-
s_playerBurnerDetentDown.Play();
68-
}
69-
70-
//----------------------------------------
71-
public static void PlayMaxBurner( )
72-
{
73-
if (s_playerMaxBurner != null)
74-
s_playerMaxBurner.Play();
75-
}
76-
77-
}
78-
79-
//------------------------------------------------------------------
80-
internal static partial class Tests
81-
{
82-
internal static void PlaySound( )
83-
{
84-
Sounds.PlayIdleStop();
85-
Sounds.PlayBurnerDetentUp();
86-
Sounds.PlayBurnerDetentDown();
87-
Sounds.PlayMaxBurner();
88-
}
89-
}
90-
}
1+
using System;
2+
using System.IO;
3+
using System.Media;
4+
5+
namespace DragWheel
6+
{
7+
internal static class Sounds
8+
{
9+
//--------------------------------------------------------------
10+
static SoundPlayer s_playerIdleStop = null;
11+
static SoundPlayer s_playerBurnerDetentUp = null;
12+
static SoundPlayer s_playerBurnerDetentDown = null;
13+
static SoundPlayer s_playerMaxBurner = null;
14+
15+
static Sounds( )
16+
{
17+
ResourceLoader resloader = new ResourceLoader();
18+
19+
string soundIdleStop = Config.IdleStopSound;
20+
if (!String.IsNullOrEmpty(soundIdleStop))
21+
{
22+
Stream wavStream = resloader.TryLoadResourceBinary(soundIdleStop);
23+
s_playerIdleStop = new SoundPlayer(wavStream);
24+
}
25+
26+
string soundBurnerDetentUp = Config.BurnerDetentUpSound;
27+
if (!String.IsNullOrEmpty(soundBurnerDetentUp))
28+
{
29+
Stream wavStream = resloader.TryLoadResourceBinary(soundBurnerDetentUp);
30+
s_playerBurnerDetentUp = new SoundPlayer(wavStream);
31+
}
32+
33+
string soundBurnerDetentDown = Config.BurnerDetentDownSound;
34+
if (!String.IsNullOrEmpty(soundBurnerDetentDown))
35+
{
36+
Stream wavStream = resloader.TryLoadResourceBinary(soundBurnerDetentDown);
37+
s_playerBurnerDetentDown = new SoundPlayer(wavStream);
38+
}
39+
40+
string soundMaxBurner = Config.MaxBurnerSound;
41+
if (!String.IsNullOrEmpty(soundMaxBurner))
42+
{
43+
Stream wavStream = resloader.TryLoadResourceBinary(soundMaxBurner);
44+
s_playerMaxBurner = new SoundPlayer(wavStream);
45+
}
46+
}
47+
48+
//----------------------------------------
49+
public static void PlayIdleStop( )
50+
{
51+
if (s_playerIdleStop != null)
52+
s_playerIdleStop.Play();
53+
}
54+
55+
//----------------------------------------
56+
public static void PlayBurnerDetentUp( )
57+
{
58+
if (s_playerBurnerDetentUp != null)
59+
s_playerBurnerDetentUp.Play();
60+
}
61+
62+
//----------------------------------------
63+
public static void PlayBurnerDetentDown( )
64+
{
65+
if (s_playerBurnerDetentDown != null)
66+
s_playerBurnerDetentDown.Play();
67+
}
68+
69+
//----------------------------------------
70+
public static void PlayMaxBurner( )
71+
{
72+
if (s_playerMaxBurner != null)
73+
s_playerMaxBurner.Play();
74+
}
75+
76+
}
77+
78+
//------------------------------------------------------------------
79+
internal static partial class Tests
80+
{
81+
internal static void PlaySound( )
82+
{
83+
Sounds.PlayIdleStop();
84+
Sounds.PlayBurnerDetentUp();
85+
Sounds.PlayBurnerDetentDown();
86+
Sounds.PlayMaxBurner();
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)