Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
ο»Ώ#pragma checksum "E:\fluentui-blazor-community-extensions\src\Core\Components\FloatingButton\FluentCxFloatingButton.razor" "{8829d00f-11b8-4213-878b-770e8597ac16}" "c63f5265c750f1122162591bd5f009c3206d869a26fc294ae0f0d5c505f1fbd2"
ο»Ώ#pragma checksum "D:\TFS\Personnels\Microsoft\src\Core\Components\FloatingButton\FluentCxFloatingButton.razor" "{8829d00f-11b8-4213-878b-770e8597ac16}" "c63f5265c750f1122162591bd5f009c3206d869a26fc294ae0f0d5c505f1fbd2"
// <auto-generated/>
#pragma warning disable 1591
namespace
#nullable restore
#line (1,12)-(1,48) "E:\fluentui-blazor-community-extensions\src\Core\Components\FloatingButton\FluentCxFloatingButton.razor"
#line (1,12)-(1,48) "D:\TFS\Personnels\Microsoft\src\Core\Components\FloatingButton\FluentCxFloatingButton.razor"
FluentUI.Blazor.Community.Components

#line default
Expand All @@ -17,13 +17,13 @@ namespace
using global::System.Threading.Tasks;
using global::Microsoft.AspNetCore.Components;
#nullable restore
#line (1,2)-(1,43) "E:\fluentui-blazor-community-extensions\src\Core\_Imports.razor"
#line (1,2)-(1,43) "D:\TFS\Personnels\Microsoft\src\Core\_Imports.razor"
using Microsoft.AspNetCore.Components.Web

#nullable disable
;
#nullable restore
#line (2,2)-(2,48) "E:\fluentui-blazor-community-extensions\src\Core\_Imports.razor"
#line (2,2)-(2,48) "D:\TFS\Personnels\Microsoft\src\Core\_Imports.razor"
using Microsoft.FluentUI.AspNetCore.Components

#nullable disable
Expand All @@ -33,7 +33,7 @@ namespace
#nullable restore
public partial class FluentCxFloatingButton :
#nullable restore
#line (2,11)-(2,23) "E:\fluentui-blazor-community-extensions\src\Core\Components\FloatingButton\FluentCxFloatingButton.razor"
#line (2,11)-(2,23) "D:\TFS\Personnels\Microsoft\src\Core\Components\FloatingButton\FluentCxFloatingButton.razor"
FluentButton

