/// <summary> /// /// </summary> /// <param name="recognition"></param> /// <param name="recording"></param> /// <param name="exceptionsBag"></param> /// <param name="cancellationToken"></param> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentException"></exception> /// <returns></returns> public static async Task BindRecordingAsync( this IStreamingRecognition recognition, IRecording recording, ExceptionsBag?exceptionsBag = null, CancellationToken cancellationToken = default) { recognition = recognition ?? throw new ArgumentNullException(nameof(recognition)); recording = recording ?? throw new ArgumentNullException(nameof(recording)); if (recording.Settings.Format is not AudioFormat.Raw) { if (!recording.Header.Any()) { throw new ArgumentException("recording.Header is empty."); } await recognition.WriteAsync(recording.Header, cancellationToken).ConfigureAwait(false); } if (recording.Data.Any()) { await recognition.WriteAsync(recording.Data, cancellationToken).ConfigureAwait(false); } async void OnDataReceived(object?_, byte[] bytes) { try { await recognition.WriteAsync(bytes, cancellationToken).ConfigureAwait(false); } catch (Exception exception) { exceptionsBag?.OnOccurred(exception); } } void OnStopped(object?o, byte[] bytes) { try { recording.DataReceived -= OnDataReceived; recording.Stopped -= OnStopped; } catch (Exception exception) { exceptionsBag?.OnOccurred(exception); } } recording.DataReceived += OnDataReceived; recording.Stopped += OnStopped; }
public static async Task BaseModuleTest <T1, T2>( string name1, string name2, Func <ExceptionsBag, T1, T2, CancellationToken, Task> testFunc) where T1 : class, IModule where T2 : class, IModule { using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(15)); var cancellationToken = cancellationTokenSource.Token; var exceptions = new ExceptionsBag(); await using var manager = new ModuleManager <IModule>( Path.Combine(Path.GetTempPath(), $"H.Containers.Tests_{name1}_{name2}")); manager.ExceptionOccurred += (_, exception) => { Console.WriteLine($"ExceptionOccurred: {exception}"); exceptions.OnOccurred(exception); // ReSharper disable once AccessToDisposedClosure cancellationTokenSource.Cancel(); }; using var instance1 = await manager.AddModuleAsync <T1>( CreateContainer (name1), name1, name1, ResourcesUtilities.ReadFileAsBytes($"{name1}.zip"), cancellationToken); using var instance2 = await manager.AddModuleAsync <T2>( CreateContainer (name2), name2, name2, ResourcesUtilities.ReadFileAsBytes($"{name2}.zip"), cancellationToken); Assert.IsNotNull(instance1); Assert.IsNotNull(instance2); foreach (var instance in new IModule[] { instance1, instance2 }) { instance.EnableLog(); } await testFunc(exceptions, instance1, instance2, cancellationToken); try { await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); } catch (OperationCanceledException) { } exceptions.EnsureNoExceptions(); }
/// <summary> /// Stop when values for <paramref name="silenceInMilliseconds"></paramref> of /// <paramref name="bufferInMilliseconds"/> will be lower than <paramref name="threshold"></paramref>. <br/> /// NAudioRecorder produces 100 DataReceived events per seconds. <br/> /// It can be set up by NAudioRecorder.Delay property. <br/> /// </summary> /// <param name="recording"></param> /// <param name="bufferInMilliseconds"></param> /// <param name="silenceInMilliseconds"></param> /// <param name="threshold"></param> /// <param name="exceptions"></param> public static IRecording StopWhenSilence( this IRecording recording, int bufferInMilliseconds = 3000, int silenceInMilliseconds = 2500, double threshold = 0.02, ExceptionsBag?exceptions = null) { recording = recording ?? throw new ArgumentNullException(nameof(recording)); var delay = (int)recording.Settings.Delay.TotalMilliseconds; var bufferSize = bufferInMilliseconds / delay; var requiredCount = silenceInMilliseconds / delay; var detector = new SilenceDetector(recording.Settings, bufferSize, requiredCount, threshold); detector.Detected += async(_, _) => { try { await recording.StopAsync().ConfigureAwait(false); } catch (Exception exception) { exceptions?.OnOccurred(exception); } }; recording.DataReceived += (_, bytes) => { try { detector.Write(bytes); } catch (Exception exception) { exceptions?.OnOccurred(exception); } }; return(recording); }
public static void EnableLogging( this IServiceBase service, ExceptionsBag?exceptions = null, CancellationTokenSource?source = null) { service.ExceptionOccurred += (_, exception) => { Console.WriteLine($"{nameof(service.ExceptionOccurred)}: {exception}"); exceptions?.OnOccurred(exception); source?.Cancel(); }; if (service is ICommandProducer commandProducer) { commandProducer.CommandReceived += (_, value) => { Console.WriteLine($"{nameof(commandProducer.CommandReceived)}: {value}"); }; commandProducer.AsyncCommandReceived += (_, value, _) => { Console.WriteLine($"{nameof(commandProducer.AsyncCommandReceived)}: {value}"); return(Task.FromResult(EmptyArray <IValue> .Value)); }; } switch (service) { case HookService hookService: hookService.UpCaught += (_, value) => { Console.WriteLine($"{nameof(hookService.UpCaught)}: {value}"); }; hookService.DownCaught += (_, value) => { Console.WriteLine($"{nameof(hookService.DownCaught)}: {value}"); }; hookService.BoundUpCaught += (_, value) => { Console.WriteLine($"{nameof(hookService.BoundUpCaught)}: {value.Keys}, {value.Command}"); }; hookService.BoundDownCaught += (_, value) => { Console.WriteLine($"{nameof(hookService.BoundDownCaught)}: {value.Keys}, {value.Command}"); }; break; case RecognitionService recognitionService: recognitionService.PreviewCommandReceived += (_, value) => { Console.WriteLine($"{nameof(recognitionService.PreviewCommandReceived)}: {value}"); }; break; case RunnerService runnerService: runnerService.CallRunning += (_, call) => { Console.WriteLine($"{nameof(runnerService.CallRunning)}: {call}"); }; runnerService.CallRan += (_, call) => { Console.WriteLine($"{nameof(runnerService.CallRan)}: {call}"); }; runnerService.CallCancelled += (_, call) => { Console.WriteLine($"{nameof(runnerService.CallCancelled)}: {call}"); }; runnerService.NotSupported += (_, command) => { Console.WriteLine($"{nameof(runnerService.NotSupported)}: {command}"); }; break; } }
/// <summary> /// Dispose is required!. /// </summary> /// <param name="recognizer"></param> /// <param name="recorder"></param> /// <param name="exceptionsBag"></param> /// <param name="cancellationToken"></param> /// <exception cref="ArgumentNullException"></exception> /// <returns></returns> public static async Task <IStreamingRecognition> StartStreamingRecognitionAsync( this IRecognizer recognizer, IRecorder recorder, ExceptionsBag?exceptionsBag = null, CancellationToken cancellationToken = default) { recognizer = recognizer ?? throw new ArgumentNullException(nameof(recognizer)); recorder = recorder ?? throw new ArgumentNullException(nameof(recorder)); if (!recognizer.SupportedStreamingSettings.Any()) { throw new ArgumentException("Recognizer does not support streaming recognition."); } var isStopped = false; var settings = recognizer.SupportedStreamingSettings.First(); var recording = await recorder.StartAsync(settings, cancellationToken) .ConfigureAwait(false); recording.StopWhenSilence(); var recognition = await recognizer.StartStreamingRecognitionAsync(settings, cancellationToken) .ConfigureAwait(false); recognition.Stopping += async(_, _) => { if (isStopped) { return; } try { await recording.StopAsync(cancellationToken).ConfigureAwait(false); } catch (Exception exception) { exceptionsBag?.OnOccurred(exception); } finally { recording.Dispose(); } }; recording.Stopped += async(_, _) => { isStopped = true; try { await recognition.StopAsync(cancellationToken).ConfigureAwait(false); } catch (Exception exception) { exceptionsBag?.OnOccurred(exception); } finally { recording.Dispose(); } }; await recognition.BindRecordingAsync(recording, exceptionsBag, cancellationToken).ConfigureAwait(false); return(recognition); }
/// <summary> /// /// </summary> /// <param name="process"></param> /// <param name="cancellationToken"></param> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="InvalidOperationException"></exception> /// <returns></returns> public async Task <Rectangle> SelectAsync( IProcess <ICommand> process, CancellationToken cancellationToken = default) { process = process ?? throw new ArgumentNullException(nameof(process)); if (Window == null) { await InitializeAsync(cancellationToken).ConfigureAwait(false); } Window = Window ?? throw new InvalidOperationException("Window is null."); var scaleFactor = await Dispatcher.InvokeAsync( () => Window.GetDpi(), DispatcherPriority.Normal, cancellationToken); var startPoint = new Point(); var endPoint = new Point(); var currentPoint = new Point(); using var exceptions = new ExceptionsBag(); using var hook = new LowLevelMouseHook { GenerateMouseMoveEvents = true, }; hook.ExceptionOccurred += (_, exception) => { // ReSharper disable once AccessToDisposedClosure exceptions.OnOccurred(exception); }; var isInitialized = false; hook.Move += (_, args) => { currentPoint = args.Position; if (isInitialized) { return; } startPoint = currentPoint.ToApp(scaleFactor); endPoint = startPoint; isInitialized = true; }; hook.Start(); using var timer = new Timer(15); timer.Elapsed += (_, _) => { if (!isInitialized) { return; } endPoint = currentPoint.ToApp(scaleFactor); Dispatcher.Invoke(() => { ApplyRectangle( Window, startPoint, endPoint); }); }; timer.Start(); await Dispatcher.InvokeAsync(() => { ApplyRectangle( Window, startPoint, endPoint); Window.Border.Visibility = Visibility.Visible; }, DispatcherPriority.Normal, cancellationToken); await process.WaitAsync(cancellationToken).ConfigureAwait(false); timer.Dispose(); hook.Dispose(); await Dispatcher.InvokeAsync(() => { Window.Border.Visibility = Visibility.Hidden; }, DispatcherPriority.Normal, cancellationToken); return(startPoint .ToRectangle(endPoint) .Normalize() .ToPhysical(scaleFactor)); }