Compare commits
	
		
			7 Commits
		
	
	
		
			v1.1.1
			...
			609a7bdb65
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 609a7bdb65 | |||
| 13fdfde3e5 | |||
| bbad79b4f3 | |||
| 708180dc8e | |||
| 5711ace990 | |||
| d89c8b1ffa | |||
| f94052e54b | 
| @ -36,6 +36,7 @@ public class AudioHelper | |||||||
| 		manager.GetSessionEnumerator(out var sessionEnumerator); | 		manager.GetSessionEnumerator(out var sessionEnumerator); | ||||||
|  |  | ||||||
| 		var results = new ActiveAudioSessionWrapper(); | 		var results = new ActiveAudioSessionWrapper(); | ||||||
|  | 		var currentIndex = int.MaxValue; | ||||||
|  |  | ||||||
| 		sessionEnumerator.GetCount(out var count); | 		sessionEnumerator.GetCount(out var count); | ||||||
| 		for (int i = 0; i < count; i++) | 		for (int i = 0; i < count; i++) | ||||||
| @ -45,23 +46,33 @@ public class AudioHelper | |||||||
| 			session.GetProcessId(out var sessionProcessId); | 			session.GetProcessId(out var sessionProcessId); | ||||||
| 			var audioProcess = Process.GetProcessById(sessionProcessId); | 			var audioProcess = Process.GetProcessById(sessionProcessId); | ||||||
|  |  | ||||||
| 			if (processes.Any(x => x.Id == sessionProcessId || x.ProcessName == audioProcess?.ProcessName)) | 			var index = processes.FindIndex(x => x.Id == sessionProcessId || x.ProcessName == audioProcess?.ProcessName); | ||||||
| 			{ |  | ||||||
| 				try |  | ||||||
| 				{ |  | ||||||
| 					var displayName = audioProcess.MainModule.FileVersionInfo.FileDescription; |  | ||||||
| 					if (string.IsNullOrEmpty(displayName)) |  | ||||||
| 					{ |  | ||||||
| 						displayName = audioProcess.ProcessName; |  | ||||||
| 					} |  | ||||||
| 					results.DisplayName = displayName; |  | ||||||
| 				} |  | ||||||
| 				catch |  | ||||||
| 				{ |  | ||||||
| 					results.DisplayName ??= audioProcess.ProcessName; |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				results.ExecutablePath ??= audioProcess.MainModule.FileName; | 			if (index > -1) | ||||||
|  | 			{ | ||||||
|  | 				//processes will be ordered from best to worst (starts with the app, goes to parent) | ||||||
|  | 				//so we want the display name and executable path to come from the process that is closest to the front of the list | ||||||
|  | 				//but we want all matching sessions so things like discord work right | ||||||
|  | 				if (index < currentIndex) | ||||||
|  | 				{ | ||||||
|  | 					try | ||||||
|  | 					{ | ||||||
|  | 						var displayName = audioProcess.MainModule.FileVersionInfo.FileDescription; | ||||||
|  | 						if (string.IsNullOrEmpty(displayName)) | ||||||
|  | 						{ | ||||||
|  | 							displayName = audioProcess.ProcessName; | ||||||
|  | 						} | ||||||
|  | 						results.DisplayName = displayName; | ||||||
|  | 					} | ||||||
|  | 					catch | ||||||
|  | 					{ | ||||||
|  | 						results.DisplayName = audioProcess.ProcessName; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					results.ExecutablePath = audioProcess.MainModule.FileName; | ||||||
|  |  | ||||||
|  | 					currentIndex = index; | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 				//some apps like discord have multiple volume processes. | 				//some apps like discord have multiple volume processes. | ||||||
| 				results.AddSession(session); | 				results.AddSession(session); | ||||||
| @ -137,10 +148,21 @@ public class AudioHelper | |||||||
|  |  | ||||||
| 		try | 		try | ||||||
| 		{ | 		{ | ||||||
| 			var blah = ParentProcessUtilities.GetParentProcess(pid); | 			//note. in instances where you launch a game from steam. this ends up mapping the process to both steam and to the game. which is unfortunate | ||||||
| 			if (blah != null && blah.ProcessName != "explorer" && blah.ProcessName != "svchost") | 			//The problem is that if you don't use the parent processes, then the actual steam window won't get recognized. But if you do, then games will map to steam. | ||||||
|  | 			// | ||||||
|  | 			//Additionally, I group all audio processes that match instead of just the most specific, or the first, etc. Because Discord uses two processes, one for voice chat, and one for discord sounds. | ||||||
|  | 			// | ||||||
|  | 			//Steam and Discord are both very common, and end up butting heads in the algorithm. | ||||||
|  | 			//I want to avoid special cases, but since steam and discord are both so common, i'm making an exception. | ||||||
|  | 			var parentProcess = ParentProcessUtilities.GetParentProcess(pid); | ||||||
|  | 			if (parentProcess != null  | ||||||
|  | 				&& parentProcess.ProcessName != "explorer"  | ||||||
|  | 				&& parentProcess.ProcessName != "svchost" | ||||||
|  | 				&& (parentProcess.ProcessName == "steam" && processes.Any(x => x.ProcessName == "steamwebhelper")) //only include steam if the parent process is the steamwebhelper | ||||||
|  | 				) | ||||||
| 			{ | 			{ | ||||||
| 				processes.Add(blah); | 				processes.Add(parentProcess); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		catch | 		catch | ||||||
|  | |||||||
| @ -10,6 +10,11 @@ namespace FocusVolumeControl.AudioSessions | |||||||
| 	{ | 	{ | ||||||
| 		public static float GetAdjustedVolume(float startingVolume, int step, int ticks) | 		public static float GetAdjustedVolume(float startingVolume, int step, int ticks) | ||||||
| 		{ | 		{ | ||||||
|  | 			if(step <= 0) | ||||||
|  | 			{ | ||||||
|  | 				step = 1; | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			var level = startingVolume; | 			var level = startingVolume; | ||||||
|  |  | ||||||
| 			level += 0.01f * step * ticks; | 			level += 0.01f * step * ticks; | ||||||
|  | |||||||
| @ -26,20 +26,13 @@ public class DialAction : EncoderBase | |||||||
| 		{ | 		{ | ||||||
| 			PluginSettings instance = new PluginSettings(); | 			PluginSettings instance = new PluginSettings(); | ||||||
| 			instance.FallbackBehavior = FallbackBehavior.SystemSounds; | 			instance.FallbackBehavior = FallbackBehavior.SystemSounds; | ||||||
|  | 			instance.StepSize = 1; | ||||||
| 			return instance; | 			return instance; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	private PluginSettings settings; | 	PluginSettings settings; | ||||||
|  |  | ||||||
| 	IntPtr _foregroundWindowChangedEvent; |  | ||||||
| 	Native.WinEventDelegate _delegate; |  | ||||||
|  |  | ||||||
| 	AudioHelper _audioHelper = new AudioHelper(); | 	AudioHelper _audioHelper = new AudioHelper(); | ||||||
|  |  | ||||||
| 	Thread _thread; |  | ||||||
| 	Dispatcher _dispatcher; |  | ||||||
|  |  | ||||||
| 	UIState _previousState; | 	UIState _previousState; | ||||||
|  |  | ||||||
| 	public DialAction(ISDConnection connection, InitialPayload payload) : base(connection, payload) | 	public DialAction(ISDConnection connection, InitialPayload payload) : base(connection, payload) | ||||||
| @ -54,19 +47,7 @@ public class DialAction : EncoderBase | |||||||
| 			settings = payload.Settings.ToObject<PluginSettings>(); | 			settings = payload.Settings.ToObject<PluginSettings>(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		_thread = new Thread(() => | 		WindowChangedEventLoop.Instance.WindowChanged += WindowChanged; | ||||||
| 		{ |  | ||||||
| 			Logger.Instance.LogMessage(TracingLevel.DEBUG, "Registering for events"); |  | ||||||
| 			_delegate = new Native.WinEventDelegate(WinEventProc); |  | ||||||
| 			_foregroundWindowChangedEvent = Native.RegisterForForegroundWindowChangedEvent(_delegate); |  | ||||||
|  |  | ||||||
| 			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(); |  | ||||||
|  |  | ||||||
| 		var session = _audioHelper.GetActiveSession(settings.FallbackBehavior); | 		var session = _audioHelper.GetActiveSession(settings.FallbackBehavior); | ||||||
| 		_ = UpdateStateIfNeeded(session); | 		_ = UpdateStateIfNeeded(session); | ||||||
| @ -74,19 +55,15 @@ public class DialAction : EncoderBase | |||||||
|  |  | ||||||
| 	public override void Dispose() | 	public override void Dispose() | ||||||
| 	{ | 	{ | ||||||
| 		Logger.Instance.LogMessage(TracingLevel.DEBUG, "Disposing"); | 		//Logger.Instance.LogMessage(TracingLevel.DEBUG, "Disposing"); | ||||||
| 		if (_foregroundWindowChangedEvent != IntPtr.Zero) | 		WindowChangedEventLoop.Instance.WindowChanged -= WindowChanged; | ||||||
| 		{ |  | ||||||
| 			Native.UnhookWinEvent(_foregroundWindowChangedEvent); |  | ||||||
| 		} |  | ||||||
| 		_dispatcher.InvokeShutdown(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public override async void DialDown(DialPayload payload) | 	public override async void DialDown(DialPayload payload) | ||||||
| 	{ | 	{ | ||||||
| 		try | 		try | ||||||
| 		{ | 		{ | ||||||
| 			Logger.Instance.LogMessage(TracingLevel.INFO, "Dial Down"); | 			//Logger.Instance.LogMessage(TracingLevel.INFO, "Dial Down"); | ||||||
| 			await ToggleMuteAsync(); | 			await ToggleMuteAsync(); | ||||||
| 		} | 		} | ||||||
| 		catch (Exception ex) | 		catch (Exception ex) | ||||||
| @ -100,7 +77,7 @@ public class DialAction : EncoderBase | |||||||
| 	{ | 	{ | ||||||
| 		try | 		try | ||||||
| 		{ | 		{ | ||||||
| 			Logger.Instance.LogMessage(TracingLevel.INFO, "Touch Press"); | 			//Logger.Instance.LogMessage(TracingLevel.INFO, "Touch Press"); | ||||||
| 			if (payload.IsLongPress) | 			if (payload.IsLongPress) | ||||||
| 			{ | 			{ | ||||||
| 				await ResetAllAsync(); | 				await ResetAllAsync(); | ||||||
| @ -120,7 +97,7 @@ public class DialAction : EncoderBase | |||||||
| 	{ | 	{ | ||||||
| 		try | 		try | ||||||
| 		{ | 		{ | ||||||
| 			Logger.Instance.LogMessage(TracingLevel.INFO, "Dial Rotate"); | 			//Logger.Instance.LogMessage(TracingLevel.INFO, "Dial Rotate"); | ||||||
| 			//dial rotated. ticks positive for right, negative for left | 			//dial rotated. ticks positive for right, negative for left | ||||||
| 			var activeSession = _audioHelper.Current; | 			var activeSession = _audioHelper.Current; | ||||||
| 			if (activeSession != null) | 			if (activeSession != null) | ||||||
| @ -258,7 +235,7 @@ public class DialAction : EncoderBase | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	public void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) | 	public void WindowChanged() | ||||||
| 	{ | 	{ | ||||||
| 		try | 		try | ||||||
| 		{ | 		{ | ||||||
| @ -266,7 +243,7 @@ public class DialAction : EncoderBase | |||||||
| 		} | 		} | ||||||
| 		catch (Exception ex) | 		catch (Exception ex) | ||||||
| 		{ | 		{ | ||||||
| 			Logger.Instance.LogMessage(TracingLevel.ERROR, $"Unexpected Error in DialDown:\n {ex}"); | 			Logger.Instance.LogMessage(TracingLevel.ERROR, $"Unexpected Error in Window Down:\n {ex}"); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -70,6 +70,7 @@ | |||||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> |     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||||
|     <Compile Include="UI\UIState.cs" /> |     <Compile Include="UI\UIState.cs" /> | ||||||
|     <Compile Include="UI\ValueWithOpacity.cs" /> |     <Compile Include="UI\ValueWithOpacity.cs" /> | ||||||
|  |     <Compile Include="WindowChangedEventLoop.cs" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="App.config" /> |     <None Include="App.config" /> | ||||||
|  | |||||||
							
								
								
									
										54
									
								
								src/FocusVolumeControl/WindowChangedEventLoop.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/FocusVolumeControl/WindowChangedEventLoop.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | |||||||
|  | using BarRaider.SdTools; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Runtime.InteropServices; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | using System.Windows.Threading; | ||||||
|  |  | ||||||
|  | namespace FocusVolumeControl | ||||||
|  | { | ||||||
|  | 	internal class WindowChangedEventLoop | ||||||
|  | 	{ | ||||||
|  | 		private static readonly Lazy<WindowChangedEventLoop> _lazy = new Lazy<WindowChangedEventLoop>(() => new WindowChangedEventLoop()); | ||||||
|  | 		public static WindowChangedEventLoop Instance => _lazy.Value; | ||||||
|  |  | ||||||
|  | 		readonly Thread _thread; | ||||||
|  | 		Dispatcher _dispatcher; | ||||||
|  |  | ||||||
|  | 		IntPtr _foregroundWindowChangedEvent; | ||||||
|  | 		Native.WinEventDelegate _delegate; | ||||||
|  |  | ||||||
|  | 		private WindowChangedEventLoop() | ||||||
|  | 		{ | ||||||
|  | 			_thread = new Thread(() => | ||||||
|  | 			{ | ||||||
|  | 				Logger.Instance.LogMessage(TracingLevel.DEBUG, "Starting Window Changed Event Loop"); | ||||||
|  | 				_delegate = new Native.WinEventDelegate(WinEventProc); | ||||||
|  | 				_foregroundWindowChangedEvent = Native.RegisterForForegroundWindowChangedEvent(_delegate); | ||||||
|  |  | ||||||
|  | 				_dispatcher = Dispatcher.CurrentDispatcher; | ||||||
|  | 				Dispatcher.Run(); | ||||||
|  | 				Logger.Instance.LogMessage(TracingLevel.DEBUG, "Window Changed Event Loop Stopped"); | ||||||
|  | 			}); | ||||||
|  | 			_thread.SetApartmentState(ApartmentState.STA); | ||||||
|  | 			_thread.Start(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public event Action WindowChanged; | ||||||
|  |  | ||||||
|  | 		private void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) | ||||||
|  | 		{ | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				WindowChanged?.Invoke(); | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				Logger.Instance.LogMessage(TracingLevel.ERROR, $"Unexpected Error in EventHandler:\n {ex}"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -33,7 +33,7 @@ | |||||||
|   "Name": "Focused Application Volume", |   "Name": "Focused Application Volume", | ||||||
|   "Description": "Control the volume of the focused application", |   "Description": "Control the volume of the focused application", | ||||||
|   "URL": "https://github.com/dlprows/FocusVolumeControl", |   "URL": "https://github.com/dlprows/FocusVolumeControl", | ||||||
|   "Version": "1.1.1", |   "Version": "1.1.2", | ||||||
|   "CodePath": "FocusVolumeControl", |   "CodePath": "FocusVolumeControl", | ||||||
|   "Category": "Volume Control [dlprows]", |   "Category": "Volume Control [dlprows]", | ||||||
|   "Icon": "Images/pluginIcon", |   "Icon": "Images/pluginIcon", | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user