Skip to content

Commit

Permalink
Added speech recognition, but it's not source gen'd
Browse files Browse the repository at this point in the history
  • Loading branch information
IEvangelist committed Apr 5, 2022
1 parent f622c6a commit 8a077d3
Show file tree
Hide file tree
Showing 40 changed files with 1,437 additions and 40 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
- Blazor.Geolocation
- Blazor.SpeechSynthesis.WebAssembly
- Blazor.SpeechSynthesis
- Blazor.SpeechRecognition.WebAssembly
- Blazor.SpeechRecognition
steps:
- uses: actions/checkout@v2

Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/publish-nuget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ jobs:
- Blazor.Geolocation
- Blazor.SpeechSynthesis.WebAssembly
- Blazor.SpeechSynthesis
- Blazor.SpeechRecognition.WebAssembly
- Blazor.SpeechRecognition
steps:

- name: Print tag ref
Expand Down
14 changes: 14 additions & 0 deletions blazorators.sln
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazor.SpeechSynthesis.WebA
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazor.SpeechSynthesis", "src\Blazor.SpeechSynthesis\Blazor.SpeechSynthesis.csproj", "{CC36EFCE-CB59-4541-9E1E-2DBE5D1C290E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blazor.SpeechRecognition.WebAssembly", "src\Blazor.SpeechRecognition.WebAssembly\Blazor.SpeechRecognition.WebAssembly.csproj", "{F8BC87F2-8864-49F8-B4C2-75662BEBB045}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blazor.SpeechRecognition", "src\Blazor.SpeechRecognition\Blazor.SpeechRecognition.csproj", "{7FB98CAE-0CDB-4EF8-B9BB-6C51D62252CD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -101,6 +105,14 @@ Global
{CC36EFCE-CB59-4541-9E1E-2DBE5D1C290E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC36EFCE-CB59-4541-9E1E-2DBE5D1C290E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC36EFCE-CB59-4541-9E1E-2DBE5D1C290E}.Release|Any CPU.Build.0 = Release|Any CPU
{F8BC87F2-8864-49F8-B4C2-75662BEBB045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8BC87F2-8864-49F8-B4C2-75662BEBB045}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8BC87F2-8864-49F8-B4C2-75662BEBB045}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8BC87F2-8864-49F8-B4C2-75662BEBB045}.Release|Any CPU.Build.0 = Release|Any CPU
{7FB98CAE-0CDB-4EF8-B9BB-6C51D62252CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7FB98CAE-0CDB-4EF8-B9BB-6C51D62252CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FB98CAE-0CDB-4EF8-B9BB-6C51D62252CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FB98CAE-0CDB-4EF8-B9BB-6C51D62252CD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -118,6 +130,8 @@ Global
{F54C9271-5C28-498D-9081-59EAA22FEC69} = {537EB83C-6982-40B0-801A-479DF3B17DBE}
{35E7A636-C28A-40FC-99F3-CE6A5F3C49BF} = {537EB83C-6982-40B0-801A-479DF3B17DBE}
{CC36EFCE-CB59-4541-9E1E-2DBE5D1C290E} = {537EB83C-6982-40B0-801A-479DF3B17DBE}
{F8BC87F2-8864-49F8-B4C2-75662BEBB045} = {537EB83C-6982-40B0-801A-479DF3B17DBE}
{7FB98CAE-0CDB-4EF8-B9BB-6C51D62252CD} = {537EB83C-6982-40B0-801A-479DF3B17DBE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3F86284A-32D2-4F79-B23C-7A0CB8775971}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<ProjectReference Include="..\..\src\Blazor.Geolocation.WebAssembly\Blazor.Geolocation.WebAssembly.csproj" />
<ProjectReference Include="..\..\src\Blazor.LocalStorage.WebAssembly\Blazor.LocalStorage.WebAssembly.csproj" />
<ProjectReference Include="..\..\src\Blazor.Serialization\Blazor.Serialization.csproj" />
<ProjectReference Include="..\..\src\Blazor.SpeechRecognition.WebAssembly\Blazor.SpeechRecognition.WebAssembly.csproj" />
<ProjectReference Include="..\..\src\Blazor.SpeechSynthesis.WebAssembly\Blazor.SpeechSynthesis.WebAssembly.csproj" />
</ItemGroup>

Expand Down
28 changes: 28 additions & 0 deletions samples/Blazor.ExampleConsumer/Components/Code.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@typeparam T where T : class

@if (Value is not null)
{
<pre class="bg-dark @(_textClass) fs-4 p-4">
<code>
@{
var opts = new JsonSerializerOptions()
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
}
@Value?.ToJson(opts)
</code>
</pre>
}

@code {
[Parameter, EditorRequired]
public T? Value { get; set; } = default!;

[Parameter]
public bool IsError { get; set; }

string _textClass => IsError ? "text-warning" : "text-info";
}
1 change: 1 addition & 0 deletions samples/Blazor.ExampleConsumer/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
global using System.Text.Json.Serialization;
global using Microsoft.JSInterop;
global using Microsoft.AspNetCore.Components;
global using static System.Globalization.CultureInfo;
14 changes: 2 additions & 12 deletions samples/Blazor.ExampleConsumer/Pages/ClientPosition.razor
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,8 @@
}

