Skip to content

Commit

Permalink
Feature/add audio recording (#35)
Browse files Browse the repository at this point in the history
* Initial dump of things

* Musings on how the recording could look

* Hacked together sample to try and prove it works

* Feature/add audio recording - tested on Windows, Mac, Android (#39)

* Fix (#37)

* Add Speed property (#26)

* Add Speed property to AudioPlayer

* Add Speed property to sample app and handle speed limitations on different Android devices

* Add handling for exceptions, speed out of range and Android API level < 23

* Add SpeedOutOfRangeException handling in sample application

* Add Speed property to NET6_0 definition

* Add CanSetSpeed handing in Sample App

* Fix bad merge whoops

* Fix speed clamping on iOS and Android

* Fix Windows Speed

* PR Feedback

* Update Sample

* Update AudioPlayer.net.cs

* Update MusicPlayerPageViewModel.cs

* Update src/Plugin.Maui.Audio/AudioPlayer.android.cs

* Update src/Plugin.Maui.Audio/AudioPlayer.net.cs

Co-authored-by: Shaun Lawrence <[email protected]>

Co-authored-by: Johan Svensson <[email protected]>
Co-authored-by: Johan Svensson <[email protected]>
Co-authored-by: Gerald Versluis <[email protected]>
Co-authored-by: Shaun Lawrence <[email protected]>
Co-authored-by: Gerald Versluis <[email protected]>

* Update README with Speed related properties (#38)

* Update README.md

* Update README.md

* Windows and Android recording tested.  iOS not yet tested.

* Add NSMicrophoneUsageDescription to Info.plist

* loosen permission on mic for MacCatalyst

* implemented LastDuration for recorder

* try to get player to play again but CollectionView will not take 2nd click

* duration working for both recorder and player

* <ProvisioningType>automatic</ProvisioningType>

* removed all warnings by dealing with nullability

* build nuget package

* Fix funky formatting and remove unnecessary audio player bits

* Removed unnecessary recording bits

* A bit more tidy up

* Recorder page shows the time recording

* Smoother audio recording experience on macOS

* Recommended way to check for permissions

* Make Android non blocking on StartAsync

* XML comments and further tidy up

* Fix windows compilation errors

* Revert "Merge branch 'main' into pr/39"

This reverts commit 415a6bd, reversing
changes made to 2d00bbc.

* Remove auto added bits

* Apply suggestions from code review

Co-authored-by: Gerald Versluis <[email protected]>

* Some docs

---------

Co-authored-by: Gerald Versluis <[email protected]>
Co-authored-by: Johan Svensson <[email protected]>
Co-authored-by: Johan Svensson <[email protected]>
Co-authored-by: Johan Svensson <[email protected]>
Co-authored-by: Shaun Lawrence <[email protected]>
Co-authored-by: Gerald Versluis <[email protected]>

* Merge Speed functionality

* Update CI

* Revert "Update CI"

This reverts commit de9e99a.

* Update CI

* Update AudioPlayer.android.cs

* Apply suggestions from code review

---------

Co-authored-by: charles david young <[email protected]>
Co-authored-by: Gerald Versluis <[email protected]>
Co-authored-by: Johan Svensson <[email protected]>
Co-authored-by: Johan Svensson <[email protected]>
Co-authored-by: Johan Svensson <[email protected]>
Co-authored-by: Gerald Versluis <[email protected]>
  • Loading branch information
7 people authored Sep 4, 2023
1 parent b486393 commit 56346a1
Show file tree
Hide file tree
Showing 41 changed files with 1,327 additions and 509 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-sample.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
dotnet-version: 7.0.x
- name: Install .NET MAUI
run: dotnet workload install maui
- name: Restore dependencies
Expand Down
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Plugin.Maui.Audio

`Plugin.Maui.Audio` provides the ability to play audio inside a .NET MAUI application.
`Plugin.Maui.Audio` provides the ability to play and record audio inside a .NET MAUI application.

## Getting Started

* Available on NuGet: <http://www.nuget.org/packages/Plugin.Maui.Audio> [![NuGet](https://img.shields.io/nuget/v/Plugin.Maui.Audio.svg?label=NuGet)](https://www.nuget.org/packages/Plugin.Maui.Audio/)

## API Usage

`Plugin.Maui.Audio` provides the `AudioManager` class that allows for the creation of `AudioPlayer`s. The `AudioManager` can be used with or without dependency injection.
`Plugin.Maui.Audio` provides the `AudioManager` class that allows for the creation of `AudioPlayer`s and `AudioRecorder`s. The `AudioManager` can be used with or without dependency injection.

### `AudioManager`

Expand Down Expand Up @@ -138,7 +138,37 @@ Set the current playback position (in seconds).

Stop playback and set the current position to the beginning.

# Acknowledgements
### AudioRecorder

You can create an `AudioRecorder` through the `AudioManager` and its `CreateRecorder` method.

Once you have created an `AudioRecorder` you can interact with it in the following ways:

#### Properties

##### `CanRecordAudio`

Gets whether the device is capable of recording audio.

##### `IsRecording`

Gets whether the recorder is currently recording audio.

#### Methods

##### `StartAsync()`

Start recording audio to disk in a randomly generated file.

##### `StartAsync(string filePath)`

Start recording audio to disk in the supplied filePath.

##### `StopAsync()`

Stop recording and return the `IAudioSource` instance with the recording data.

## Acknowledgements

This project could not have came to be without these projects and people, thank you! <3

Expand Down
6 changes: 3 additions & 3 deletions samples/AudioPlayerSample/AudioPlayerSample.csproj
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0-android;net6.0-ios;net6.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net6.0-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks>net7.0-android;net7.0-ios;net7.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> -->
<!-- <TargetFrameworks>$(TargetFrameworks);net7.0-tizen</TargetFrameworks> -->
<OutputType>Exe</OutputType>
<RootNamespace>AudioPlayerSample</RootNamespace>
<UseMaui>true</UseMaui>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ public object ConvertBack(object value, Type targetType, object parameter, Cultu
{
throw new NotSupportedException();
}
}

}
18 changes: 14 additions & 4 deletions samples/AudioPlayerSample/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,23 @@ public static MauiApp CreateMauiApp()
builder.Services.AddTransient<MyLibraryPage>();
builder.Services.AddTransient<MyLibraryPageViewModel>();

builder.Services.AddTransient<MusicPlayerPage>();
builder.Services.AddTransient<MusicPlayerPageViewModel>();

Routing.RegisterRoute(Routes.MusicPlayer.RouteName, typeof(MusicPlayerPage));
RegisterPageRoute<AudioRecorderPage, AudioRecorderPageViewModel>(Routes.AudioRecorder.RouteName, builder.Services);
RegisterPageRoute<MusicPlayerPage, MusicPlayerPageViewModel>(Routes.MusicPlayer.RouteName, builder.Services);

builder.Services.AddSingleton(AudioManager.Current);

return builder.Build();
}

static void RegisterPageRoute<TPage, TPageViewModel>(
string route,
IServiceCollection services)
where TPage : ContentPage
where TPageViewModel : BaseViewModel
{
Routing.RegisterRoute(route, typeof(TPage));

services.AddTransient(typeof(TPage));
services.AddTransient(typeof(TPageViewModel));
}
}
37 changes: 37 additions & 0 deletions samples/AudioPlayerSample/Pages/AudioRecorderPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewmodels="clr-namespace:AudioPlayerSample.ViewModels"
xmlns:converters="clr-namespace:AudioPlayerSample.Converters"
x:Class="AudioPlayerSample.Pages.AudioRecorderPage"
Title="Audio Recorder"
x:DataType="viewmodels:AudioRecorderPageViewModel">

<ContentPage.Resources>
<converters:SecondsToStringConverter x:Key="SecondsToStringConverter" />
</ContentPage.Resources>

<Grid>
<VerticalStackLayout
HorizontalOptions="Center"
VerticalOptions="Center">

<Button
Text="Start"
Command="{Binding StartCommand}" />

<Button
Text="Stop"
Command="{Binding StopCommand}" />

<Button
Text="Play"
Command="{Binding PlayCommand}" />

<Label
Text="{Binding RecordingTime, Converter={StaticResource SecondsToStringConverter}}" />
</VerticalStackLayout>

</Grid>

</ContentPage>
11 changes: 11 additions & 0 deletions samples/AudioPlayerSample/Pages/AudioRecorderPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace AudioPlayerSample.Pages;

public partial class AudioRecorderPage : ContentPage
{
public AudioRecorderPage(ViewModels.AudioRecorderPageViewModel audioRecorderPageViewModel)
{
InitializeComponent();

BindingContext = audioRecorderPageViewModel;
}
}
2 changes: 1 addition & 1 deletion samples/AudioPlayerSample/Pages/MusicPlayerPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ protected override void OnDisappearing()

((MusicPlayerPageViewModel)BindingContext).TidyUp();
}
}
}
61 changes: 36 additions & 25 deletions samples/AudioPlayerSample/Pages/MyLibraryPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,42 @@
</Style>
</ContentPage.Resources>

