SEBWIN-303: Implemented audio control logic.
This commit is contained in:
parent
cc6710cedf
commit
4381be2647
10 changed files with 107 additions and 6 deletions
|
@ -109,7 +109,9 @@ namespace SafeExamBrowser.Contracts.I18n
|
|||
Shell_QuitButton,
|
||||
SystemControl_AudioDeviceInfo,
|
||||
SystemControl_AudioDeviceInfoMuted,
|
||||
SystemControl_AudioDeviceMuteTooltip,
|
||||
SystemControl_AudioDeviceNotFound,
|
||||
SystemControl_AudioDeviceUnmuteTooltip,
|
||||
SystemControl_BatteryCharged,
|
||||
SystemControl_BatteryCharging,
|
||||
SystemControl_BatteryChargeCriticalWarning,
|
||||
|
|
|
@ -208,6 +208,8 @@
|
|||
<Compile Include="UserInterface\IProgressIndicator.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\ActivatorEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\ApplicationControlClickedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\AudioMuteRequestedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\AudioVolumeSelectedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\KeyboardLayoutSelectedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\NotificationControlClickedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\IActionCenter.cs" />
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the user would like to change the audio mute status to the given value.
|
||||
/// </summary>
|
||||
public delegate void AudioMuteRequestedEventHandler(bool mute);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the user would like to set the audio volume to the given value, where <c>0.0</c> is the lowest and <c>1.0</c> the highest
|
||||
/// possible value.
|
||||
/// </summary>
|
||||
public delegate void AudioVolumeSelectedEventHandler(double volume);
|
||||
}
|
|
@ -6,6 +6,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -32,5 +34,15 @@ namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
|||
/// Shows the current audio output volume, where <c>0.0</c> is the lowest and <c>1.0</c> the highest possible value.
|
||||
/// </summary>
|
||||
double OutputDeviceVolume { set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the user requests to mute the current output device.
|
||||
/// </summary>
|
||||
event AudioMuteRequestedEventHandler MuteRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the user requests to set the volume of the current output device.
|
||||
/// </summary>
|
||||
event AudioVolumeSelectedEventHandler VolumeSelected;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -285,9 +285,15 @@
|
|||
<Entry key="SystemControl_AudioDeviceInfoMuted">
|
||||
%%NAME%%: Muted
|
||||
</Entry>
|
||||
<Entry key="SystemControl_AudioDeviceMuteTooltip">
|
||||
Click to mute audio
|
||||
</Entry>
|
||||
<Entry key="SystemControl_AudioDeviceNotFound">
|
||||
No audio device found
|
||||
</Entry>
|
||||
<Entry key="SystemControl_AudioDeviceUnmuteTooltip">
|
||||
Click to unmute audio
|
||||
</Entry>
|
||||
<Entry key="SystemControl_BatteryCharging">
|
||||
Plugged in, charging... (%%CHARGE%%%)
|
||||
</Entry>
|
||||
|
|
|
@ -49,6 +49,9 @@ namespace SafeExamBrowser.SystemComponents
|
|||
|
||||
public void Register(ISystemAudioControl control)
|
||||
{
|
||||
control.MuteRequested += Control_MuteRequested;
|
||||
control.VolumeSelected += Control_VolumeSelected;
|
||||
|
||||
lock (@lock)
|
||||
{
|
||||
controls.Add(control);
|
||||
|
@ -108,6 +111,8 @@ namespace SafeExamBrowser.SystemComponents
|
|||
{
|
||||
var info = BuildInfoText(data.MasterVolume, data.Muted);
|
||||
|
||||
logger.Debug($"Detected audio device change: Volume {data.MasterVolume * 100}, {(data.Muted ? "muted" : "unmuted")}");
|
||||
|
||||
foreach (var control in controls)
|
||||
{
|
||||
control.OutputDeviceMuted = data.Muted;
|
||||
|
@ -117,6 +122,16 @@ namespace SafeExamBrowser.SystemComponents
|
|||
}
|
||||
}
|
||||
|
||||
private void Control_MuteRequested(bool mute)
|
||||
{
|
||||
audioDevice.AudioEndpointVolume.Mute = mute;
|
||||
}
|
||||
|
||||
private void Control_VolumeSelected(double volume)
|
||||
{
|
||||
audioDevice.AudioEndpointVolume.MasterVolumeLevelScalar = (float) volume;
|
||||
}
|
||||
|
||||
private void UpdateControls()
|
||||
{
|
||||
lock (@lock)
|
||||
|
@ -154,7 +169,7 @@ namespace SafeExamBrowser.SystemComponents
|
|||
var info = text.Get(muted ? TextKey.SystemControl_AudioDeviceInfoMuted : TextKey.SystemControl_AudioDeviceInfo);
|
||||
|
||||
info = info.Replace("%%NAME%%", audioDeviceShortName);
|
||||
info = info.Replace("%%VOLUME%%", Convert.ToString(volume * 100));
|
||||
info = info.Replace("%%VOLUME%%", Convert.ToString(Math.Round(volume * 100)));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
|
|
@ -21,11 +21,13 @@
|
|||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock x:Name="AudioDeviceName" Margin="5" TextAlignment="Center" />
|
||||
<StackPanel Orientation="Horizontal" Height="40">
|
||||
<Button x:Name="Mute" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" Width="40">
|
||||
<Button x:Name="MuteButton" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" Width="40">
|
||||
<ContentControl x:Name="PopupIcon" />
|
||||
</Button>
|
||||
<Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" IsSnapToTickEnabled="True" Maximum="100" VerticalAlignment="Center" Width="250" />
|
||||
<TextBlock Grid.Column="2" FontWeight="DemiBold" FontSize="16" Text="{Binding ElementName=Volume, Path=Value}" TextAlignment="Center" VerticalAlignment="Center" Width="40" />
|
||||
<Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True"
|
||||
IsMoveToPointEnabled="True" VerticalAlignment="Center" Width="250" Thumb.DragStarted="Volume_DragStarted" Thumb.DragCompleted="Volume_DragCompleted" />
|
||||
<TextBlock Grid.Column="2" FontWeight="DemiBold" FontSize="16" Text="{Binding ElementName=Volume, Path=Value}"
|
||||
TextAlignment="Center" VerticalAlignment="Center" Width="40" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
|
|
@ -10,20 +10,29 @@ using System;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
public partial class TaskbarAudioControl : UserControl, ISystemAudioControl
|
||||
{
|
||||
private readonly IText text;
|
||||
private bool muted;
|
||||
private XamlIconResource MutedIcon;
|
||||
private XamlIconResource NoDeviceIcon;
|
||||
|
||||
public TaskbarAudioControl()
|
||||
public event AudioMuteRequestedEventHandler MuteRequested;
|
||||
public event AudioVolumeSelectedEventHandler VolumeSelected;
|
||||
|
||||
public TaskbarAudioControl(IText text)
|
||||
{
|
||||
this.text = text;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeAudioControl();
|
||||
}
|
||||
|
@ -54,11 +63,13 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
|
||||
if (value)
|
||||
{
|
||||
MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceUnmuteTooltip);
|
||||
PopupIcon.Content = IconResourceLoader.Load(MutedIcon);
|
||||
TaskbarIcon.Content = IconResourceLoader.Load(MutedIcon);
|
||||
}
|
||||
else
|
||||
{
|
||||
MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceMuteTooltip);
|
||||
TaskbarIcon.Content = LoadIcon(Volume.Value / 100);
|
||||
}
|
||||
});
|
||||
|
@ -79,7 +90,9 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
Volume.ValueChanged -= Volume_ValueChanged;
|
||||
Volume.Value = Math.Round(value * 100);
|
||||
Volume.ValueChanged += Volume_ValueChanged;
|
||||
|
||||
if (!muted)
|
||||
{
|
||||
|
@ -106,9 +119,11 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
|
||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
MuteButton.Click += (o, args) => MuteRequested?.Invoke(!muted);
|
||||
MutedIcon = new XamlIconResource(new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/AudioMuted.xaml"));
|
||||
NoDeviceIcon = new XamlIconResource(new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/AudioNoDevice.xaml"));
|
||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||
Volume.ValueChanged += Volume_ValueChanged;
|
||||
|
||||
Popup.Opened += (o, args) =>
|
||||
{
|
||||
|
@ -123,6 +138,22 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
};
|
||||
}
|
||||
|
||||
private void Volume_DragStarted(object sender, DragStartedEventArgs e)
|
||||
{
|
||||
Volume.ValueChanged -= Volume_ValueChanged;
|
||||
}
|
||||
|
||||
private void Volume_DragCompleted(object sender, DragCompletedEventArgs e)
|
||||
{
|
||||
VolumeSelected?.Invoke(Volume.Value / 100);
|
||||
Volume.ValueChanged += Volume_ValueChanged;
|
||||
}
|
||||
|
||||
private void Volume_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
|
||||
{
|
||||
VolumeSelected?.Invoke(Volume.Value / 100);
|
||||
}
|
||||
|
||||
private UIElement LoadIcon(double volume)
|
||||
{
|
||||
var icon = volume > 0.66 ? "100" : (volume > 0.33 ? "66" : "33");
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
//}
|
||||
//else
|
||||
{
|
||||
return new TaskbarAudioControl();
|
||||
return new TaskbarAudioControl(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue