diff --git a/Directory.Build.props b/Directory.Build.props index a52e14f..c4cf7ed 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ - 0.9.1 + 0.9.2 diff --git a/GitHubReleaseNotes.txt b/GitHubReleaseNotes.txt index 462d82d..8c8f0fb 100644 --- a/GitHubReleaseNotes.txt +++ b/GitHubReleaseNotes.txt @@ -1,3 +1,3 @@ https://github.com/StefH/GitHubReleaseNotes -GitHubReleaseNotes.exe --output ReleaseNotes.md --skip-empty-releases --exclude-labels question invalid doc --version 0.9.1 \ No newline at end of file +GitHubReleaseNotes.exe --output ReleaseNotes.md --skip-empty-releases --exclude-labels question invalid doc --version 0.9.2 \ No newline at end of file diff --git a/examples/Howler.Blazor-AudioPlayer/Pages/Example.razor b/examples/Howler.Blazor-AudioPlayer/Pages/Example.razor index 1babf42..a75c277 100644 --- a/examples/Howler.Blazor-AudioPlayer/Pages/Example.razor +++ b/examples/Howler.Blazor-AudioPlayer/Pages/Example.razor @@ -1,107 +1,131 @@ -@page "/" -@using Howler.Blazor.Components - - -@inject IHowl Howl -@inject IHowlGlobal HowlGlobal - -
- - - - @* - *@ -
TotalTime : @TotalTime
-
State : @State
-
Supported Codes : @SupportedCodes
-
ErrorMessage : @ErrorMessage
-
- -@code { - protected TimeSpan TotalTime; - protected string State = "-"; - protected string SupportedCodes; - public string ErrorMessage = ""; - - /// - /// InvalidOperationException: JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendererd. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method. - /// - protected override async Task OnAfterRenderAsync(bool firstRender) - { - await base.OnAfterRenderAsync(firstRender); - - if (firstRender) - { - // Display all supported codecs - var codecs = await HowlGlobal.GetCodecs(); - SupportedCodes = string.Join(", ", codecs); - - StateHasChanged(); - } - } - - protected override void OnInitialized() - { - base.OnInitialized(); - - // Register callbacks - Howl.OnPlay += e => - { - ErrorMessage = string.Empty; - State = "Playing"; - TotalTime = e.TotalTime; - - StateHasChanged(); - }; - - Howl.OnStop += e => - { - State = "Stopped"; - - StateHasChanged(); - }; - - Howl.OnPause += e => - { - State = "Paused"; - - StateHasChanged(); - }; - - Howl.OnPlayError += e => - { - ErrorMessage = $"OnPlayError : {e.Error}"; - - StateHasChanged(); - }; - - Howl.OnLoadError += e => - { - ErrorMessage = $"OnLoadError : {e.Error}"; - - StateHasChanged(); - }; - } - - protected async Task Play() - { - ErrorMessage = string.Empty; - - var sources = new[] - { - "https://lookandstore.blob.core.windows.net/863da396-6e44-4b3b-8db1-e447d87b121f/instrumental_mp3_637141046337946343_99lfo/instrumental_mp3?sv=2018-03-28&sr=b&sig=96LJ7bycF3lrtiWbVP5tK6%2BOOIJKfq7eYPO%2FjOT72ns%3D&se=2022-10-04T18%3A23%3A53Z&sp=rl", - "https://www.healingfrequenciesmusic.com/wp-content/uploads/2015/03/Love-Abounds-Sample.mp3?_=1" - }; - await Howl.Play(sources); - } - - protected async Task Stop() - { - await Howl.Stop(); - } - - protected async Task Pause() - { - await Howl.Pause(); - } +@page "/" +@using Howler.Blazor.Components + + +@inject IHowl Howl +@inject IHowlGlobal HowlGlobal + +
+ + + + + + + + + + + + + + + + + +
Play an audio file with source location
Play an audio file with source location and format
Pause
Stop
+
+ + @* + *@ +
TotalTime : @TotalTime
+
State : @State
+
Supported Codes : @SupportedCodes
+
ErrorMessage : @ErrorMessage
+
+ +@code { + protected TimeSpan TotalTime; + protected string State = "-"; + protected string SupportedCodes; + public string ErrorMessage = ""; + + /// + /// InvalidOperationException: JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendererd. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method. + /// + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + + if (firstRender) + { + // Display all supported codecs + var codecs = await HowlGlobal.GetCodecs(); + SupportedCodes = string.Join(", ", codecs); + + StateHasChanged(); + } + } + + protected override void OnInitialized() + { + base.OnInitialized(); + + // Register callbacks + Howl.OnPlay += e => + { + ErrorMessage = string.Empty; + State = "Playing"; + TotalTime = e.TotalTime; + + StateHasChanged(); + }; + + Howl.OnStop += e => + { + State = "Stopped"; + + StateHasChanged(); + }; + + Howl.OnPause += e => + { + State = "Paused"; + + StateHasChanged(); + }; + + Howl.OnPlayError += e => + { + ErrorMessage = $"OnPlayError : {e.Error}"; + + StateHasChanged(); + }; + + Howl.OnLoadError += e => + { + ErrorMessage = $"OnLoadError : {e.Error}"; + + StateHasChanged(); + }; + } + + protected async Task Play1() + { + ErrorMessage = string.Empty; + + await Howl.Play("https://www.healingfrequenciesmusic.com/wp-content/uploads/2015/03/Love-Abounds-Sample.mp3?_=1"); + } + + protected async Task Play2() + { + ErrorMessage = string.Empty; + + var options = new HowlOptions + { + Sources = new[] { "https://lookandstore.blob.core.windows.net/863da396-6e44-4b3b-8db1-e447d87b121f/instrumental_mp3_637141046337946343_99lfo/instrumental_mp3?sv=2018-03-28&sr=b&sig=96LJ7bycF3lrtiWbVP5tK6%2BOOIJKfq7eYPO%2FjOT72ns%3D&se=2022-10-04T18%3A23%3A53Z&sp=rl" }, + Formats = new[] { "mp3" } + }; + await Howl.Play(options); + } + + protected async Task Stop() + { + await Howl.Stop(); + } + + protected async Task Pause() + { + await Howl.Pause(); + } } \ No newline at end of file diff --git a/examples/Howler.Blazor-AudioPlayer/Startup.cs b/examples/Howler.Blazor-AudioPlayer/Startup.cs index 6d9b11d..a14c575 100644 --- a/examples/Howler.Blazor-AudioPlayer/Startup.cs +++ b/examples/Howler.Blazor-AudioPlayer/Startup.cs @@ -21,6 +21,7 @@ public Startup(IConfiguration configuration) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { + services.AddCors(); services.AddRazorPages(); services.AddServerSideBlazor(); @@ -44,6 +45,9 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseHttpsRedirection(); + // Needed to play files from blob-storage ??? + app.UseCors(x => x.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()); + ConfigureStaticFiles(app); app.UseRouting(); diff --git a/src/Howler.Blazor/Components/Howl.cs b/src/Howler.Blazor/Components/Howl.cs index 1aa768b..9f23f87 100644 --- a/src/Howler.Blazor/Components/Howl.cs +++ b/src/Howler.Blazor/Components/Howl.cs @@ -32,9 +32,9 @@ public ValueTask Play(params string[] sources) { Guard.HasNoNulls(sources, nameof(sources)); - var options = new HowlSettings + var options = new HowlOptions { - Sources = sources // .Select(WebUtility.UrlEncode).ToArray() + Sources = sources }; return Play(options); @@ -49,7 +49,7 @@ public ValueTask Play(byte[] audio, string mimetype) var audioAsBase64 = Convert.ToBase64String(audio); string html5AudioUrl = $"data:{mimetype};base64,{audioAsBase64}"; - var options = new HowlSettings + var options = new HowlOptions { Sources = new[] { html5AudioUrl } }; @@ -57,11 +57,13 @@ public ValueTask Play(byte[] audio, string mimetype) return _runtime.InvokeAsync("howl.play", _dotNetObjectReference, options); } - public ValueTask Play(HowlSettings settings) + public ValueTask Play(HowlOptions options) { - Guard.NotNull(settings, nameof(settings)); + Guard.HasNoNulls(options.Sources, nameof(options.Sources)); + Guard.Condition(options.Sources, sources => sources.Length > 0, nameof(options.Sources)); + // Guard.Condition(options.Formats, formats => formats == null || formats.Length == options.Sources.Length, nameof(options.Formats)); - return _runtime.InvokeAsync("howl.play", _dotNetObjectReference, settings); + return _runtime.InvokeAsync("howl.play", _dotNetObjectReference, options); } public ValueTask Stop() diff --git a/src/Howler.Blazor/Components/HowlSettings.cs b/src/Howler.Blazor/Components/HowlOptions.cs similarity index 70% rename from src/Howler.Blazor/Components/HowlSettings.cs rename to src/Howler.Blazor/Components/HowlOptions.cs index 9659ddd..005ffe7 100644 --- a/src/Howler.Blazor/Components/HowlSettings.cs +++ b/src/Howler.Blazor/Components/HowlOptions.cs @@ -1,6 +1,6 @@ namespace Howler.Blazor.Components { - public class HowlSettings + public class HowlOptions { /// /// The sources to the track(s) to be loaded for the sound (URLs or base64 data URIs). @@ -9,6 +9,12 @@ public class HowlSettings /// public string[] Sources { get; set; } + /// + /// Howler.js automatically detects your file format from the extension, + /// but you may also specify a format in situations where extraction won't work (such as with a SoundCloud stream). + /// + public string[] Formats { get; set; } + /// /// Set to true to force HTML5 Audio. /// This should be used for large audio files so that you don't have to wait for the full file to be downloaded and decoded before playing. diff --git a/src/Howler.Blazor/Components/IHowl.cs b/src/Howler.Blazor/Components/IHowl.cs index 99e41d6..3d3bf76 100644 --- a/src/Howler.Blazor/Components/IHowl.cs +++ b/src/Howler.Blazor/Components/IHowl.cs @@ -21,7 +21,7 @@ public interface IHowl : IHowlEvents ValueTask Play(byte[] audio, string mimeType); - ValueTask Play(HowlSettings settings); + ValueTask Play(HowlOptions options); ValueTask Stop(); diff --git a/src/Howler.Blazor/Validation/Guard.cs b/src/Howler.Blazor/Validation/Guard.cs index 7c8c96e..033adcd 100644 --- a/src/Howler.Blazor/Validation/Guard.cs +++ b/src/Howler.Blazor/Validation/Guard.cs @@ -109,7 +109,7 @@ public static string NullButNotEmpty(string value, [InvokerParameterName] [NotNu return value; } - public static IList HasNoNulls(IList value, [InvokerParameterName] [NotNull] string parameterName) + public static IEnumerable HasNoNulls(IEnumerable value, [InvokerParameterName] [NotNull] string parameterName) where T : class { NotNull(value, parameterName); diff --git a/src/Howler.Blazor/wwwroot/JsInteropHowl.js b/src/Howler.Blazor/wwwroot/JsInteropHowl.js index 89807aa..6eb947f 100644 --- a/src/Howler.Blazor/wwwroot/JsInteropHowl.js +++ b/src/Howler.Blazor/wwwroot/JsInteropHowl.js @@ -9,6 +9,7 @@ window.howl = { howl = new Howl({ src: options.sources, + format: options.formats, html5: options.html5, onplay: async function (id) { const duration = Math.round(howl.duration());