This will be a draft until more testing can be done and the refactor is seen as beneficial.
The main aim of this PR is to have the volume/mute indicators on the MIDI controller react to outside input. For example, if I change the volume manually in the Windows Volume Mixer, the indicators on my controller should show the new volume that has been set.
This PR achieves that (with less code than before!) but it became apparent that a refactor of the way we handle audio devices and Windows Mixer entries would be a good move.
Main changes
MIDI controller now reacts to external volume/mute changes
AudioDevice is gone
MixerSession is gone
New AudioDeviceWatcher that tracks the active audio devices and Windows Mixer sessions via events
New Assignment which provides a unified interface for Fader instances to interact with
Hugely simplified and optimised pop-up code and speed
Simplified Fader a little bit due to use of Assignment instances
Simplified MidiDevice a little bit due to use of Assignment instances
What was the point of a refactor?
The #1 target was to remove the constant refreshing and duplication of MixerSession instances which would create many internal MMDevice instances. This was causing a small memory leak, but the main drawback was that it was confusing to work with after a good year-or-so of small edits and tweaks.
The AudioDeviceWatcher uses events to keep an up-to-date list of both audio devices and Windows Mixer entries with no need for manual refreshing. This means that not only are we no longer spawning MMDevice instances where we don't need to, but also that the absolute latest state is always available for viewing in places like the pop-up. This means it's lightning fast, simpler, and has no memory leaks! In fact, AudioDeviceWatcher even keeps track of the current default audio device, meaning we could add an option that always controls your default!
There was also a lot of code that traversed the various "types" of MixerSession: Master, Application, SystemSounds, and Focus. For this, we've created a new Assignment class which provides a consistent interface that things like Fader can use to reliably get/set volumes/mutes (etc) without having to worry about the source.
On top of this, our Assignment instances register to events from the AudioDeviceWatcher and can feed external volume/mute/etc changes back to faders, meaning we can now keep the MIDI controller up-to-date with whatever state the machine is in without having to constantly check!
Is everything working?
I'll add a list here to work through and will include anything else that pops up.
Currently, a couple of things haven't been added in:
[x] ~AssignInactive - This is so we can still load in that Fader A is assigned to Application B even if Application B isn't active on boot.~
[x] ~Record button opening the application - All that's really needed here is to store the application path in the Assignment if it's available.~
[x] ~System Sounds - It has a raw name at the moment.~
Building and testing
Because of the nature of Visual Studio, it may be necessary to clean your solution before you try using this branch.
This will be a draft until more testing can be done and the refactor is seen as beneficial.
The main aim of this PR is to have the volume/mute indicators on the MIDI controller react to outside input. For example, if I change the volume manually in the Windows Volume Mixer, the indicators on my controller should show the new volume that has been set.
This PR achieves that (with less code than before!) but it became apparent that a refactor of the way we handle audio devices and Windows Mixer entries would be a good move.
Main changes
AudioDevice
is goneMixerSession
is goneAudioDeviceWatcher
that tracks the active audio devices and Windows Mixer sessions via eventsAssignment
which provides a unified interface forFader
instances to interact withFader
a little bit due to use ofAssignment
instancesMidiDevice
a little bit due to use ofAssignment
instancesWhat was the point of a refactor?
The #1 target was to remove the constant refreshing and duplication of
MixerSession
instances which would create many internalMMDevice
instances. This was causing a small memory leak, but the main drawback was that it was confusing to work with after a good year-or-so of small edits and tweaks.The
AudioDeviceWatcher
uses events to keep an up-to-date list of both audio devices and Windows Mixer entries with no need for manual refreshing. This means that not only are we no longer spawningMMDevice
instances where we don't need to, but also that the absolute latest state is always available for viewing in places like the pop-up. This means it's lightning fast, simpler, and has no memory leaks! In fact,AudioDeviceWatcher
even keeps track of the current default audio device, meaning we could add an option that always controls your default!There was also a lot of code that traversed the various "types" of
MixerSession
:Master
,Application
,SystemSounds
, andFocus
. For this, we've created a newAssignment
class which provides a consistent interface that things likeFader
can use to reliably get/set volumes/mutes (etc) without having to worry about the source.On top of this, our
Assignment
instances register to events from theAudioDeviceWatcher
and can feed external volume/mute/etc changes back to faders, meaning we can now keep the MIDI controller up-to-date with whatever state the machine is in without having to constantly check!Is everything working?
I'll add a list here to work through and will include anything else that pops up. Currently, a couple of things haven't been added in:
AssignInactive
- This is so we can still load in that Fader A is assigned to Application B even if Application B isn't active on boot.~Assignment
if it's available.~Building and testing
Because of the nature of Visual Studio, it may be necessary to clean your solution before you try using this branch.
bin
andobj
folders insideNK2Tray
folder