@{
var (bgClass, json) = (_position, _positionError) switch
{
(null, { }) => ("bg-danger", _positionError.ToJson(_opts)),
({ }, null) => ("bg-dark", _position.ToJson(_opts)),
_ => ("", null)
};
if (bgClass is not "" && json is not null)
{
<pre class="@bgClass text-info fs-4 p-4">
<code>@json</code>
</pre>
}
<Code Value=@_position T=GeolocationPosition IsError=false />
<Code Value=@_positionError T=GeolocationPositionError IsError=true />

<BingMap Position=@_position />
}
29 changes: 29 additions & 0 deletions samples/Blazor.ExampleConsumer/Pages/ListenToMe.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@page "/listen"

<PageTitle>Speech-to-text</PageTitle>

<p>This page demonstrates the source generated <code>Blazor.SpeechRecongition.WebAssembly</code> package.</p>

<div class="mb-3 w-75">
<label for="text" class="form-label">
Speech-to-text
</label>
<textarea class="form-control" id="text"
readonly=@_isRecognizingSpeech rows="6" @bind=@_transcript>
</textarea>
</div>
<Code Value=@_errorEvent T=SpeechRecognitionErrorEvent IsError=true />

<button type="button" class="btn btn-lg btn-primary"
@onclick=@OnRecognizeSpeechClick>
@if (_isRecognizingSpeech)
{
<span class="oi oi-media-stop"></span>
<span class="ps-2">Stop</span>
}
else
{
<span class="oi oi-microphone"></span>
<span class="ps-2">Listen</span>
}
</button>
76 changes: 76 additions & 0 deletions samples/Blazor.ExampleConsumer/Pages/ListenToMe.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) David Pine. All rights reserved.
// Licensed under the MIT License.

namespace Blazor.ExampleConsumer.Pages;

public sealed partial class ListenToMe : IAsyncDisposable
{
bool _isRecognizingSpeech = false;
SpeechRecognitionErrorEvent? _errorEvent;
string? _transcript;

[Inject]
public ISpeechRecognitionService SpeechRecognition { get; set; } = null!;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await SpeechRecognition.InitializeModuleAsync();
}
}

void OnRecognizeSpeechClick()
{
if (_isRecognizingSpeech)
{
SpeechRecognition.CancelSpeechRecognition(false);
}
else
{
var bcp47Tag = CurrentUICulture.Name;
SpeechRecognition.RecognizeSpeech(
bcp47Tag,
OnRecognized,
OnError,
OnStarted,
OnEnded);
}
}

void OnStarted()
{
_isRecognizingSpeech = true;
StateHasChanged();
}

void OnEnded()
{
_isRecognizingSpeech = false;
StateHasChanged();
}

void OnError(SpeechRecognitionErrorEvent errorEvent)
{
_errorEvent = errorEvent;
StateHasChanged();
}

