Squashed commit of the following:
commit d6c92ea0ad95c0b640ac9c7df48197412c7518e3
Author: haritabh-z01 <haritabh.z01+github@gmail.com>
Date: Thu Aug 21 23:27:44 2025 +0530
fix: unpacking amical/smart-whisper dep
commit 87819819bb12c07b94f5b52cbb0ea42a452c16e2
Author: haritabh-z01 <haritabh.z01+github@gmail.com>
Date: Thu Aug 21 17:41:02 2025 +0530
fix: unpacking of smart-whisper
commit 81cec166834606cbff2cdd2e750dcc1fb769d4f3
Author: haritabh-z01 <haritabh.z01+github@gmail.com>
Date: Thu Aug 21 16:08:39 2025 +0530
chore: re-enable mac builds
commit f13069c1f350fe06c69aa8f16af41f983f34131e
Author: haritabh-z01 <haritabh.z01+github@gmail.com>
Date: Thu Aug 21 13:06:26 2025 +0530
feat: add smart-whisper package with updated build configuration
commit a24e06856cc595f5e6c5d914090531716d208d2a
Author: haritabh-z01 <haritabh.z01+github@gmail.com>
Date: Thu Aug 21 11:37:25 2025 +0530
chore: bump smart-whisper ver
commit 98f84b6f89c873370f1bb356f11c97dab0185ab7
Author: haritabh-z01 <haritabh.z01+github@gmail.com>
Date: Wed Aug 20 08:59:55 2025 +0530
feat: release wf updates for win builds
commit a85825d362f2a27fdef7b49533a9139aea4785b7
Author: haritabh-z01 <haritabh.z01+github@gmail.com>
Date: Wed Aug 20 08:36:13 2025 +0530
feat: add windows support basics
This commit is contained in:
parent
2d852a0d14
commit
17d034be80
59 changed files with 10524 additions and 3079 deletions
333
packages/native-helpers/windows-helper/src/RpcHandler.cs
Normal file
333
packages/native-helpers/windows-helper/src/RpcHandler.cs
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using WindowsHelper.Models;
|
||||
using WindowsHelper.Services;
|
||||
|
||||
namespace WindowsHelper
|
||||
{
|
||||
public class RpcHandler
|
||||
{
|
||||
private readonly JsonSerializerOptions jsonOptions;
|
||||
private readonly AccessibilityService accessibilityService;
|
||||
private readonly AudioService audioService;
|
||||
private Action<string>? audioCompletionHandler;
|
||||
|
||||
public RpcHandler()
|
||||
{
|
||||
// Use the generated converter settings from the models
|
||||
jsonOptions = WindowsHelper.Models.Converter.Settings;
|
||||
|
||||
accessibilityService = new AccessibilityService();
|
||||
audioService = new AudioService();
|
||||
audioService.SoundPlaybackCompleted += OnSoundPlaybackCompleted;
|
||||
}
|
||||
|
||||
public void ProcessRpcRequests(CancellationToken cancellationToken)
|
||||
{
|
||||
LogToStderr("RpcHandler: Starting RPC request processing loop.");
|
||||
|
||||
try
|
||||
{
|
||||
string? line;
|
||||
while (!cancellationToken.IsCancellationRequested && (line = Console.ReadLine()) != null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
LogToStderr("Warning: Received empty line on stdin.");
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var request = JsonSerializer.Deserialize<RpcRequest>(line, jsonOptions);
|
||||
if (request != null)
|
||||
{
|
||||
LogToStderr($"RpcHandler: Received RPC Request ID {request.Id}, Method: {request.Method}");
|
||||
_ = Task.Run(() => HandleRpcRequest(request), cancellationToken);
|
||||
}
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
LogToStderr($"Error decoding RpcRequest from stdin: {ex.Message}. Line: {line}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogToStderr($"Fatal error in RPC processing: {ex.Message}");
|
||||
}
|
||||
|
||||
LogToStderr("RpcHandler: RPC request processing loop finished.");
|
||||
}
|
||||
|
||||
private async void HandleRpcRequest(RpcRequest request)
|
||||
{
|
||||
RpcResponse response;
|
||||
|
||||
try
|
||||
{
|
||||
switch (request.Method)
|
||||
{
|
||||
case Method.GetAccessibilityTreeDetails:
|
||||
response = await HandleGetAccessibilityTreeDetails(request);
|
||||
break;
|
||||
|
||||
case Method.GetAccessibilityContext:
|
||||
response = await HandleGetAccessibilityContext(request);
|
||||
break;
|
||||
|
||||
case Method.PasteText:
|
||||
response = HandlePasteText(request);
|
||||
break;
|
||||
|
||||
case Method.MuteSystemAudio:
|
||||
response = await HandleMuteSystemAudio(request);
|
||||
return; // Response sent after audio playback
|
||||
|
||||
case Method.RestoreSystemAudio:
|
||||
response = HandleRestoreSystemAudio(request);
|
||||
break;
|
||||
|
||||
default:
|
||||
LogToStderr($"Method not found: {request.Method} for ID: {request.Id}");
|
||||
response = new RpcResponse
|
||||
{
|
||||
Id = request.Id.ToString(),
|
||||
Error = new Error
|
||||
{
|
||||
Code = -32601,
|
||||
Message = $"Method not found: {request.Method}"
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogToStderr($"Error handling request {request.Id}: {ex.Message}");
|
||||
response = new RpcResponse
|
||||
{
|
||||
Id = request.Id.ToString(),
|
||||
Error = new Error
|
||||
{
|
||||
Code = -32603,
|
||||
Message = $"Internal error: {ex.Message}"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
SendRpcResponse(response);
|
||||
}
|
||||
|
||||
private async Task<RpcResponse> HandleGetAccessibilityTreeDetails(RpcRequest request)
|
||||
{
|
||||
LogToStderr($"Handling getAccessibilityTreeDetails for ID: {request.Id}");
|
||||
|
||||
GetAccessibilityTreeDetailsParams? parameters = null;
|
||||
if (request.Params != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var json = JsonSerializer.Serialize(request.Params, jsonOptions);
|
||||
parameters = JsonSerializer.Deserialize<GetAccessibilityTreeDetailsParams>(json, jsonOptions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogToStderr($"Error decoding params: {ex.Message}");
|
||||
return new RpcResponse
|
||||
{
|
||||
Id = request.Id.ToString(),
|
||||
Error = new Error
|
||||
{
|
||||
Code = -32602,
|
||||
Message = $"Invalid params: {ex.Message}",
|
||||
Data = request.Params
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Get accessibility tree on UI thread
|
||||
var tree = await Task.Run(() => accessibilityService.FetchAccessibilityTree(parameters?.RootId));
|
||||
|
||||
return new RpcResponse
|
||||
{
|
||||
Id = request.Id.ToString(),
|
||||
Result = new GetAccessibilityTreeDetailsResult { Tree = tree }
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<RpcResponse> HandleGetAccessibilityContext(RpcRequest request)
|
||||
{
|
||||
LogToStderr($"Handling getAccessibilityContext for ID: {request.Id}");
|
||||
|
||||
GetAccessibilityContextParams? parameters = null;
|
||||
if (request.Params != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var json = JsonSerializer.Serialize(request.Params, jsonOptions);
|
||||
parameters = JsonSerializer.Deserialize<GetAccessibilityContextParams>(json, jsonOptions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogToStderr($"Error decoding params: {ex.Message}");
|
||||
return new RpcResponse
|
||||
{
|
||||
Id = request.Id.ToString(),
|
||||
Error = new Error
|
||||
{
|
||||
Code = -32602,
|
||||
Message = $"Invalid params: {ex.Message}",
|
||||
Data = request.Params
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var editableOnly = parameters?.EditableOnly ?? false;
|
||||
var context = await Task.Run(() => accessibilityService.GetAccessibilityContext(editableOnly));
|
||||
|
||||
return new RpcResponse
|
||||
{
|
||||
Id = request.Id.ToString(),
|
||||
Result = new GetAccessibilityContextResult { Context = context }
|
||||
};
|
||||
}
|
||||
|
||||
private RpcResponse HandlePasteText(RpcRequest request)
|
||||
{
|
||||
LogToStderr($"Handling pasteText for ID: {request.Id}");
|
||||
|
||||
if (request.Params == null)
|
||||
{
|
||||
return new RpcResponse
|
||||
{
|
||||
Id = request.Id.ToString(),
|
||||
Error = new Error
|
||||
{
|
||||
Code = -32602,
|
||||
Message = "Missing params for pasteText"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var json = JsonSerializer.Serialize(request.Params, jsonOptions);
|
||||
var parameters = JsonSerializer.Deserialize<PasteTextParams>(json, jsonOptions);
|
||||
|
||||
if (parameters != null)
|
||||
{
|
||||
var success = accessibilityService.PasteText(parameters.Transcript);
|
||||
return new RpcResponse
|
||||
{
|
||||
Id = request.Id.ToString(),
|
||||
Result = new PasteTextResult
|
||||
{
|
||||
Success = success,
|
||||
Message = success ? "Pasted successfully" : "Paste failed"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogToStderr($"Error processing pasteText: {ex.Message}");
|
||||
}
|
||||
|
||||
return new RpcResponse
|
||||
{
|
||||
Id = request.Id.ToString(),
|
||||
Error = new Error
|
||||
{
|
||||
Code = -32603,
|
||||
Message = "Error during paste operation"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<RpcResponse> HandleMuteSystemAudio(RpcRequest request)
|
||||
{
|
||||
LogToStderr($"Handling muteSystemAudio for ID: {request.Id}");
|
||||
|
||||
// Store the request ID for the completion handler
|
||||
var requestId = request.Id.ToString();
|
||||
|
||||
audioCompletionHandler = (id) =>
|
||||
{
|
||||
LogToStderr($"rec-start.mp3 finished playing. Proceeding to mute system audio. ID: {id}");
|
||||
var success = audioService.MuteSystemAudio();
|
||||
var response = new RpcResponse
|
||||
{
|
||||
Id = id,
|
||||
Result = new MuteSystemAudioResult
|
||||
{
|
||||
Success = success,
|
||||
Message = success ? "Mute command sent" : "Failed to send mute command"
|
||||
}
|
||||
};
|
||||
SendRpcResponse(response);
|
||||
audioCompletionHandler = null;
|
||||
};
|
||||
|
||||
// Play sound and wait for completion
|
||||
await audioService.PlaySound("rec-start", requestId);
|
||||
|
||||
// Return dummy response (real response sent after audio completion)
|
||||
return new RpcResponse { Id = request.Id.ToString() };
|
||||
}
|
||||
|
||||
private RpcResponse HandleRestoreSystemAudio(RpcRequest request)
|
||||
{
|
||||
LogToStderr($"Handling restoreSystemAudio for ID: {request.Id}");
|
||||
|
||||
var success = audioService.RestoreSystemAudio();
|
||||
if (success)
|
||||
{
|
||||
// Play sound asynchronously (don't wait)
|
||||
_ = audioService.PlaySound("rec-stop", request.Id.ToString());
|
||||
}
|
||||
|
||||
return new RpcResponse
|
||||
{
|
||||
Id = request.Id.ToString(),
|
||||
Result = new RestoreSystemAudioResult
|
||||
{
|
||||
Success = success,
|
||||
Message = success ? "Restore command sent" : "Failed to send restore command"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void OnSoundPlaybackCompleted(object? sender, string requestId)
|
||||
{
|
||||
audioCompletionHandler?.Invoke(requestId);
|
||||
}
|
||||
|
||||
private void SendRpcResponse(RpcResponse response)
|
||||
{
|
||||
try
|
||||
{
|
||||
var json = JsonSerializer.Serialize(response, jsonOptions);
|
||||
LogToStderr($"[RpcHandler] Sending response to stdout: {json}");
|
||||
Console.WriteLine(json);
|
||||
Console.Out.Flush();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogToStderr($"Error encoding RpcResponse: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void LogToStderr(string message)
|
||||
{
|
||||
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||
Console.Error.WriteLine($"[{timestamp}] {message}");
|
||||
Console.Error.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue