SEBWIN-303: Started implementing audio control.
This commit is contained in:
parent
b71529da31
commit
768336e381
28 changed files with 575 additions and 5 deletions
|
@ -34,6 +34,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||||
private Mock<INotificationController> aboutController;
|
private Mock<INotificationController> aboutController;
|
||||||
private Mock<INotificationInfo> logInfo;
|
private Mock<INotificationInfo> logInfo;
|
||||||
private Mock<INotificationController> logController;
|
private Mock<INotificationController> logController;
|
||||||
|
private Mock<ISystemComponent<ISystemAudioControl>> audio;
|
||||||
private Mock<ISystemComponent<ISystemKeyboardLayoutControl>> keyboardLayout;
|
private Mock<ISystemComponent<ISystemKeyboardLayoutControl>> keyboardLayout;
|
||||||
private Mock<ISystemComponent<ISystemPowerSupplyControl>> powerSupply;
|
private Mock<ISystemComponent<ISystemPowerSupplyControl>> powerSupply;
|
||||||
private Mock<ISystemComponent<ISystemWirelessNetworkControl>> wirelessNetwork;
|
private Mock<ISystemComponent<ISystemWirelessNetworkControl>> wirelessNetwork;
|
||||||
|
@ -55,6 +56,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||||
aboutController = new Mock<INotificationController>();
|
aboutController = new Mock<INotificationController>();
|
||||||
logInfo = new Mock<INotificationInfo>();
|
logInfo = new Mock<INotificationInfo>();
|
||||||
logController = new Mock<INotificationController>();
|
logController = new Mock<INotificationController>();
|
||||||
|
audio = new Mock<ISystemComponent<ISystemAudioControl>>();
|
||||||
keyboardLayout = new Mock<ISystemComponent<ISystemKeyboardLayoutControl>>();
|
keyboardLayout = new Mock<ISystemComponent<ISystemKeyboardLayoutControl>>();
|
||||||
powerSupply = new Mock<ISystemComponent<ISystemPowerSupplyControl>>();
|
powerSupply = new Mock<ISystemComponent<ISystemPowerSupplyControl>>();
|
||||||
wirelessNetwork = new Mock<ISystemComponent<ISystemWirelessNetworkControl>>();
|
wirelessNetwork = new Mock<ISystemComponent<ISystemWirelessNetworkControl>>();
|
||||||
|
@ -76,6 +78,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||||
aboutController.Object,
|
aboutController.Object,
|
||||||
logInfo.Object,
|
logInfo.Object,
|
||||||
logController.Object,
|
logController.Object,
|
||||||
|
audio.Object,
|
||||||
keyboardLayout.Object,
|
keyboardLayout.Object,
|
||||||
powerSupply.Object,
|
powerSupply.Object,
|
||||||
wirelessNetwork.Object,
|
wirelessNetwork.Object,
|
||||||
|
|
|
@ -67,6 +67,7 @@ namespace SafeExamBrowser.Client
|
||||||
private IProcessMonitor processMonitor;
|
private IProcessMonitor processMonitor;
|
||||||
private INativeMethods nativeMethods;
|
private INativeMethods nativeMethods;
|
||||||
private IRuntimeProxy runtimeProxy;
|
private IRuntimeProxy runtimeProxy;
|
||||||
|
private ISystemComponent<ISystemAudioControl> audio;
|
||||||
private ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout;
|
private ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout;
|
||||||
private ISystemComponent<ISystemPowerSupplyControl> powerSupply;
|
private ISystemComponent<ISystemPowerSupplyControl> powerSupply;
|
||||||
private ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork;
|
private ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork;
|
||||||
|
@ -93,6 +94,7 @@ namespace SafeExamBrowser.Client
|
||||||
InitializeText();
|
InitializeText();
|
||||||
|
|
||||||
actionCenter = BuildActionCenter();
|
actionCenter = BuildActionCenter();
|
||||||
|
audio = new Audio(new ModuleLogger(logger, nameof(Audio)), text);
|
||||||
keyboardLayout = new KeyboardLayout(new ModuleLogger(logger, nameof(KeyboardLayout)), text);
|
keyboardLayout = new KeyboardLayout(new ModuleLogger(logger, nameof(KeyboardLayout)), text);
|
||||||
messageBox = BuildMessageBox();
|
messageBox = BuildMessageBox();
|
||||||
powerSupply = new PowerSupply(new ModuleLogger(logger, nameof(PowerSupply)), text);
|
powerSupply = new PowerSupply(new ModuleLogger(logger, nameof(PowerSupply)), text);
|
||||||
|
@ -277,6 +279,7 @@ namespace SafeExamBrowser.Client
|
||||||
aboutController,
|
aboutController,
|
||||||
logInfo,
|
logInfo,
|
||||||
logController,
|
logController,
|
||||||
|
audio,
|
||||||
keyboardLayout,
|
keyboardLayout,
|
||||||
powerSupply,
|
powerSupply,
|
||||||
wirelessNetwork,
|
wirelessNetwork,
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
private INotificationController aboutController;
|
private INotificationController aboutController;
|
||||||
private INotificationInfo logInfo;
|
private INotificationInfo logInfo;
|
||||||
private INotificationController logController;
|
private INotificationController logController;
|
||||||
|
private ISystemComponent<ISystemAudioControl> audio;
|
||||||
private ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout;
|
private ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout;
|
||||||
private ISystemComponent<ISystemPowerSupplyControl> powerSupply;
|
private ISystemComponent<ISystemPowerSupplyControl> powerSupply;
|
||||||
private ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork;
|
private ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork;
|
||||||
|
@ -52,6 +53,7 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
INotificationController aboutController,
|
INotificationController aboutController,
|
||||||
INotificationInfo logInfo,
|
INotificationInfo logInfo,
|
||||||
INotificationController logController,
|
INotificationController logController,
|
||||||
|
ISystemComponent<ISystemAudioControl> audio,
|
||||||
ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout,
|
ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout,
|
||||||
ISystemComponent<ISystemPowerSupplyControl> powerSupply,
|
ISystemComponent<ISystemPowerSupplyControl> powerSupply,
|
||||||
ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork,
|
ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork,
|
||||||
|
@ -70,6 +72,7 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.logInfo = logInfo;
|
this.logInfo = logInfo;
|
||||||
this.logController = logController;
|
this.logController = logController;
|
||||||
|
this.audio = audio;
|
||||||
this.keyboardLayout = keyboardLayout;
|
this.keyboardLayout = keyboardLayout;
|
||||||
this.powerSupply = powerSupply;
|
this.powerSupply = powerSupply;
|
||||||
this.systemInfo = systemInfo;
|
this.systemInfo = systemInfo;
|
||||||
|
@ -128,6 +131,7 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
actionCenter.InitializeText(text);
|
actionCenter.InitializeText(text);
|
||||||
|
|
||||||
InitializeAboutNotificationForActionCenter();
|
InitializeAboutNotificationForActionCenter();
|
||||||
|
InitializeAudioForActionCenter();
|
||||||
InitializeClockForActionCenter();
|
InitializeClockForActionCenter();
|
||||||
InitializeLogNotificationForActionCenter();
|
InitializeLogNotificationForActionCenter();
|
||||||
InitializeKeyboardLayoutForActionCenter();
|
InitializeKeyboardLayoutForActionCenter();
|
||||||
|
@ -148,11 +152,12 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
taskbar.InitializeText(text);
|
taskbar.InitializeText(text);
|
||||||
|
|
||||||
InitializeAboutNotificationForTaskbar();
|
InitializeAboutNotificationForTaskbar();
|
||||||
InitializeClockForTaskbar();
|
|
||||||
InitializeLogNotificationForTaskbar();
|
InitializeLogNotificationForTaskbar();
|
||||||
InitializeKeyboardLayoutForTaskbar();
|
|
||||||
InitializeWirelessNetworkForTaskbar();
|
|
||||||
InitializePowerSupplyForTaskbar();
|
InitializePowerSupplyForTaskbar();
|
||||||
|
InitializeWirelessNetworkForTaskbar();
|
||||||
|
InitializeAudioForTaskbar();
|
||||||
|
InitializeKeyboardLayoutForTaskbar();
|
||||||
|
InitializeClockForTaskbar();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -162,6 +167,7 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
|
|
||||||
private void InitializeSystemComponents()
|
private void InitializeSystemComponents()
|
||||||
{
|
{
|
||||||
|
audio.Initialize();
|
||||||
keyboardLayout.Initialize();
|
keyboardLayout.Initialize();
|
||||||
powerSupply.Initialize();
|
powerSupply.Initialize();
|
||||||
wirelessNetwork.Initialize();
|
wirelessNetwork.Initialize();
|
||||||
|
@ -189,6 +195,28 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeAudioForActionCenter()
|
||||||
|
{
|
||||||
|
if (actionCenterSettings.ShowAudio)
|
||||||
|
{
|
||||||
|
var control = uiFactory.CreateAudioControl(Location.ActionCenter);
|
||||||
|
|
||||||
|
audio.Register(control);
|
||||||
|
actionCenter.AddSystemControl(control);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeAudioForTaskbar()
|
||||||
|
{
|
||||||
|
if (taskbarSettings.ShowAudio)
|
||||||
|
{
|
||||||
|
var control = uiFactory.CreateAudioControl(Location.Taskbar);
|
||||||
|
|
||||||
|
audio.Register(control);
|
||||||
|
taskbar.AddSystemControl(control);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void InitializeClockForActionCenter()
|
private void InitializeClockForActionCenter()
|
||||||
{
|
{
|
||||||
actionCenter.ShowClock = actionCenterSettings.ShowClock;
|
actionCenter.ShowClock = actionCenterSettings.ShowClock;
|
||||||
|
@ -308,6 +336,7 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
|
|
||||||
private void TerminateSystemComponents()
|
private void TerminateSystemComponents()
|
||||||
{
|
{
|
||||||
|
audio.Terminate();
|
||||||
keyboardLayout.Terminate();
|
keyboardLayout.Terminate();
|
||||||
powerSupply.Terminate();
|
powerSupply.Terminate();
|
||||||
wirelessNetwork.Terminate();
|
wirelessNetwork.Terminate();
|
||||||
|
|
|
@ -20,6 +20,15 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MapAudio(Settings settings, object value)
|
||||||
|
{
|
||||||
|
if (value is bool show)
|
||||||
|
{
|
||||||
|
settings.ActionCenter.ShowAudio = show;
|
||||||
|
settings.Taskbar.ShowAudio = show;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void MapClock(Settings settings, object value)
|
private void MapClock(Settings settings, object value)
|
||||||
{
|
{
|
||||||
if (value is bool show)
|
if (value is bool show)
|
||||||
|
|
|
@ -189,6 +189,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
||||||
{
|
{
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
|
case Keys.UserInterface.ShowAudio:
|
||||||
|
MapAudio(settings, value);
|
||||||
|
break;
|
||||||
case Keys.UserInterface.ShowKeyboardLayout:
|
case Keys.UserInterface.ShowKeyboardLayout:
|
||||||
MapKeyboardLayout(settings, value);
|
MapKeyboardLayout(settings, value);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -121,6 +121,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
||||||
|
|
||||||
internal static class UserInterface
|
internal static class UserInterface
|
||||||
{
|
{
|
||||||
|
internal const string ShowAudio = "audioControlEnabled";
|
||||||
internal const string ShowClock = "showTime";
|
internal const string ShowClock = "showTime";
|
||||||
internal const string ShowKeyboardLayout = "showInputLanguage";
|
internal const string ShowKeyboardLayout = "showInputLanguage";
|
||||||
internal const string ShowWirelessNetwork = "allowWlan";
|
internal const string ShowWirelessNetwork = "allowWlan";
|
||||||
|
|
|
@ -31,6 +31,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ShowApplicationLog { get; set; }
|
public bool ShowApplicationLog { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the system control for audio is accessible via the action center.
|
||||||
|
/// </summary>
|
||||||
|
public bool ShowAudio { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the current date and time will be rendered in the action center.
|
/// Determines whether the current date and time will be rendered in the action center.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -31,6 +31,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ShowApplicationLog { get; set; }
|
public bool ShowApplicationLog { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the system control for audio is accessible via the taskbar.
|
||||||
|
/// </summary>
|
||||||
|
public bool ShowAudio { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the current date and time will be rendered in the taskbar.
|
/// Determines whether the current date and time will be rendered in the taskbar.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -107,6 +107,9 @@ namespace SafeExamBrowser.Contracts.I18n
|
||||||
PasswordDialog_SettingsPasswordRequiredTitle,
|
PasswordDialog_SettingsPasswordRequiredTitle,
|
||||||
RuntimeWindow_ApplicationRunning,
|
RuntimeWindow_ApplicationRunning,
|
||||||
Shell_QuitButton,
|
Shell_QuitButton,
|
||||||
|
SystemControl_AudioDeviceInfo,
|
||||||
|
SystemControl_AudioDeviceInfoMuted,
|
||||||
|
SystemControl_AudioDeviceNotFound,
|
||||||
SystemControl_BatteryCharged,
|
SystemControl_BatteryCharged,
|
||||||
SystemControl_BatteryCharging,
|
SystemControl_BatteryCharging,
|
||||||
SystemControl_BatteryChargeCriticalWarning,
|
SystemControl_BatteryChargeCriticalWarning,
|
||||||
|
|
|
@ -212,6 +212,7 @@
|
||||||
<Compile Include="UserInterface\Shell\Events\NotificationControlClickedEventHandler.cs" />
|
<Compile Include="UserInterface\Shell\Events\NotificationControlClickedEventHandler.cs" />
|
||||||
<Compile Include="UserInterface\Shell\IActionCenter.cs" />
|
<Compile Include="UserInterface\Shell\IActionCenter.cs" />
|
||||||
<Compile Include="UserInterface\Shell\IActionCenterActivator.cs" />
|
<Compile Include="UserInterface\Shell\IActionCenterActivator.cs" />
|
||||||
|
<Compile Include="UserInterface\Shell\ISystemAudioControl.cs" />
|
||||||
<Compile Include="UserInterface\Shell\Location.cs" />
|
<Compile Include="UserInterface\Shell\Location.cs" />
|
||||||
<Compile Include="UserInterface\Windows\Events\WindowClosingEventHandler.cs" />
|
<Compile Include="UserInterface\Windows\Events\WindowClosingEventHandler.cs" />
|
||||||
<Compile Include="UserInterface\Shell\Events\WirelessNetworkSelectedEventHandler.cs" />
|
<Compile Include="UserInterface\Shell\Events\WirelessNetworkSelectedEventHandler.cs" />
|
||||||
|
|
|
@ -11,8 +11,8 @@ using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||||
namespace SafeExamBrowser.Contracts.SystemComponents
|
namespace SafeExamBrowser.Contracts.SystemComponents
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the functionality of a system component (e.g. the power supply). Each system component will get an <see cref="ISystemControl"/>
|
/// Defines the functionality of a system component (e.g. the power supply). Each system component can get multiple <see cref="ISystemControl"/>
|
||||||
/// assigned, via which the user is able to interact with or get information about the underlying system component.
|
/// assigned, which in turn allow the user to interact with or get information about the underlying system component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISystemComponent<TControl> where TControl : ISystemControl
|
public interface ISystemComponent<TControl> where TControl : ISystemControl
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,6 +33,11 @@ namespace SafeExamBrowser.Contracts.UserInterface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IApplicationControl CreateApplicationControl(IApplicationInfo info, Location location);
|
IApplicationControl CreateApplicationControl(IApplicationInfo info, Location location);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a system control which allows to change the audio settings of the computer.
|
||||||
|
/// </summary>
|
||||||
|
ISystemAudioControl CreateAudioControl(Location location);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new browser window loaded with the given browser control and settings.
|
/// Creates a new browser window loaded with the given browser control and settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The control of the audio system component.
|
||||||
|
/// </summary>
|
||||||
|
public interface ISystemAudioControl : ISystemControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines whether the computer has an audio output device.
|
||||||
|
/// </summary>
|
||||||
|
bool HasOutputDevice { set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the current output device is muted.
|
||||||
|
/// </summary>
|
||||||
|
bool OutputDeviceMuted { set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows the name of the currently active audio output device.
|
||||||
|
/// </summary>
|
||||||
|
string OutputDeviceName { set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -279,6 +279,15 @@
|
||||||
<Entry key="Shell_QuitButton">
|
<Entry key="Shell_QuitButton">
|
||||||
Terminate Session
|
Terminate Session
|
||||||
</Entry>
|
</Entry>
|
||||||
|
<Entry key="SystemControl_AudioDeviceInfo">
|
||||||
|
%%NAME%%: %%VOLUME%%%
|
||||||
|
</Entry>
|
||||||
|
<Entry key="SystemControl_AudioDeviceInfoMuted">
|
||||||
|
%%NAME%%: Muted
|
||||||
|
</Entry>
|
||||||
|
<Entry key="SystemControl_AudioDeviceNotFound">
|
||||||
|
No audio device found
|
||||||
|
</Entry>
|
||||||
<Entry key="SystemControl_BatteryCharging">
|
<Entry key="SystemControl_BatteryCharging">
|
||||||
Plugged in, charging... (%%CHARGE%%%)
|
Plugged in, charging... (%%CHARGE%%%)
|
||||||
</Entry>
|
</Entry>
|
||||||
|
|
162
SafeExamBrowser.SystemComponents/Audio.cs
Normal file
162
SafeExamBrowser.SystemComponents/Audio.cs
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NAudio.CoreAudioApi;
|
||||||
|
using SafeExamBrowser.Contracts.I18n;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
using SafeExamBrowser.Contracts.SystemComponents;
|
||||||
|
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.SystemComponents
|
||||||
|
{
|
||||||
|
public class Audio : ISystemComponent<ISystemAudioControl>
|
||||||
|
{
|
||||||
|
private readonly object @lock = new object();
|
||||||
|
|
||||||
|
private MMDevice audioDevice;
|
||||||
|
private string audioDeviceShortName;
|
||||||
|
private List<ISystemAudioControl> controls;
|
||||||
|
private ILogger logger;
|
||||||
|
private IText text;
|
||||||
|
|
||||||
|
public Audio(ILogger logger, IText text)
|
||||||
|
{
|
||||||
|
this.controls = new List<ISystemAudioControl>();
|
||||||
|
this.logger = logger;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
if (TryLoadAudioDevice())
|
||||||
|
{
|
||||||
|
InitializeAudioDevice();
|
||||||
|
InitializeSettings();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Warn("Could not find an active audio device!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Register(ISystemAudioControl control)
|
||||||
|
{
|
||||||
|
lock (@lock)
|
||||||
|
{
|
||||||
|
controls.Add(control);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Terminate()
|
||||||
|
{
|
||||||
|
if (audioDevice != default(MMDevice))
|
||||||
|
{
|
||||||
|
audioDevice.AudioEndpointVolume.OnVolumeNotification -= AudioEndpointVolume_OnVolumeNotification;
|
||||||
|
audioDevice.Dispose();
|
||||||
|
logger.Info("Stopped monitoring the audio device.");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var control in controls)
|
||||||
|
{
|
||||||
|
control.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryLoadAudioDevice()
|
||||||
|
{
|
||||||
|
using (var enumerator = new MMDeviceEnumerator())
|
||||||
|
{
|
||||||
|
if (enumerator.HasDefaultAudioEndpoint(DataFlow.Render, Role.Console))
|
||||||
|
{
|
||||||
|
audioDevice = enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Console);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audioDevice = enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active).FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return audioDevice != default(MMDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeAudioDevice()
|
||||||
|
{
|
||||||
|
logger.Info($"Found '{audioDevice}' to be the active audio device.");
|
||||||
|
audioDevice.AudioEndpointVolume.OnVolumeNotification += AudioEndpointVolume_OnVolumeNotification;
|
||||||
|
audioDeviceShortName = audioDevice.FriendlyName.Length > 25 ? audioDevice.FriendlyName.Split(' ').First() : audioDevice.FriendlyName;
|
||||||
|
logger.Info("Started monitoring the audio device.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeSettings()
|
||||||
|
{
|
||||||
|
// TODO: Mute on startup & initial volume!
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AudioEndpointVolume_OnVolumeNotification(AudioVolumeNotificationData data)
|
||||||
|
{
|
||||||
|
lock (@lock)
|
||||||
|
{
|
||||||
|
var info = BuildInfoText(data.MasterVolume, data.Muted);
|
||||||
|
|
||||||
|
foreach (var control in controls)
|
||||||
|
{
|
||||||
|
control.OutputDeviceMuted = data.Muted;
|
||||||
|
control.OutputDeviceVolume = data.MasterVolume;
|
||||||
|
control.SetInformation(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateControls()
|
||||||
|
{
|
||||||
|
lock (@lock)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var info = BuildInfoText(audioDevice.AudioEndpointVolume.MasterVolumeLevelScalar, audioDevice.AudioEndpointVolume.Mute);
|
||||||
|
|
||||||
|
foreach (var control in controls)
|
||||||
|
{
|
||||||
|
if (audioDevice != default(MMDevice))
|
||||||
|
{
|
||||||
|
control.HasOutputDevice = true;
|
||||||
|
control.OutputDeviceMuted = audioDevice.AudioEndpointVolume.Mute;
|
||||||
|
control.OutputDeviceName = audioDevice.FriendlyName;
|
||||||
|
control.OutputDeviceVolume = audioDevice.AudioEndpointVolume.MasterVolumeLevelScalar;
|
||||||
|
control.SetInformation(info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
control.HasOutputDevice = false;
|
||||||
|
control.SetInformation(text.Get(TextKey.SystemControl_AudioDeviceNotFound));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.Error("Failed to update audio device status!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildInfoText(float volume, bool muted)
|
||||||
|
{
|
||||||
|
var info = text.Get(muted ? TextKey.SystemControl_AudioDeviceInfoMuted : TextKey.SystemControl_AudioDeviceInfo);
|
||||||
|
|
||||||
|
info = info.Replace("%%NAME%%", audioDeviceShortName);
|
||||||
|
info = info.Replace("%%VOLUME%%", Convert.ToString(volume * 100));
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,6 +48,9 @@
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="NAudio, Version=1.9.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\NAudio.1.9.0\lib\net35\NAudio.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="PresentationCore" />
|
<Reference Include="PresentationCore" />
|
||||||
<Reference Include="SimpleWifi, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="SimpleWifi, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
@ -59,6 +62,7 @@
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Audio.cs" />
|
||||||
<Compile Include="KeyboardLayoutDefinition.cs" />
|
<Compile Include="KeyboardLayoutDefinition.cs" />
|
||||||
<Compile Include="KeyboardLayout.cs" />
|
<Compile Include="KeyboardLayout.cs" />
|
||||||
<Compile Include="PowerSupply.cs" />
|
<Compile Include="PowerSupply.cs" />
|
||||||
|
@ -74,5 +78,8 @@
|
||||||
<Name>SafeExamBrowser.Contracts</Name>
|
<Name>SafeExamBrowser.Contracts</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
4
SafeExamBrowser.SystemComponents/packages.config
Normal file
4
SafeExamBrowser.SystemComponents/packages.config
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="NAudio" version="1.9.0" targetFramework="net472" />
|
||||||
|
</packages>
|
|
@ -0,0 +1,37 @@
|
||||||
|
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.TaskbarAudioControl"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||||
|
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls"
|
||||||
|
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="40">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||||
|
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||||
|
<ResourceDictionary Source="../Templates/ScrollViewers.xaml" />
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Grid>
|
||||||
|
<Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||||
|
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="0.75,0.75,0.75,0">
|
||||||
|
<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">
|
||||||
|
<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" />
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Popup>
|
||||||
|
<Button x:Name="Button" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" ToolTipService.ShowOnDisabled="True" Width="40">
|
||||||
|
<ContentControl x:Name="TaskbarIcon" />
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* 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.Media;
|
||||||
|
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||||
|
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
|
{
|
||||||
|
public partial class TaskbarAudioControl : UserControl, ISystemAudioControl
|
||||||
|
{
|
||||||
|
private bool muted;
|
||||||
|
private XamlIconResource MutedIcon;
|
||||||
|
private XamlIconResource NoDeviceIcon;
|
||||||
|
|
||||||
|
public TaskbarAudioControl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
InitializeAudioControl();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasOutputDevice
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Dispatcher.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
Button.IsEnabled = value;
|
||||||
|
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
TaskbarIcon.Content = IconResourceLoader.Load(NoDeviceIcon);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OutputDeviceMuted
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Dispatcher.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
muted = value;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
PopupIcon.Content = IconResourceLoader.Load(MutedIcon);
|
||||||
|
TaskbarIcon.Content = IconResourceLoader.Load(MutedIcon);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskbarIcon.Content = LoadIcon(Volume.Value / 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OutputDeviceName
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Dispatcher.InvokeAsync(() => AudioDeviceName.Text = value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double OutputDeviceVolume
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Dispatcher.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
Volume.Value = Math.Round(value * 100);
|
||||||
|
|
||||||
|
if (!muted)
|
||||||
|
{
|
||||||
|
PopupIcon.Content = LoadIcon(value);
|
||||||
|
TaskbarIcon.Content = LoadIcon(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
Popup.IsOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetInformation(string text)
|
||||||
|
{
|
||||||
|
Dispatcher.InvokeAsync(() => Button.ToolTip = text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeAudioControl()
|
||||||
|
{
|
||||||
|
var originalBrush = Button.Background;
|
||||||
|
|
||||||
|
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||||
|
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||||
|
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));
|
||||||
|
|
||||||
|
Popup.Opened += (o, args) =>
|
||||||
|
{
|
||||||
|
Background = Brushes.LightGray;
|
||||||
|
Button.Background = Brushes.LightGray;
|
||||||
|
};
|
||||||
|
|
||||||
|
Popup.Closed += (o, args) =>
|
||||||
|
{
|
||||||
|
Background = originalBrush;
|
||||||
|
Button.Background = originalBrush;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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_{icon}.xaml");
|
||||||
|
var resource = new XamlIconResource(uri);
|
||||||
|
|
||||||
|
return IconResourceLoader.Load(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
SafeExamBrowser.UserInterface.Desktop/Images/AudioMuted.xaml
Normal file
12
SafeExamBrowser.UserInterface.Desktop/Images/AudioMuted.xaml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<Viewbox
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
<Grid>
|
||||||
|
<fa:ImageAwesome Icon="VolumeOff" HorizontalAlignment="Left" />
|
||||||
|
<Canvas Width="100" Height="100">
|
||||||
|
<Path StrokeThickness="5.0" Stroke="Black" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 60,35 L 90,65"/>
|
||||||
|
<Path StrokeThickness="5.0" Stroke="Black" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 60,65 L 90,35"/>
|
||||||
|
</Canvas>
|
||||||
|
</Grid>
|
||||||
|
</Viewbox>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<Viewbox
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
<Grid Margin="1">
|
||||||
|
<Grid Margin="5,0,0,0">
|
||||||
|
<fa:ImageAwesome Icon="VolumeOff" Foreground="DarkGray" HorizontalAlignment="Left" />
|
||||||
|
<Canvas Width="100" Height="100">
|
||||||
|
<Path StrokeThickness="5.0" Stroke="DarkGray" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 55,35 C 65,45 65,55 55,65"/>
|
||||||
|
<Path StrokeThickness="5.0" Stroke="DarkGray" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 65,25 C 80,35 80,65 65,75"/>
|
||||||
|
<Path StrokeThickness="5.0" Stroke="DarkGray" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 75,15 C 95,30 95,70 75,85"/>
|
||||||
|
</Canvas>
|
||||||
|
</Grid>
|
||||||
|
<fa:ImageAwesome Foreground="Red" Icon="Ban" Opacity="0.3" />
|
||||||
|
</Grid>
|
||||||
|
</Viewbox>
|
13
SafeExamBrowser.UserInterface.Desktop/Images/Audio_100.xaml
Normal file
13
SafeExamBrowser.UserInterface.Desktop/Images/Audio_100.xaml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<Viewbox
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
<Grid>
|
||||||
|
<fa:ImageAwesome Icon="VolumeOff" HorizontalAlignment="Left" />
|
||||||
|
<Canvas Width="100" Height="100">
|
||||||
|
<Path StrokeThickness="5.0" Stroke="Black" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 55,35 C 65,45 65,55 55,65"/>
|
||||||
|
<Path StrokeThickness="5.0" Stroke="Black" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 65,25 C 80,35 80,65 65,75"/>
|
||||||
|
<Path StrokeThickness="5.0" Stroke="Black" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 75,15 C 95,30 95,70 75,85"/>
|
||||||
|
</Canvas>
|
||||||
|
</Grid>
|
||||||
|
</Viewbox>
|
13
SafeExamBrowser.UserInterface.Desktop/Images/Audio_33.xaml
Normal file
13
SafeExamBrowser.UserInterface.Desktop/Images/Audio_33.xaml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<Viewbox
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
<Grid>
|
||||||
|
<fa:ImageAwesome Icon="VolumeOff" HorizontalAlignment="Left" />
|
||||||
|
<Canvas Width="100" Height="100">
|
||||||
|
<Path StrokeThickness="5.0" Stroke="Black" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 55,35 C 65,45 65,55 55,65"/>
|
||||||
|
<Path StrokeThickness="5.0" Stroke="DarkGray" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 65,25 C 80,35 80,65 65,75"/>
|
||||||
|
<Path StrokeThickness="5.0" Stroke="DarkGray" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 75,15 C 95,30 95,70 75,85"/>
|
||||||
|
</Canvas>
|
||||||
|
</Grid>
|
||||||
|
</Viewbox>
|
13
SafeExamBrowser.UserInterface.Desktop/Images/Audio_66.xaml
Normal file
13
SafeExamBrowser.UserInterface.Desktop/Images/Audio_66.xaml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<Viewbox
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
<Grid>
|
||||||
|
<fa:ImageAwesome Icon="VolumeOff" HorizontalAlignment="Left" />
|
||||||
|
<Canvas Width="100" Height="100">
|
||||||
|
<Path StrokeThickness="5.0" Stroke="Black" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 55,35 C 65,45 65,55 55,65"/>
|
||||||
|
<Path StrokeThickness="5.0" Stroke="Black" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 65,25 C 80,35 80,65 65,75"/>
|
||||||
|
<Path StrokeThickness="5.0" Stroke="DarkGray" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 75,15 C 95,30 95,70 75,85"/>
|
||||||
|
</Canvas>
|
||||||
|
</Grid>
|
||||||
|
</Viewbox>
|
|
@ -110,6 +110,9 @@
|
||||||
<Compile Include="Controls\TaskbarApplicationInstanceButton.xaml.cs">
|
<Compile Include="Controls\TaskbarApplicationInstanceButton.xaml.cs">
|
||||||
<DependentUpon>TaskbarApplicationInstanceButton.xaml</DependentUpon>
|
<DependentUpon>TaskbarApplicationInstanceButton.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Controls\TaskbarAudioControl.xaml.cs">
|
||||||
|
<DependentUpon>TaskbarAudioControl.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Controls\TaskbarClock.xaml.cs">
|
<Compile Include="Controls\TaskbarClock.xaml.cs">
|
||||||
<DependentUpon>TaskbarClock.xaml</DependentUpon>
|
<DependentUpon>TaskbarClock.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -212,6 +215,10 @@
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Controls\TaskbarAudioControl.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="Controls\TaskbarClock.xaml">
|
<Page Include="Controls\TaskbarClock.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
@ -256,6 +263,26 @@
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Resource>
|
</Resource>
|
||||||
|
<Resource Include="Images\AudioNoDevice.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Resource>
|
||||||
|
<Resource Include="Images\Audio_66.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Resource>
|
||||||
|
<Resource Include="Images\Audio_33.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Resource>
|
||||||
|
<Resource Include="Images\Audio_100.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Resource>
|
||||||
|
<Resource Include="Images\AudioMuted.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Resource>
|
||||||
<Page Include="Templates\ScrollViewers.xaml">
|
<Page Include="Templates\ScrollViewers.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
|
|
@ -52,6 +52,19 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ISystemAudioControl CreateAudioControl(Location location)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
//if (location == Location.ActionCenter)
|
||||||
|
//{
|
||||||
|
// return new ActionCenterAudioControl();
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
{
|
||||||
|
return new TaskbarAudioControl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow)
|
public IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow)
|
||||||
{
|
{
|
||||||
return new BrowserWindow(control, settings, isMainWindow, text);
|
return new BrowserWindow(control, settings, isMainWindow, text);
|
||||||
|
|
|
@ -52,6 +52,12 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ISystemAudioControl CreateAudioControl(Location location)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow)
|
public IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow)
|
||||||
{
|
{
|
||||||
return new BrowserWindow(control, settings, isMainWindow, text);
|
return new BrowserWindow(control, settings, isMainWindow, text);
|
||||||
|
|
Binary file not shown.
Loading…
Reference in a new issue