void OnRecognized(string transcript)
{
_transcript = _transcript switch
{
null => transcript,
_ => $"{_transcript.Trim()} {transcript}".Trim()
};
StateHasChanged();
}

public async ValueTask DisposeAsync()
{
if (SpeechRecognition is not null)
{
await SpeechRecognition.DisposeAsync();
}
}
}
3 changes: 2 additions & 1 deletion samples/Blazor.ExampleConsumer/Pages/ReadToMe.razor
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@

<div class="btn-group btn-group-lg">
<button type="button" class="btn btn-lg btn-primary" @onclick=@Speak>
Speak
<span class="oi oi-audio"></span>
<span class="ps-2">Speak</span>
</button>
<button type="button" class="btn btn-lg btn-warning" title="Pause" @onclick=@SpeechSynthesis.Pause>
<span class="oi oi-media-pause"></span>
Expand Down
1 change: 0 additions & 1 deletion samples/Blazor.ExampleConsumer/Pages/ReadToMe.razor.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) David Pine. All rights reserved.
// Licensed under the MIT License.

using System.Runtime.CompilerServices;
using Humanizer;

namespace Blazor.ExampleConsumer.Pages;
Expand Down
17 changes: 4 additions & 13 deletions samples/Blazor.ExampleConsumer/Pages/Sandbox.razor
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,10 @@
</a>
}
</h1>
<pre class="bg-dark text-info fs-4 p-4">
<code>
@{
var opts = new JsonSerializerOptions()
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
}
@(_position?.ToJson(opts) ?? _positionError?.ToJson(opts))
</code>
</pre>

<Code Value=@_position T=GeolocationPosition IsError=false />
<Code Value=@_positionError T=GeolocationPositionError IsError=true />

<BingMap Position=@_position />

