Skip to content

Commit

Permalink
fixes issues with seek and speed (#109)
Browse files Browse the repository at this point in the history
* Add support for AudioRecording Options

* delete raw file on android after recording stopped and throw exception on ios

* ensure recordings and other audio can be played on iOS after a recording session.

EnableRate on iOS to ensure speed value can be changed.

* fixes #32 : load audio from files on android

* fix navigation issue in setter

* fixes issues with seek and speed

* stream support for android

* Try fix CI

* Revert "Try fix CI"

This reverts commit 10cda9b.

* Update Plugin.Maui.Audio.Sample.csproj

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

* Update AudioRecorderPageViewModel.cs

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

* Update AudioPlayer.macios.cs

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

* Update AudioPlayer.macios.cs

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

* Update AudioRecordingOptions.cs

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

* Update AudioRecordingOptions.cs

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

* Update AudioRecordingOptions.cs

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

* Update AudioRecordingOptions.cs

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

* Update AudioRecordingOptions.cs

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

* support for windows recording options

* trace error message

* bug fixes on windows & support of Alac & Flac

* reset csproj

* replace observable collections with lists

* fix error on ios and final merges

* remove redundant code

* merging

* fix navigation while playing

* delay only on windows

* workaround for state machine issues on windows

* merge

* restore some lost changes

* Update Plugin.Maui.Audio.Sample.csproj

* Update samples/Plugin.Maui.Audio.Sample/ViewModels/MusicPlayerPageViewModel.cs

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

* resolve @bijington's comments

---------

Co-authored-by: Gerald Versluis <[email protected]>
Co-authored-by: Gerald Versluis <[email protected]>
Co-authored-by: Shaun Lawrence <[email protected]>
  • Loading branch information
4 people authored May 3, 2024
1 parent d88f00d commit 1cfdf4c
Show file tree
Hide file tree
Showing 10 changed files with 353 additions and 184 deletions.
1 change: 0 additions & 1 deletion samples/Plugin.Maui.Audio.Sample.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugin.Maui.Audio.Sample", "Plugin.Maui.Audio.Sample\Plugin.Maui.Audio.Sample.csproj", "{490BB138-9606-4FFF-8AAD-841C5B1ED059}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugin.Maui.Audio", "..\src\Plugin.Maui.Audio\Plugin.Maui.Audio.csproj", "{B60F3174-E978-4F2B-B117-F6F0327594C8}"

EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
18 changes: 15 additions & 3 deletions samples/Plugin.Maui.Audio.Sample/Pages/MusicPlayerPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@

<Slider
Value="{Binding CurrentPosition}"
DragStartedCommand="{Binding SeekStartedCommand}"
DragCompletedCommand="{Binding SeekCommand}"
Maximum="{Binding Duration}" />

<HorizontalStackLayout Spacing="5" HorizontalOptions="Center">
Expand Down Expand Up @@ -82,20 +84,30 @@
Maximum="1"
Value="{Binding Balance}" />

<Label IsVisible="{Binding CanSetSpeed}">
<Label.FormattedText>
<FormattedString>
<Span Text="Audio Player Speed" />
<Span Text="{Binding AudioSpeed, StringFormat=' ({0:F1}):'}" />
</FormattedString>
</Label.FormattedText>
</Label>

<Label IsVisible="{Binding CanSetSpeed}">
<Label.FormattedText>
<FormattedString>
<Span Text="Speed" />
<Span Text="{Binding Speed, StringFormat=' ({0:F1}):'}"/>
<Span Text="Speed setting" />
<Span Text="{Binding UserSpeed, StringFormat=' ({0:F1}):'}" />
</FormattedString>
</Label.FormattedText>
</Label>

<Slider
IsVisible="{Binding CanSetSpeed}"
Minimum="{Binding MinimumSpeed}"
Maximum="{Binding MaximumSpeed}"
Value="{Binding Speed}" />
Value="{Binding UserSpeed}"
DragCompletedCommand="{Binding UpdateSpeedCommand}"/>
</VerticalStackLayout>
</ScrollView>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ public class MusicPlayerPageViewModel : BaseViewModel, IQueryAttributable, IDisp
IAudioPlayer audioPlayer;
TimeSpan animationProgress;
MusicItemViewModel musicItemViewModel;
bool isPositionChangeSystemDriven;
bool isDisposed;

public MusicPlayerPageViewModel(
Expand All @@ -20,6 +19,16 @@ public MusicPlayerPageViewModel(
PlayCommand = new Command(Play);
PauseCommand = new Command(Pause);
StopCommand = new Command(Stop);
UpdateSpeedCommand = new Command(UpdateSpeed);
SeekStartedCommand = new Command(SeekStarted);
SeekCommand = new Command(Seek);
}

void AudioPlayer_PlaybackEnded(object sender, EventArgs e)
{
NotifyPropertyChanged(nameof(IsPlaying));
NotifyPropertyChanged(nameof(AnimationProgress));
CurrentPosition = audioPlayer.CurrentPosition;
}

public async void ApplyQueryAttributes(IDictionary<string, object> query)
Expand All @@ -30,7 +39,13 @@ public async void ApplyQueryAttributes(IDictionary<string, object> query)
MusicItemViewModel = musicItem;

audioPlayer = audioManager.CreatePlayer(await FileSystem.OpenAppPackageFileAsync(musicItem.Filename));
audioPlayer.PlaybackEnded += AudioPlayer_PlaybackEnded;

#if WINDOWS
// On windows, without this delay, the states are not updated in time
// instead of this hack, we should update the windows state machine to be more reactive, or use an event based approach to update the UI
await Task.Delay(50);
#endif
NotifyPropertyChanged(nameof(HasAudioSource));
NotifyPropertyChanged(nameof(Duration));
NotifyPropertyChanged(nameof(CanSetSpeed));
Expand All @@ -39,16 +54,39 @@ public async void ApplyQueryAttributes(IDictionary<string, object> query)
}
}

