Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audio device picker #2028

Merged
merged 7 commits into from
Jun 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 21 additions & 38 deletions Project-Aurora/Project-Aurora/Profiles/LocalPCInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,61 +35,54 @@ public class LocalPCInformation : Node {
#endregion

#region Audio Properties
private static readonly MMDeviceEnumerator mmDeviceEnumerator = new MMDeviceEnumerator();
private static readonly NAudio.Wave.WaveInEvent waveInEvent = new NAudio.Wave.WaveInEvent();
private static readonly AudioDeviceProxy captureProxy;
private static readonly AudioDeviceProxy renderProxy;

/// <summary>
/// Gets the default endpoint for output (playback) devices e.g. speakers, headphones, etc.
/// This will return null if there are no playback devices available.
/// </summary>
private MMDevice DefaultAudioOutDevice {
private MMDevice CaptureDevice {
get {
try { return mmDeviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Console); }
catch { return null; }
if (captureProxy != null)
captureProxy.DeviceId = Global.Configuration.GSIAudioCaptureDevice;
return captureProxy?.Device;
}
}

/// <summary>
/// Gets the default endpoint for input (recording) devices e.g. microphones.
/// This will return null if there are no recording devices available.
/// </summary>
private MMDevice DefaultAudioInDevice {
private MMDevice RenderDevice {
get {
try { return mmDeviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Capture, Role.Console); }
catch { return null; }
renderProxy.DeviceId = Global.Configuration.GSIAudioRenderDevice;
return renderProxy?.Device;
}
}

/// <summary>
/// Current system volume (as set from the speaker icon)
/// </summary>
// Note: Manually checks if muted to return 0 since this is not taken into account with the MasterVolumeLevelScalar.
public float SystemVolume => SystemVolumeIsMuted ? 0 : DefaultAudioOutDevice?.AudioEndpointVolume.MasterVolumeLevelScalar * 100 ?? 0;
public float SystemVolume => SystemVolumeIsMuted ? 0 : RenderDevice?.AudioEndpointVolume.MasterVolumeLevelScalar * 100 ?? 0;

/// <summary>
/// Gets whether the system volume is muted.
/// </summary>
public bool SystemVolumeIsMuted => DefaultAudioOutDevice?.AudioEndpointVolume.Mute ?? true;
public bool SystemVolumeIsMuted => RenderDevice?.AudioEndpointVolume.Mute ?? true;

/// <summary>
/// The volume level that is being recorded by the default microphone even when muted.
/// </summary>
public float MicrophoneLevel => DefaultAudioInDevice?.AudioMeterInformation.MasterPeakValue * 100 ?? 0;
public float MicrophoneLevel => CaptureDevice?.AudioMeterInformation.MasterPeakValue * 100 ?? 0;

/// <summary>
/// The volume level that is being emitted by the default speaker even when muted.
/// </summary>
public float SpeakerLevel => DefaultAudioOutDevice?.AudioMeterInformation.MasterPeakValue * 100 ?? 0;
public float SpeakerLevel => RenderDevice?.AudioMeterInformation.MasterPeakValue * 100 ?? 0;

/// <summary>
/// The volume level that is being recorded by the default microphone if not muted.
/// </summary>
public float MicLevelIfNotMuted => MicrophoneIsMuted ? 0 : DefaultAudioInDevice?.AudioMeterInformation.MasterPeakValue * 100 ?? 0;
public float MicLevelIfNotMuted => MicrophoneIsMuted ? 0 : CaptureDevice?.AudioMeterInformation.MasterPeakValue * 100 ?? 0;

/// <summary>
/// Gets whether the default microphone is muted.
/// </summary>
public bool MicrophoneIsMuted => DefaultAudioInDevice?.AudioEndpointVolume.Mute ?? true;
public bool MicrophoneIsMuted => CaptureDevice?.AudioEndpointVolume.Mute ?? true;
#endregion

#region Device Properties
Expand Down Expand Up @@ -153,23 +146,13 @@ private MMDevice DefaultAudioInDevice {
/// </summary>
public bool IsDesktopLocked => DesktopUtils.IsDesktopLocked;

static LocalPCInformation() {
void StartStopRecording() {
// We must start recording to be able to capture audio in, but only do this if the user has the option set. Allowing them
// to turn it off will give them piece of mind we're not spying on them and will stop the Windows 10 mic icon appearing.
try {
if (Global.Configuration.EnableAudioCapture)
waveInEvent.StartRecording();
else
waveInEvent.StopRecording();
} catch { }
}
private bool pendingAudioDeviceUpdate = false;

StartStopRecording();
Global.Configuration.PropertyChanged += (sender, e) => {
if (e.PropertyName == "EnableAudioCapture")
StartStopRecording();
};
static LocalPCInformation() {
// Do not create a capture device if audio capture is disabled. Otherwise it will create a mic icon in win 10 and people will think we're spies.
if (Global.Configuration.EnableAudioCapture)
captureProxy = new AudioDeviceProxy(Global.Configuration.GSIAudioCaptureDevice, DataFlow.Capture);
renderProxy = new AudioDeviceProxy(Global.Configuration.GSIAudioRenderDevice, DataFlow.Render);
}
}

Expand Down
1 change: 1 addition & 0 deletions Project-Aurora/Project-Aurora/Project-Aurora.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@
<DependentUpon>Window_ProcessSelection.xaml</DependentUpon>
</Compile>
<Compile Include="Utils\AttachedApplication.cs" />
<Compile Include="Utils\AudioDeviceProxy.cs" />
<Compile Include="Utils\CollectionUtils.cs" />
<Compile Include="Utils\DragBehaviour.cs" />
<Compile Include="Utils\FastMemberExtensions.cs" />
Expand Down
3 changes: 3 additions & 0 deletions Project-Aurora/Project-Aurora/Settings/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,9 @@ public class Configuration : INotifyPropertyChanged

public List<string> ProfileOrder { get; set; } = new List<string>();

public string GSIAudioRenderDevice { get; set; } = AudioDeviceProxy.DEFAULT_DEVICE_ID;
public string GSIAudioCaptureDevice { get; set; } = AudioDeviceProxy.DEFAULT_DEVICE_ID;

public Configuration()
{
//First Time Installs
Expand Down
43 changes: 25 additions & 18 deletions Project-Aurora/Project-Aurora/Settings/Control_Settings.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
xmlns:EnumDeviceKeys="clr-namespace:Aurora.Devices"
xmlns:EnumPercentEffectType="clr-namespace:Aurora.Settings"
xmlns:EnumInteractiveEffects="clr-namespace:Aurora.Profiles.Desktop"
xmlns:EnumValueConverters="clr-namespace:Aurora.Utils"
xmlns:u="clr-namespace:Aurora.Utils"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:Controls="clr-namespace:Aurora.Controls" xmlns:params="http://schemas.codeplex.com/elysium/params" x:Class="Aurora.Settings.Control_Settings"
mc:Ignorable="d"
Expand All @@ -20,12 +20,12 @@
<x:Type TypeName="EnumPercentEffectType:PercentEffectType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<EnumValueConverters:PercentEffectTypeToStringVC x:Key="PercentEffectTypeToStringVC"/>
<u:PercentEffectTypeToStringVC x:Key="PercentEffectTypeToStringVC"/>
<DataTemplate x:Key="PercentEffectTypeTemplate">
<TextBlock Text="{Binding Converter={StaticResource PercentEffectTypeToStringVC}}" />
</DataTemplate>

<EnumValueConverters:DeviceKeysToStringVC x:Key="DeviceKeysToStringVC"/>
<u:DeviceKeysToStringVC x:Key="DeviceKeysToStringVC"/>
<DataTemplate x:Key="DeviceKeys">
<TextBlock Text="{Binding Converter={StaticResource DeviceKeysToStringVC}}" />
</DataTemplate>
Expand All @@ -35,7 +35,7 @@
<x:Type TypeName="EnumPercentEffectType:IdleEffects" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<EnumValueConverters:IdleEffectsToStringVC x:Key="IdleEffectsToStringVC"/>
<u:IdleEffectsToStringVC x:Key="IdleEffectsToStringVC"/>
<DataTemplate x:Key="IdleEffectsTemplate">
<TextBlock Text="{Binding Converter={StaticResource IdleEffectsToStringVC}}" />
</DataTemplate>
Expand All @@ -45,7 +45,7 @@
<x:Type TypeName="local:PreferredKeyboardLocalization" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<EnumValueConverters:KbLayoutToStringVC x:Key="KbLayoutToStringVC"/>
<u:KbLayoutToStringVC x:Key="KbLayoutToStringVC"/>
<DataTemplate x:Key="KbLayoutTemplate">
<TextBlock Text="{Binding Converter={StaticResource KbLayoutToStringVC}}" />
</DataTemplate>
Expand All @@ -55,7 +55,7 @@
<x:Type TypeName="local:PreferredKeyboard" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<EnumValueConverters:KbBrandToStringVC x:Key="KbBrandToStringVC"/>
<u:KbBrandToStringVC x:Key="KbBrandToStringVC"/>
<DataTemplate x:Key="KbBrandTemplate">
<TextBlock Text="{Binding Converter={StaticResource KbBrandToStringVC}}" />
</DataTemplate>
Expand All @@ -65,7 +65,7 @@
<x:Type TypeName="local:PreferredMouse" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<EnumValueConverters:MouseBrandToStringVC x:Key="MouseBrandToStringVC"/>
<u:MouseBrandToStringVC x:Key="MouseBrandToStringVC"/>
<DataTemplate x:Key="MouseBrandTemplate">
<TextBlock Text="{Binding Converter={StaticResource MouseBrandToStringVC}}" />
</DataTemplate>
Expand All @@ -75,7 +75,7 @@
<x:Type TypeName="local:MouseOrientationType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<EnumValueConverters:MouseOrientationToStringVC x:Key="MouseOrientationToStringVC"/>
<u:MouseOrientationToStringVC x:Key="MouseOrientationToStringVC"/>
<DataTemplate x:Key="MouseOrientationTemplate">
<TextBlock Text="{Binding Converter={StaticResource MouseOrientationToStringVC}}" />
</DataTemplate>
Expand All @@ -85,7 +85,7 @@
<x:Type TypeName="local:KeycapType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<EnumValueConverters:KeycapTypeToStringVC x:Key="KeycapTypeToStringVC"/>
<u:KeycapTypeToStringVC x:Key="KeycapTypeToStringVC"/>
<DataTemplate x:Key="KeycapTypeTemplate">
<TextBlock Text="{Binding Converter={StaticResource KeycapTypeToStringVC}}" />
</DataTemplate>
Expand All @@ -95,7 +95,7 @@
<x:Type TypeName="local:BitmapAccuracy" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<EnumValueConverters:BitmapAccuracyToStringVC x:Key="BitmapAccuracyToStringVC"/>
<u:BitmapAccuracyToStringVC x:Key="BitmapAccuracyToStringVC"/>
<DataTemplate x:Key="BitmapAccuracyTemplate">
<TextBlock Text="{Binding Converter={StaticResource BitmapAccuracyToStringVC}}" />
</DataTemplate>
Expand All @@ -105,7 +105,7 @@
<x:Type TypeName="local:AppExitMode" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<EnumValueConverters:appexitmodeToStringVC x:Key="appexitmodeToStringVC"/>
<u:appexitmodeToStringVC x:Key="appexitmodeToStringVC"/>
<DataTemplate x:Key="appexitmodeTemplate">
<TextBlock Text="{Binding Converter={StaticResource appexitmodeToStringVC}}" />
</DataTemplate>
Expand All @@ -115,7 +115,7 @@
<x:Type TypeName="local:ApplicationDetectionMode" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<EnumValueConverters:AppDetectionModeToStringVC x:Key="AppDetectionModeToStringVC"/>
<u:AppDetectionModeToStringVC x:Key="AppDetectionModeToStringVC"/>
<DataTemplate x:Key="AppDetectionModeTemplate">
<TextBlock Text="{Binding Converter={StaticResource AppDetectionModeToStringVC}}" />
</DataTemplate>
Expand All @@ -132,10 +132,10 @@
<TextBlock HorizontalAlignment="Left" Margin="11,230,0,0" TextWrapping="Wrap" Text="Blackout start time:" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="12,254,0,0" TextWrapping="Wrap" Text="Blackout end time:" VerticalAlignment="Top"/>
<CheckBox x:Name="timed_dimming_with_games_checkbox" Content="Apply timed blackout to game events" HorizontalAlignment="Left" Margin="10,205,0,0" VerticalAlignment="Top" Checked="timed_dimming_with_games_checkbox_Checked" Unchecked="timed_dimming_with_games_checkbox_Checked"/>
<ListBox x:Name="excluded_listbox" HorizontalAlignment="Left" Height="199" Margin="512,83,0,-30" VerticalAlignment="Top" Width="160"/>
<TextBlock Text="Excluded Processes" HorizontalAlignment="Left" Margin="512,62,0,0" VerticalAlignment="Top" Width="113"/>
<Button x:Name="excluded_add" Content="Add Process" HorizontalAlignment="Left" Margin="677,83,0,0" VerticalAlignment="Top" Click="excluded_add_Click"/>
<Button x:Name="excluded_remove" Content="Remove Process" HorizontalAlignment="Left" Margin="677,111,0,0" VerticalAlignment="Top" Click="excluded_remove_Click"/>
<ListBox x:Name="excluded_listbox" HorizontalAlignment="Left" Height="199" Margin="512,139,0,0" VerticalAlignment="Top" Width="160"/>
<TextBlock Text="Excluded Processes" HorizontalAlignment="Left" Margin="512,117,0,0" VerticalAlignment="Top" Width="113"/>
<Button x:Name="excluded_add" Content="Add Process" HorizontalAlignment="Left" Margin="677,139,0,0" VerticalAlignment="Top" Click="excluded_add_Click"/>
<Button x:Name="excluded_remove" Content="Remove Process" HorizontalAlignment="Left" Margin="677,167,0,0" VerticalAlignment="Top" Click="excluded_remove_Click"/>
<TextBlock HorizontalAlignment="Left" Margin="12,132,0,0" TextWrapping="Wrap" Text="Keyboard brightness modifier: " VerticalAlignment="Top"/>
<TextBlock x:Name="lblKeyboardBrightness" HorizontalAlignment="Left" Margin="335,132,0,0" TextWrapping="Wrap" Text="0 %" VerticalAlignment="Top"/>
<Slider x:Name="sldKeyboardBrightness" HorizontalAlignment="Left" Margin="180,132,0,0" VerticalAlignment="Top" Width="150" Maximum="1" ValueChanged="sliderPercentages_ValueChanged" Value="{Binding KeyboardBrightness, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Tag="{Binding ElementName=lblKeyboardBrightness, Path=.}"/>
Expand Down Expand Up @@ -170,7 +170,14 @@
<TextBlock Text="Delay:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="278,10,0,0" />
<xctk:IntegerUpDown x:Name="startDelayAmount" Height="22" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="315,8,0,0" Width="69" Minimum="0" Increment="15" ValueChanged="startDelayAmount_ValueChanged" />
<TextBlock Text="sec" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="389,10,0,0" />
<CheckBox Content="Enable Audio Capture (for gamestates)" ToolTip="Aurora only measures the activity level from your microphone for use with the 'LocalPCInfo' game state. None of this data is stored or transmitted elsewhere." HorizontalAlignment="Left" Margin="512,39,0,0" VerticalAlignment="Top" IsChecked="{Binding EnableAudioCapture}" />

<CheckBox Content="Enable Audio Capture for gamestates (restart required)" ToolTip="Aurora only measures the activity level from your microphone for use with the 'LocalPCInfo' game state. None of this data is stored or transmitted elsewhere." HorizontalAlignment="Left" Margin="512,39,0,0" VerticalAlignment="Top" IsChecked="{Binding EnableAudioCapture}" />
<TextBlock Text="GSI Playback Device:" Margin="511,62,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />
<ComboBox SelectedValue="{Binding Path=GSIAudioRenderDevice, Mode=TwoWay}" ItemsSource="{x:Static u:AudioDeviceProxy.PlaybackDevices}" DisplayMemberPath="Value" SelectedValuePath="Key" Margin="632,59,0,0" Width="185" HorizontalAlignment="Left" VerticalAlignment="Top" />
<TextBlock Text="?" TextDecorations="Underline" ToolTip="The audio playback device that will be used for the local PC information state values. Does not affect visualizer layer." ToolTipService.InitialShowDelay="0" Margin="822,62,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />
<TextBlock Text="GSI Recording Device:" Margin="511,89,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />
<ComboBox SelectedValue="{Binding Path=GSIAudioCaptureDevice, Mode=TwoWay}" ItemsSource="{x:Static u:AudioDeviceProxy.RecordingDevices}" DisplayMemberPath="Value" SelectedValuePath="Key" Margin="632,86,0,0" Width="185" HorizontalAlignment="Left" VerticalAlignment="Top" />
<TextBlock Text="?" TextDecorations="Underline" ToolTip="The audio recording device that will be used for the local PC information state values. Does not affect visualizer layer." ToolTipService.InitialShowDelay="0" Margin="822,89,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />
</Grid>
</TabItem>
<TabItem Header="Away Effects">
Expand Down Expand Up @@ -376,7 +383,7 @@
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>

<StackPanel Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Top" >
<Button
x:Name="btnShowBitmapWindow"
Expand Down
Loading