@code {
Expand Down
1 change: 1 addition & 0 deletions samples/Blazor.ExampleConsumer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@
builder.Services.AddLocalStorageServices();
builder.Services.AddGeolocationServices();
builder.Services.AddSpeechSynthesisServices();
builder.Services.AddSpeechRecognitionServices();

await builder.Build().RunAsync();
7 changes: 6 additions & 1 deletion samples/Blazor.ExampleConsumer/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@
<span class="oi oi-map" aria-hidden="true"></span> Geolocation
</NavLink>
</div>
<div class="nav-item px-3">
<div class="nav-item px-3">
<NavLink class="nav-link" href="speak">
<span class="oi oi-audio" aria-hidden="true"></span> Text-to-speech
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="listen">
<span class="oi oi-microphone" aria-hidden="true"></span> Speech-to-text
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="sandbox">
<span class="oi oi-inbox" aria-hidden="true"></span> Sandbox
Expand Down
6 changes: 3 additions & 3 deletions src/Blazor.LocalStorage.WebAssembly/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The [`Blazor.LocalStorage.WebAssembly`](https://www.nuget.org/packages/Blazor.Lo

## Get started

After the NuGet package is added as a reference, call the `AddLocalStorageServices` method to register the `IStorageService` service type.
After the NuGet package is added as a reference, call the `AddLocalStorageServices` method to register the `ILocalStorageService` service type.

```csharp
using Microsoft.AspNetCore.Components.Web;
Expand All @@ -25,7 +25,7 @@ builder.Services.AddLocalStorageServices();
await builder.Build().RunAsync();
```

Anywhere needed within your Razor component, or Blazor client code — either `@inject` or `[Inject]` the `IStorageService` type. The interface takes the following shape:
Anywhere needed within your Razor component, or Blazor client code — either `@inject` or `[Inject]` the `ILocalStorageService` type. The interface takes the following shape:

```csharp
using Blazor.Serialization.Extensions;
Expand All @@ -37,7 +37,7 @@ namespace Microsoft.JSInterop;
/// <summary>
/// Source generated interface definition of the <c>Storage</c> type.
/// </summary>
public interface IStorageService
public interface ILocalStorageService
{
/// <summary>
/// Source generated implementation of <c>window.localStorage.clear</c>.
Expand Down
6 changes: 3 additions & 3 deletions src/Blazor.LocalStorage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The [`Blazor.LocalStorage`](https://www.nuget.org/packages/Blazor.LocalStorage)

## Get started

After the NuGet package is added as a reference, call the `AddLocalStorageServices` method to register the `IStorageService` service type.
After the NuGet package is added as a reference, call the `AddLocalStorageServices` method to register the `ILocalStorageService` service type.

```csharp
var builder = WebApplication.CreateBuilder(args);
Expand All @@ -27,7 +27,7 @@ app.MapFallbackToPage("/_Host");
app.Run();
```

Anywhere needed within your Razor component, or Blazor client code — either `@inject` or `[Inject]` the `IStorageService` type. The interface takes the following shape:
Anywhere needed within your Razor component, or Blazor client code — either `@inject` or `[Inject]` the `ILocalStorageService` type. The interface takes the following shape:

```csharp
using Blazor.Serialization.Extensions;
Expand All @@ -39,7 +39,7 @@ namespace Microsoft.JSInterop;
/// <summary>
/// Source generated interface definition of the <c>Storage</c> type.
/// </summary>
public interface IStorageService
public interface ILocalStorageService
{
/// <summary>
/// Source generated implementation of <c>window.localStorage.clear</c>.
Expand Down
6 changes: 3 additions & 3 deletions src/Blazor.SessionStorage.WebAssembly/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The [`Blazor.SessionStorage.WebAssembly`](https://www.nuget.org/packages/Blazor.

## Get started

After the NuGet package is added as a reference, call the `AddSessionStorageServices` method to register the `IStorageService` service type.
After the NuGet package is added as a reference, call the `AddSessionStorageServices` method to register the `ISessionStorageService` service type.

```csharp
using Microsoft.AspNetCore.Components.Web;
Expand All @@ -25,7 +25,7 @@ builder.Services.AddSessionStorageServices();
await builder.Build().RunAsync();
```

Anywhere needed within your Razor component, or Blazor client code — either `@inject` or `[Inject]` the `IStorageService` type. The interface takes the following shape:
Anywhere needed within your Razor component, or Blazor client code — either `@inject` or `[Inject]` the `ISessionStorageService` type. The interface takes the following shape:

```csharp
using Blazor.Serialization.Extensions;
Expand All @@ -37,7 +37,7 @@ namespace Microsoft.JSInterop;
/// <summary>
/// Source generated interface definition of the <c>Storage</c> type.
/// </summary>
public interface IStorageService
public interface ISessionStorageService
{
/// <summary>
/// Source generated implementation of <c>window.sessionStorage.clear</c>.
Expand Down
6 changes: 3 additions & 3 deletions src/Blazor.SessionStorage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The [`Blazor.SessionStorage`](https://www.nuget.org/packages/Blazor.SessionStora

## Get started

After the NuGet package is added as a reference, call the `AddSessionStorageServices` method to register the `IStorageService` service type.
After the NuGet package is added as a reference, call the `AddSessionStorageServices` method to register the `ISessionStorageService` service type.

```csharp
var builder = WebApplication.CreateBuilder(args);
Expand All @@ -27,7 +27,7 @@ app.MapFallbackToPage("/_Host");
app.Run();
```

Anywhere needed within your Razor component, or Blazor client code — either `@inject` or `[Inject]` the `IStorageService` type. The interface takes the following shape:
Anywhere needed within your Razor component, or Blazor client code — either `@inject` or `[Inject]` the `ISessionStorageService` type. The interface takes the following shape:

```csharp
using Blazor.Serialization.Extensions;
Expand All @@ -39,7 +39,7 @@ namespace Microsoft.JSInterop;
/// <summary>
/// Source generated interface definition of the <c>Storage</c> type.
/// </summary>
public interface IStorageService
public interface ISessionStorageService
{
/// <summary>
/// Source generated implementation of <c>window.sessionStorage.clear</c>.
Expand Down
Loading

0 comments on commit 8a077d3

Please sign in to comment.