OBS Websocket and initial blur, still some bugs

This commit is contained in:
glax 2024-04-16 00:48:45 +02:00
parent f9c1f4e739
commit 7e22fa58e3
3 changed files with 238 additions and 2 deletions

227
OBSBlur/OBS/Blur.cs Normal file
View File

@ -0,0 +1,227 @@
using Newtonsoft.Json.Linq;
using OBSBlur.Window;
using OBSWebsocketDotNet;
using OBSWebsocketDotNet.Communication;
using OBSWebsocketDotNet.Types;
using OBSWebsocketDotNet.Types.Events;
namespace OBSBlur.OBS;
public class Blur
{
WindowManager windowManager = new ();
private OBSWebsocket _websocket = new ();
private string currentScene;
private string[] enabledScenes;
private string[] blurPrograms;
private Dictionary<IntPtr, uint> windowHandleSceneItems = new();
public Blur(string obsUrl, string obsPassword, string[] enabledScenes, string[] blurPrograms)
{
this.enabledScenes = enabledScenes;
this.blurPrograms = blurPrograms;
windowManager.UpdateInterval = 1;
_websocket.CurrentProgramSceneChanged += WebsocketOnCurrentProgramSceneChanged;
_websocket.Connected += WebsocketOnConnected;
_websocket.Disconnected += WebsocketOnDisconnected;
_websocket.ConnectAsync(obsUrl, obsPassword);
windowManager.WindowsChanged += WindowManagerOnWindowsChanged;
windowManager.WindowZOrderChanged += WindowManagerOnWindowZOrderChanged;
}
private void UpdateBlurs(WindowInfo[]? windowInfos = null, IntPtr[]? zOrder = null)
{
if (!enabledScenes.Contains(currentScene))
return;
if (!_websocket.IsConnected)
return;
windowInfos ??= windowManager.WindowInfos;
zOrder ??= windowManager.WindowZOrder;
bool addRemove = true;
foreach (IntPtr window in zOrder)
{
WindowInfo windowInfo = windowInfos.FirstOrDefault(w => w.WindowHandle == window);
if(windowInfo is {WindowHandle: 0x0})
continue;
bool blur = false;
foreach(string program in blurPrograms)
if (windowInfo.ProcessInfo.ProcessName.Contains(program, StringComparison.OrdinalIgnoreCase))
blur = true;
if(blur && addRemove)
BlurWindow(windowInfo);
else if(blur && addRemove is false)
DeleteBlur(windowInfo);
if (windowInfo.WindowPlacement.ShowCmd is ShowWindowCommands.Maximize)
addRemove = false;
}
foreach(WindowInfo windowInfo in windowInfos)
if (windowInfo.WindowPlacement.ShowCmd is ShowWindowCommands.ShowMinimized &&
windowHandleSceneItems.ContainsKey(windowInfo.WindowHandle))
{
DeleteBlur(windowInfo);
windowHandleSceneItems.Remove(windowInfo.WindowHandle);
}
}
private void BlurWindow(WindowInfo windowInfo)
{
if(windowHandleSceneItems.ContainsKey(windowInfo.WindowHandle))
MoveBlur(windowInfo);
else
AddBlur(windowInfo);
}
private void AddBlur(WindowInfo windowInfo)
{
Dictionary<string, object> request = new()
{
{"sceneName", currentScene},
{"sceneItemId", GetBlurSource()}
};
try
{
JObject response = _websocket.SendRequest("DuplicateSceneItem", JObject.FromObject(request));
windowHandleSceneItems.Add(windowInfo.WindowHandle, response["sceneItemId"]!.Value<uint>());
MoveBlur(windowInfo);
}
catch (ErrorResponseException e)
{
Console.WriteLine("No Scene Item with name 'Blur' found.");
throw;
}
}
private void MoveBlur(WindowInfo windowInfo)
{
if (!windowHandleSceneItems.ContainsKey(windowInfo.WindowHandle))
return;
SceneItemTransformInfo info = windowInfo.WindowPlacement.ShowCmd switch
{
ShowWindowCommands.Maximize => new ()
{
X = 0,
Y = 0,
BoundsHeight = 1080, //TODO desktop res
BoundsWidth = 1920,
BoundsType = SceneItemBoundsType.OBS_BOUNDS_STRETCH,
Alignnment = 5
},
_ => new()
{
X = windowInfo.WindowPlacement.NormalPosition.Left,
Y = windowInfo.WindowPlacement.NormalPosition.Top,
BoundsHeight = windowInfo.WindowPlacement.NormalPosition.Height,
BoundsWidth = windowInfo.WindowPlacement.NormalPosition.Width,
BoundsType = SceneItemBoundsType.OBS_BOUNDS_STRETCH,
Alignnment = 5
},
};
Dictionary<string, object> request = new()
{
{"sceneName", currentScene},
{"sceneItemId", windowHandleSceneItems[windowInfo.WindowHandle]},
{"sceneItemTransform", info}
};
_websocket.SendRequest("SetSceneItemTransform", JObject.FromObject(request));
Dictionary<string, object> request2 = new()
{
{"sceneName", currentScene},
{"sceneItemId", windowHandleSceneItems[windowInfo.WindowHandle]},
{"sceneItemEnabled", true}
};
_websocket.SendRequest("SetSceneItemEnabled", JObject.FromObject(request2));
}
private void DeleteBlur(WindowInfo windowInfo)
{
if (!windowHandleSceneItems.ContainsKey(windowInfo.WindowHandle))
return;
Dictionary<string, object> request = new()
{
{"sceneName", currentScene},
{"sceneItemId", windowHandleSceneItems[windowInfo.WindowHandle]}
};
_websocket.SendRequest("RemoveSceneItem", JObject.FromObject(request));
windowHandleSceneItems.Remove(windowInfo.WindowHandle);
}
private uint GetBlurSource()
{
Dictionary<string, string> request = new()
{
{"sceneName", currentScene},
{"sourceName", "Blur"}
};
try
{
JObject response = _websocket.SendRequest("GetSceneItemId", JObject.FromObject(request));
return response["sceneItemId"]!.Value<uint>();
}
catch (ErrorResponseException e)
{
Console.WriteLine("No Scene Item with name 'Blur' found.");
throw;
}
}
private void WindowManagerOnWindowZOrderChanged(IntPtr[] neworder)
{
/*
uint i = 0;
string prnt = "";
foreach (IntPtr windowHandle in order)
{
WindowInfo windowInfo = windowManager.WindowInfos.FirstOrDefault(w => w.WindowHandle == windowHandle);
if(windowInfo.WindowHandle is 0x0)
continue;
prnt += $"{++i,3} {windowInfo}\n";
}
Console.Clear();
Console.WriteLine(prnt);*/
Console.WriteLine($"Z-order changed {DateTime.UtcNow:O}");
UpdateBlurs(zOrder: neworder);
}
private void WindowManagerOnWindowsChanged(WindowInfo[] before, WindowInfo[] after)
{
string prnt = "";
foreach (WindowInfo windowInfo in after)
prnt += $"{windowInfo}\n";
Console.WriteLine(prnt);
Console.WriteLine($"Windows changed {DateTime.UtcNow:O}");
UpdateBlurs(windowInfos: after);
}
private void WebsocketOnDisconnected(object? sender, ObsDisconnectionInfo e)
{
Console.WriteLine($"Obs Disconnected {DateTime.UtcNow:O}");
}
private void WebsocketOnConnected(object? sender, EventArgs e)
{
currentScene = _websocket.GetCurrentProgramScene();
Console.WriteLine($"Obs Connected. Current Scene {currentScene} {DateTime.UtcNow:O}");
UpdateBlurs();
}
private void WebsocketOnCurrentProgramSceneChanged(object? sender, ProgramSceneChangedEventArgs e)
{
currentScene = e.SceneName;
Console.WriteLine($"Obs Scene Changed -> {currentScene} {DateTime.UtcNow:O}");
UpdateBlurs();
}
}

View File

@ -7,4 +7,8 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="obs-websocket-dotnet" Version="5.0.0.3" />
</ItemGroup>
</Project>

View File

@ -1,3 +1,8 @@
using OBSBlur.Window;
using OBSBlur.OBS;
new WindowManager();
Blur _ = new Blur("ws://localhost:4444", "", new []{"Desktop"}, new []{ "Discord", "VRCX" });
while (true)
Thread.Sleep(100);