double currentPosition = 0;
public double CurrentPosition
{
get => audioPlayer?.CurrentPosition ?? 0;
get => currentPosition;
set
{
if (audioPlayer is not null &&
audioPlayer.CanSeek &&
isPositionChangeSystemDriven is false)
currentPosition = value;
NotifyPropertyChanged();
}
}

bool wasPlayingBeforeSeek = false;
void SeekStarted()
{
if (audioPlayer is not null &&
audioPlayer.CanSeek)
{
wasPlayingBeforeSeek = audioPlayer.IsPlaying;
audioPlayer.Pause();
}
}

void Seek()
{
if (audioPlayer is not null &&
audioPlayer.CanSeek)
{
audioPlayer.Seek(CurrentPosition);

if (wasPlayingBeforeSeek)
{
audioPlayer.Seek(value);
Play();
wasPlayingBeforeSeek = false;
}
}
}
Expand Down Expand Up @@ -82,6 +120,10 @@ public TimeSpan AnimationProgress
public Command PlayCommand { get; }
public Command PauseCommand { get; }
public Command StopCommand { get; }
public Command UpdateSpeedCommand { get; }
public Command SeekStartedCommand { get; }
public Command SeekCommand { get; }


public double Volume
{
Expand Down Expand Up @@ -109,25 +151,39 @@ public double Balance

public bool CanSetSpeed => audioPlayer?.CanSetSpeed ?? false;

public double Speed

double userSpeed = 1.0;
public double UserSpeed
{
get => audioPlayer?.Speed ?? 1;
get => userSpeed;
set
{
try
{
if (audioPlayer?.CanSetSpeed ?? false)
{
audioPlayer.Speed = Math.Round(value, 1, MidpointRounding.AwayFromZero);
NotifyPropertyChanged();
}
}
catch (Exception ex)
userSpeed = value;
NotifyPropertyChanged();
}
}

public void UpdateSpeed()
{
try
{
if ((audioPlayer?.CanSetSpeed ?? false) && UserSpeed >= MinimumSpeed && UserSpeed <= MaximumSpeed)
{
App.Current.MainPage.DisplayAlert("Speed", ex.Message, "OK");
audioPlayer.SetSpeed(UserSpeed);
NotifyPropertyChanged(nameof(AudioSpeed));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
UserSpeed = AudioSpeed;
NotifyPropertyChanged(nameof(UserSpeed));
}
}
public double AudioSpeed => audioPlayer?.Speed ?? 1.0;

public double MinimumSpeed => audioPlayer?.MinimumSpeed ?? 1;
public double MaximumSpeed => audioPlayer?.MaximumSpeed ?? 1;
Expand All @@ -143,6 +199,7 @@ public bool Loop

void Play()
{
UpdateSpeed();
audioPlayer.Play();

UpdatePlaybackPosition();
Expand All @@ -151,59 +208,51 @@ void Play()

void Pause()
{
if (audioPlayer.IsPlaying)
{
audioPlayer.Pause();
}
else
{
audioPlayer.Play();
}

audioPlayer.Pause();
UpdatePlaybackPosition();
NotifyPropertyChanged(nameof(IsPlaying));
}

void Stop()
{
bool wasPlaying = audioPlayer.IsPlaying;
audioPlayer.Stop();
AnimationProgress = TimeSpan.Zero;
CurrentPosition = 0;

NotifyPropertyChanged(nameof(IsPlaying));
NotifyPropertyChanged(nameof(CurrentPosition));

if (wasPlaying)
{
NotifyPropertyChanged(nameof(IsPlaying));
}
}

void UpdatePlaybackPosition()
{
if (audioPlayer?.IsPlaying is false)
{
return;
#if WINDOWS
// On windows, without this delay, the playback state is not updated in time
// instead of this hack, we should update the windows state machine to be more reactive, or use an event based approach to update the UI
Thread.Sleep(50);
#endif

if (audioPlayer?.IsPlaying is false)
{
NotifyPropertyChanged(nameof(IsPlaying));
NotifyPropertyChanged(nameof(AnimationProgress));
CurrentPosition = audioPlayer.CurrentPosition;
return;
}
}

dispatcher.DispatchDelayed(
TimeSpan.FromMilliseconds(16),
() =>
{
Console.WriteLine($"{CurrentPosition} with duration of {Duration}");
isPositionChangeSystemDriven = true;
NotifyPropertyChanged(nameof(CurrentPosition));
isPositionChangeSystemDriven = false;
CurrentPosition = audioPlayer?.CurrentPosition ?? 0;
UpdatePlaybackPosition();
});
}

public void TidyUp()
{
audioPlayer.PlaybackEnded -= AudioPlayer_PlaybackEnded;
audioPlayer?.Dispose();
audioPlayer = null;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Plugin.Maui.Audio/AudioPlayer/AsyncAudioPlayer.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ public double Balance
public double Speed
{
get => audioPlayer.Speed;
set => audioPlayer.Speed = value;
}

public void SetSpeed(double speed) => audioPlayer.SetSpeed(speed);

/// <inheritdoc cref="IAudio.MinimumSpeed" />
public double MinimumSpeed => audioPlayer.MinimumSpeed;

Expand Down
Loading

0 comments on commit 1cfdf4c

Please sign in to comment.