#line default
Expand All @@ -46,7 +46,7 @@ public partial class FluentCxFloatingButton :
protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
#nullable restore
#line (4,2)-(8,1) "E:\fluentui-blazor-community-extensions\src\Core\Components\FloatingButton\FluentCxFloatingButton.razor"
#line (4,2)-(8,1) "D:\TFS\Personnels\Microsoft\src\Core\Components\FloatingButton\FluentCxFloatingButton.razor"
if (IsVisible)
{
base.BuildRenderTree(__builder);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ο»Ώ#pragma checksum "E:\fluentui-blazor-community-extensions\src\Core\_Imports.razor" "{8829d00f-11b8-4213-878b-770e8597ac16}" "d152b9916444bc13c0c63bebf3aba36aa917067fe32d156426ae9a3d93832788"
ο»Ώ#pragma checksum "D:\TFS\Personnels\Microsoft\src\Core\_Imports.razor" "{8829d00f-11b8-4213-878b-770e8597ac16}" "d152b9916444bc13c0c63bebf3aba36aa917067fe32d156426ae9a3d93832788"
// <auto-generated/>
#pragma warning disable 1591
namespace FluentUI.Blazor.Community.Components
Expand All @@ -10,13 +10,13 @@ namespace FluentUI.Blazor.Community.Components
using global::System.Threading.Tasks;
using global::Microsoft.AspNetCore.Components;
#nullable restore
#line (1,2)-(1,43) "E:\fluentui-blazor-community-extensions\src\Core\_Imports.razor"
#line (1,2)-(1,43) "D:\TFS\Personnels\Microsoft\src\Core\_Imports.razor"
using Microsoft.AspNetCore.Components.Web

#nullable disable
;
#nullable restore
#line (2,2)-(2,48) "E:\fluentui-blazor-community-extensions\src\Core\_Imports.razor"
#line (2,2)-(2,48) "D:\TFS\Personnels\Microsoft\src\Core\_Imports.razor"
using Microsoft.FluentUI.AspNetCore.Components

#nullable disable
Expand Down
5 changes: 5 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
<!-- Independent from TargetFrameWorks-->
<ItemGroup>
<!-- Demo Apps -->
<PackageVersion Include="FFMpegCore" Version="5.4.0" />
<PackageVersion Include="MetadataExtractor" Version="2.9.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.0" />
<PackageVersion Include="LoxSmoke.DocXml" Version="3.8.0" />
<!-- Main dependencies -->
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="10.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.StaticFiles" Version="2.3.9" />
<PackageVersion Include="Microsoft.FluentUI.AspNetCore.Components" Version="5.0.0-preview.26012.1" />
<!-- Shared dependencies -->
<PackageVersion Include="Markdig.Signed" Version="0.43.0" />
Expand All @@ -28,6 +31,8 @@
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="coverlet.msbuild" Version="6.0.4" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="TagLibSharp" Version="2.3.0" />
<PackageVersion Include="TagLibSharp2" Version="0.6.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
<PackageVersion Include="xunit.v3" Version="3.2.1" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: Audio
icon: SoundWaveCircle
route: /Audio
---

# Audio

The audio component allows you to play audio files in your application.
It supports various audio formats and provides controls for play, pause, and volume.
We don't provide an implementation of IAudioMetadataProvider so this function are disabled by defaut :

* Properties
* Audio list

## Examples

{{ AudioDefaultExample }}


## API Audio

{{ API Type=Audio }}

Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
ο»Ώο»Ώ@using Microsoft.AspNetCore.StaticFiles
@using Microsoft.JSInterop
@implements IDisposable

<p>
The FluentCxAudio component can plays many audio files.
You can play, pause, move to next or previous track, show the playlist, manage volume, download track.
To download a track, if the track is on an outside website, you need to configure CORS.
To be able to use the metadata of the audio media, you need to implement your own extractor using <code>IAudioMetadataProvider</code>

The FluentCxAudio has 4 views :

<FluentStack Wrap HorizontalGap="4px">
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Default" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Compact" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Minimal" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Floating" />
</FluentStack>

The visualizer has 8 modes for now :

<FluentStack HorizontalGap="4px" Wrap>
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Spectrum" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Waveform" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Spatial" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Vortex" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Particles" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="RadialWaveform" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Tunnel" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Constellation" />
<FluentBadge Appearance="BadgeAppearance.Tint" Color="BadgeColor.Brand" Content="Fractal" />
</FluentStack>
</p>

<FluentStack Orientation="Orientation.Vertical">
<FluentMessageBar Intent="MessageBarIntent.Warning" AllowDismiss=false>
The HTML Audio Element has an issue when the user uses the seek bar.
</FluentMessageBar>

<div style="height: 600px; margin-top: 5px">
<FluentStack Orientation="Orientation.Vertical">
<FluentStack HorizontalGap="4px">
<FluentSelect Items="@(Enum.GetValues<AudioPlayerView>())"
TOption="AudioPlayerView"
Label="View"
@bind-Value=_view />

<FluentSelect Items="@(Enum.GetValues<VisualizerMode>())"
TOption="VisualizerMode"
Label="Visualizer"
@bind-Value=_mode />
</FluentStack>

<FluentStack Style="flex:1; min-height:0;">
<FluentInputFile Id="my-file-uploader"
Mode="InputFileMode.SaveToTemporaryFolder"
Multiple="true"
MaximumFileCount="10"
MaximumFileSize="@(10*1024*1024)"
Accept="audio/*"
@bind-ProgressPercent="@ProgressPercent"
OnCompleted="@OnCompletedAsync"
Style="height: 300px;">
<ChildContent>
<label for="my-file-uploader">
<FluentIcon Value="@(new @Icons.Regular.Size24.ArrowUpload())" />
</label>

<div>
Drag files here you wish to upload,
or <label for="my-file-uploader">browse</label>
for them<span style="color: red;">*</span>.
<br />
<em>Maximum of 10 files allowed.</em>
</div>
</ChildContent>
</FluentInputFile>

<FluentCxAudio VisualizerMode="@_mode" View="@_view">
@foreach (var item in _audioFiles)
{
<AudioTrackItem Source="@GetPath(item.Value)" />
}
</FluentCxAudio>
</FluentStack>
</FluentStack>
</div>

</FluentStack>

@code {
private VisualizerMode _mode;
private AudioPlayerView _view = AudioPlayerView.Default;

int ProgressPercent = 0;
private readonly Dictionary<string, string> _audioFiles = [];
private readonly List<FluentInputFileEventArgs> _files = [];
private readonly Dictionary<string, AudioMetadata> _metadataCache = [];

[Inject]
private IJSRuntime Runtime { get; set; } = null!;

private static string GetPath(string path)
{
if (path.StartsWith("blob"))
{
return path;
}

var index = path.IndexOf("uploads");

if (index >= 0)
{
return path[(index - 1)..].Replace("\\", "/");
}

return path.Replace(Directory.GetCurrentDirectory(), string.Empty)
.Replace("wwwroot", string.Empty)
.Replace("\\", "/")
.Substring(2);
}

private async Task OnCompletedAsync(IEnumerable<FluentInputFileEventArgs> files)
{
foreach (var file in files)
{
var newFileName = $"RenamedFile_{Guid.NewGuid()}{Path.GetExtension(file.Name)}";
var filePath = newFileName;

if (System.OperatingSystem.IsBrowser())
{
var provider = new FileExtensionContentTypeProvider();
if (!provider.TryGetContentType(file.Name, out var contentType))
{
contentType = "application/octet-stream";
}

filePath = await Runtime.InvokeAsync<string>("getBlobUrl", contentType, File.ReadAllBytes(file.LocalFile!.FullName));
}
else
{
filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads", newFileName);
var directory = Path.GetDirectoryName(filePath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory!);
}

await using var stream = File.OpenRead(file.LocalFile!.FullName);
await using var fileStream = File.Create(filePath);
await stream.CopyToAsync(fileStream);
}

if (!_audioFiles.ContainsKey(file.Name))
{
_audioFiles.Add(file.Name, filePath);
}

if (!_files.Contains(file))
{
_files.Add(file);
}
}

await Task.Delay(500);
ProgressPercent = 0;
}

public void Dispose()
{
try
{
foreach (var file in _audioFiles)
{
if (File.Exists(file.Value))
{
File.Delete(file.Value);
}
}

foreach (var file in _files)
{
if (file.LocalFile is not null && File.Exists(file.LocalFile.FullName))
{
File.Delete(file.LocalFile.FullName);
}
}
}
catch { }
}
}
Loading