<CollectionView ItemsSource="{Binding Music}"
SelectionMode="Single"
SelectedItem="{Binding SelectedMusicItem}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewmodels:MusicItemViewModel">
<Border Style="{StaticResource border_gallery_card}">
<Grid ColumnDefinitions="75,*"
RowDefinitions="3*,2*"
ColumnSpacing="8">
<!-- Placeholder for imagery -->
<Image BackgroundColor="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}"
Grid.RowSpan="2" />
<Grid
RowDefinitions="60,*">

<Label Text="{Binding Title}"
FontSize="32"
FontAttributes="Bold"
Grid.Column="1" />
<Button
Text="Create Recording"
HorizontalOptions="End"
Margin="10"
Command="{Binding AddRecordingCommand}" />

<Label Text="{Binding Artist}"
FontSize="20"
Grid.Column="1"
Grid.Row="1" />
</Grid>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CollectionView ItemsSource="{Binding Music}"
Grid.Row="1"
SelectionMode="Single"
SelectedItem="{Binding SelectedMusicItem}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewmodels:MusicItemViewModel">
<Border Style="{StaticResource border_gallery_card}">
<Grid ColumnDefinitions="75,*"
RowDefinitions="3*,2*"
ColumnSpacing="8">
<!-- Placeholder for imagery -->
<Image BackgroundColor="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}"
Grid.RowSpan="2" />

