/* * 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/. */ using System; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Media; using System.Windows.Threading; using SafeExamBrowser.Applications.Contracts.Resources.Icons; using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.SystemComponents.Contracts.Audio; using SafeExamBrowser.UserInterface.Contracts.Shell; using SafeExamBrowser.UserInterface.Shared.Utilities; namespace SafeExamBrowser.UserInterface.Desktop.Controls { public partial class ActionCenterAudioControl : UserControl, ISystemControl { private readonly IAudio audio; private readonly IText text; private bool muted; private IconResource MutedIcon; private IconResource NoDeviceIcon; public ActionCenterAudioControl(IAudio audio, IText text) { this.audio = audio; this.text = text; InitializeComponent(); InitializeAudioControl(); } public void Close() { Popup.IsOpen = false; } private void InitializeAudioControl() { var originalBrush = Grid.Background; audio.VolumeChanged += Audio_VolumeChanged; Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen; Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver)); MuteButton.Click += MuteButton_Click; MutedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.xaml") }; NoDeviceIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Light_NoDevice.xaml") }; Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver)); Popup.Opened += (o, args) => Grid.Background = Brushes.Gray; Popup.Closed += (o, args) => Grid.Background = originalBrush; Volume.ValueChanged += Volume_ValueChanged; if (audio.HasOutputDevice) { AudioDeviceName.Text = audio.DeviceFullName; Button.IsEnabled = true; UpdateVolume(audio.OutputVolume, audio.OutputMuted); } else { AudioDeviceName.Text = text.Get(TextKey.SystemControl_AudioDeviceNotFound); Button.IsEnabled = false; Button.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceNotFound); ButtonIcon.Content = IconResourceLoader.Load(NoDeviceIcon); Text.Text = text.Get(TextKey.SystemControl_AudioDeviceNotFound); } } private void Audio_VolumeChanged(double volume, bool muted) { Dispatcher.InvokeAsync(() => UpdateVolume(volume, muted)); } private void MuteButton_Click(object sender, RoutedEventArgs e) { if (muted) { audio.Unmute(); } else { audio.Mute(); } } private void Volume_DragStarted(object sender, DragStartedEventArgs e) { Volume.ValueChanged -= Volume_ValueChanged; } private void Volume_DragCompleted(object sender, DragCompletedEventArgs e) { audio.SetVolume(Volume.Value / 100); Volume.ValueChanged += Volume_ValueChanged; } private void Volume_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { audio.SetVolume(Volume.Value / 100); } private void UpdateVolume(double volume, bool muted) { var info = BuildInfoText(volume, muted); this.muted = muted; Button.ToolTip = info; Text.Text = info; Volume.ValueChanged -= Volume_ValueChanged; Volume.Value = Math.Round(volume * 100); Volume.ValueChanged += Volume_ValueChanged; if (muted) { ButtonIcon.Content = IconResourceLoader.Load(MutedIcon); MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceUnmuteTooltip); PopupIcon.Content = IconResourceLoader.Load(MutedIcon); } else { ButtonIcon.Content = LoadIcon(volume); MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceMuteTooltip); PopupIcon.Content = LoadIcon(volume); } } private string BuildInfoText(double volume, bool muted) { var info = text.Get(muted ? TextKey.SystemControl_AudioDeviceInfoMuted : TextKey.SystemControl_AudioDeviceInfo); info = info.Replace("%%NAME%%", audio.DeviceShortName); info = info.Replace("%%VOLUME%%", Convert.ToString(Math.Round(volume * 100))); return info; } private UIElement LoadIcon(double volume) { var icon = volume > 0.66 ? "100" : (volume > 0.33 ? "66" : "33"); var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Light_{icon}.xaml"); var resource = new XamlIconResource { Uri = uri}; return IconResourceLoader.Load(resource); } } }