2023-08-06 13:46:36 -06:00
|
|
|
|
using BarRaider.SdTools;
|
|
|
|
|
using BarRaider.SdTools.Payloads;
|
2023-08-20 20:52:48 -06:00
|
|
|
|
using FocusVolumeControl.AudioSessions;
|
2023-08-06 21:51:04 -06:00
|
|
|
|
using FocusVolumeControl.UI;
|
2023-08-06 13:46:36 -06:00
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
2023-08-06 21:51:04 -06:00
|
|
|
|
using System.Windows.Threading;
|
2023-08-06 13:46:36 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
namespace FocusVolumeControl;
|
|
|
|
|
|
|
|
|
|
[PluginActionId("com.dlprows.focusvolumecontrol.dialaction")]
|
|
|
|
|
public class DialAction : EncoderBase
|
2023-08-06 13:46:36 -06:00
|
|
|
|
{
|
2023-08-20 20:52:48 -06:00
|
|
|
|
private class PluginSettings
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
[JsonProperty("onVolumeNotFound")]
|
|
|
|
|
public FallbackBehavior FallbackBehavior { get; set; }
|
|
|
|
|
|
|
|
|
|
public static PluginSettings CreateDefaultSettings()
|
|
|
|
|
{
|
|
|
|
|
PluginSettings instance = new PluginSettings();
|
|
|
|
|
instance.FallbackBehavior = FallbackBehavior.PreviousApp;
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-06 13:46:36 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
private PluginSettings settings;
|
2023-08-06 13:46:36 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
IntPtr _foregroundWindowChangedEvent;
|
|
|
|
|
Native.WinEventDelegate _delegate;
|
2023-08-06 13:46:36 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
IAudioSession _currentAudioSession;
|
|
|
|
|
AudioHelper _audioHelper = new AudioHelper();
|
2023-08-06 13:46:36 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
Thread _thread;
|
|
|
|
|
Dispatcher _dispatcher;
|
2023-08-06 13:46:36 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
UIState _previousState;
|
2023-08-06 13:46:36 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
public DialAction(ISDConnection connection, InitialPayload payload) : base(connection, payload)
|
2023-08-06 21:51:04 -06:00
|
|
|
|
{
|
2023-08-20 20:52:48 -06:00
|
|
|
|
if (payload.Settings == null || payload.Settings.Count == 0)
|
2023-08-06 21:51:04 -06:00
|
|
|
|
{
|
2023-08-20 20:52:48 -06:00
|
|
|
|
settings = PluginSettings.CreateDefaultSettings();
|
|
|
|
|
SaveSettings();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
settings = payload.Settings.ToObject<PluginSettings>();
|
2023-08-06 21:51:04 -06:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
_thread = new Thread(() =>
|
|
|
|
|
{
|
|
|
|
|
Logger.Instance.LogMessage(TracingLevel.DEBUG, "Registering for events");
|
|
|
|
|
_delegate = new Native.WinEventDelegate(WinEventProc);
|
|
|
|
|
_foregroundWindowChangedEvent = Native.RegisterForForegroundWindowChangedEvent(_delegate);
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
Logger.Instance.LogMessage(TracingLevel.DEBUG, "Starting Dispatcher");
|
|
|
|
|
_dispatcher = Dispatcher.CurrentDispatcher;
|
|
|
|
|
Dispatcher.Run();
|
|
|
|
|
Logger.Instance.LogMessage(TracingLevel.DEBUG, "Dispatcher Stopped");
|
|
|
|
|
});
|
|
|
|
|
_thread.SetApartmentState(ApartmentState.STA);
|
|
|
|
|
_thread.Start();
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
_currentAudioSession = settings.FallbackBehavior == FallbackBehavior.SystemSounds ? _audioHelper.GetSystemSounds() : _audioHelper.GetSystemVolume();
|
|
|
|
|
}
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
public override async void DialDown(DialPayload payload)
|
|
|
|
|
{
|
|
|
|
|
//dial pressed down
|
|
|
|
|
Logger.Instance.LogMessage(TracingLevel.INFO, "Dial Down");
|
|
|
|
|
await ToggleMuteAsync();
|
|
|
|
|
}
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
public override async void TouchPress(TouchpadPressPayload payload)
|
|
|
|
|
{
|
|
|
|
|
Logger.Instance.LogMessage(TracingLevel.INFO, "Touch Press");
|
|
|
|
|
if (payload.IsLongPress)
|
2023-08-06 21:51:04 -06:00
|
|
|
|
{
|
2023-08-20 20:52:48 -06:00
|
|
|
|
_audioHelper.ResetAll();
|
2023-08-06 21:51:04 -06:00
|
|
|
|
}
|
2023-08-20 20:52:48 -06:00
|
|
|
|
else
|
2023-08-06 21:51:04 -06:00
|
|
|
|
{
|
|
|
|
|
await ToggleMuteAsync();
|
|
|
|
|
}
|
2023-08-20 20:52:48 -06:00
|
|
|
|
}
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
async Task ToggleMuteAsync()
|
|
|
|
|
{
|
|
|
|
|
try
|
2023-08-06 21:51:04 -06:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (_currentAudioSession != null)
|
|
|
|
|
{
|
|
|
|
|
_currentAudioSession.ToggleMute();
|
|
|
|
|
await UpdateStateIfNeeded();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
await Connection.ShowAlert();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-20 20:52:48 -06:00
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
await Connection.ShowAlert();
|
|
|
|
|
Logger.Instance.LogMessage(TracingLevel.ERROR, $"Unable to toggle mute: {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
public override async void DialRotate(DialRotatePayload payload)
|
|
|
|
|
{
|
|
|
|
|
Logger.Instance.LogMessage(TracingLevel.INFO, "Dial Rotate");
|
|
|
|
|
//dial rotated. ticks positive for right, negative for left
|
|
|
|
|
try
|
2023-08-06 21:51:04 -06:00
|
|
|
|
{
|
|
|
|
|
if (_currentAudioSession != null)
|
|
|
|
|
{
|
|
|
|
|
_currentAudioSession.IncrementVolumeLevel(1, payload.Ticks);
|
|
|
|
|
await UpdateStateIfNeeded();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
await Connection.ShowAlert();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-20 20:52:48 -06:00
|
|
|
|
catch (Exception ex)
|
2023-08-06 21:51:04 -06:00
|
|
|
|
{
|
2023-08-20 20:52:48 -06:00
|
|
|
|
await Connection.ShowAlert();
|
|
|
|
|
Logger.Instance.LogMessage(TracingLevel.ERROR, $"Unable to toggle mute: {ex.Message}");
|
2023-08-06 21:51:04 -06:00
|
|
|
|
}
|
2023-08-20 20:52:48 -06:00
|
|
|
|
}
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
public override void DialUp(DialPayload payload)
|
|
|
|
|
{
|
|
|
|
|
//dial unpressed
|
|
|
|
|
Logger.Instance.LogMessage(TracingLevel.INFO, "Dial Up");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Dispose()
|
|
|
|
|
{
|
|
|
|
|
Logger.Instance.LogMessage(TracingLevel.DEBUG, "Disposing");
|
2023-08-06 13:46:36 -06:00
|
|
|
|
if(_foregroundWindowChangedEvent != IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
Native.UnhookWinEvent(_foregroundWindowChangedEvent);
|
|
|
|
|
}
|
2023-08-20 20:52:48 -06:00
|
|
|
|
_dispatcher.InvokeShutdown();
|
|
|
|
|
}
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
public override async void OnTick()
|
|
|
|
|
{
|
|
|
|
|
//called once every 1000ms and can be used for updating the title/image of the key
|
|
|
|
|
var activeSession = _audioHelper.GetActiveSession(settings.FallbackBehavior);
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
if(activeSession != null)
|
|
|
|
|
{
|
|
|
|
|
_currentAudioSession = activeSession;
|
2023-08-06 21:51:04 -06:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
await UpdateStateIfNeeded();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task UpdateStateIfNeeded()
|
|
|
|
|
{
|
|
|
|
|
if (_currentAudioSession != null)
|
2023-08-06 21:51:04 -06:00
|
|
|
|
{
|
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
var uiState = new UIState(_currentAudioSession);
|
|
|
|
|
|
|
|
|
|
if ( _previousState != null && uiState != null &&
|
|
|
|
|
uiState.Title == _previousState.Title &&
|
|
|
|
|
uiState.Value.Value == _previousState.Value.Value &&
|
|
|
|
|
uiState.Value.Opacity == _previousState.Value.Opacity &&
|
|
|
|
|
uiState.Indicator.Value == _previousState.Indicator.Value &&
|
|
|
|
|
uiState.Indicator.Opacity == _previousState.Indicator.Opacity &&
|
|
|
|
|
uiState.icon.Value == _previousState.icon.Value &&
|
|
|
|
|
uiState.icon.Opacity == _previousState.icon.Opacity
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
return;
|
2023-08-06 21:51:04 -06:00
|
|
|
|
}
|
2023-08-20 20:52:48 -06:00
|
|
|
|
|
|
|
|
|
await Connection.SetFeedbackAsync(uiState);
|
|
|
|
|
_previousState = uiState;
|
2023-08-06 21:51:04 -06:00
|
|
|
|
}
|
2023-08-20 20:52:48 -06:00
|
|
|
|
}
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload)
|
|
|
|
|
{
|
|
|
|
|
}
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
public override void ReceivedSettings(ReceivedSettingsPayload payload)
|
|
|
|
|
{
|
|
|
|
|
Tools.AutoPopulateSettings(settings, payload.Settings);
|
|
|
|
|
SaveSettings();
|
|
|
|
|
}
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
2023-08-20 20:52:48 -06:00
|
|
|
|
private Task SaveSettings()
|
|
|
|
|
{
|
|
|
|
|
return Connection.SetSettingsAsync(JObject.FromObject(settings));
|
|
|
|
|
}
|
2023-08-06 21:51:04 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
|
2023-08-06 13:46:36 -06:00
|
|
|
|
{
|
2023-08-20 20:52:48 -06:00
|
|
|
|
OnTick();
|
2023-08-06 13:46:36 -06:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|