<Label Text="{Binding Title}"
FontSize="32"
FontAttributes="Bold"
Grid.Column="1" />

<Label Text="{Binding Artist}"
FontSize="20"
Grid.Column="1"
Grid.Row="1" />
</Grid>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>
2 changes: 1 addition & 1 deletion samples/AudioPlayerSample/Pages/MyLibraryPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ public MyLibraryPage(MyLibraryPageViewModel myLibraryPageViewModel)

BindingContext = myLibraryPageViewModel;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
2 changes: 2 additions & 0 deletions samples/AudioPlayerSample/Platforms/MacCatalyst/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
<key>NSMicrophoneUsageDescription</key>
<string>The [app name] wants to use your microphone to record audio.</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
Expand Down Expand Up @@ -38,6 +38,7 @@

<Capabilities>
<rescap:Capability Name="runFullTrust" />
<DeviceCapability Name="microphone"/>
</Capabilities>

</Package>
Expand Down
2 changes: 2 additions & 0 deletions samples/AudioPlayerSample/Platforms/iOS/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
<key>NSMicrophoneUsageDescription</key>
<string>The [app name] wants to use your microphone to record audio.</string>
</dict>
</plist>
7 changes: 6 additions & 1 deletion samples/AudioPlayerSample/Routes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

public static class Routes
{
public static class AudioRecorder
{
public const string RouteName = "audio-recorder";
}

public static class MusicPlayer
{
public const string RouteName = "music-player";
Expand All @@ -11,4 +16,4 @@ public static class Arguments
public const string Music = "music";
}
}
}
}
Loading

0 comments on commit 56346a1

Please sign in to comment.