Skip to content

Commit 1cfdf4c

Browse files
borrmannjfversluisbijington
authored
fixes issues with seek and speed (#109)
* 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]>
1 parent d88f00d commit 1cfdf4c

File tree

10 files changed

+353
-184
lines changed

10 files changed

+353
-184
lines changed

samples/Plugin.Maui.Audio.Sample.sln

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ MinimumVisualStudioVersion = 10.0.40219.1
55
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugin.Maui.Audio.Sample", "Plugin.Maui.Audio.Sample\Plugin.Maui.Audio.Sample.csproj", "{490BB138-9606-4FFF-8AAD-841C5B1ED059}"
66
EndProject
77
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugin.Maui.Audio", "..\src\Plugin.Maui.Audio\Plugin.Maui.Audio.csproj", "{B60F3174-E978-4F2B-B117-F6F0327594C8}"
8-
98
EndProject
109
Global
1110
GlobalSection(SolutionConfigurationPlatforms) = preSolution

samples/Plugin.Maui.Audio.Sample/Pages/MusicPlayerPage.xaml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040

4141
<Slider
4242
Value="{Binding CurrentPosition}"
43+
DragStartedCommand="{Binding SeekStartedCommand}"
44+
DragCompletedCommand="{Binding SeekCommand}"
4345
Maximum="{Binding Duration}" />
4446

4547
<HorizontalStackLayout Spacing="5" HorizontalOptions="Center">
@@ -82,20 +84,30 @@
8284
Maximum="1"
8385
Value="{Binding Balance}" />
8486

87+
<Label IsVisible="{Binding CanSetSpeed}">
88+
<Label.FormattedText>
89+
<FormattedString>
90+
<Span Text="Audio Player Speed" />
91+
<Span Text="{Binding AudioSpeed, StringFormat=' ({0:F1}):'}" />
92+
</FormattedString>
93+
</Label.FormattedText>
94+
</Label>
8595

8696
<Label IsVisible="{Binding CanSetSpeed}">
8797
<Label.FormattedText>
8898
<FormattedString>
89-
<Span Text="Speed" />
90-
<Span Text="{Binding Speed, StringFormat=' ({0:F1}):'}"/>
99+
<Span Text="Speed setting" />
100+
<Span Text="{Binding UserSpeed, StringFormat=' ({0:F1}):'}" />
91101
</FormattedString>
92102
</Label.FormattedText>
93103
</Label>
104+
94105
<Slider
95106
IsVisible="{Binding CanSetSpeed}"
96107
Minimum="{Binding MinimumSpeed}"
97108
Maximum="{Binding MaximumSpeed}"
98-
Value="{Binding Speed}" />
109+
Value="{Binding UserSpeed}"
110+
DragCompletedCommand="{Binding UpdateSpeedCommand}"/>
99111
</VerticalStackLayout>
100112
</ScrollView>
101113

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

Lines changed: 92 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ public class MusicPlayerPageViewModel : BaseViewModel, IQueryAttributable, IDisp
77
IAudioPlayer audioPlayer;
88
TimeSpan animationProgress;
99
MusicItemViewModel musicItemViewModel;
10-
bool isPositionChangeSystemDriven;
1110
bool isDisposed;
1211

1312
public MusicPlayerPageViewModel(
@@ -20,6 +19,16 @@ public MusicPlayerPageViewModel(
2019
PlayCommand = new Command(Play);
2120
PauseCommand = new Command(Pause);
2221
StopCommand = new Command(Stop);
22+
UpdateSpeedCommand = new Command(UpdateSpeed);
23+
SeekStartedCommand = new Command(SeekStarted);
24+
SeekCommand = new Command(Seek);
25+
}
26+
27+
void AudioPlayer_PlaybackEnded(object sender, EventArgs e)
28+
{
29+
NotifyPropertyChanged(nameof(IsPlaying));
30+
NotifyPropertyChanged(nameof(AnimationProgress));
31+
CurrentPosition = audioPlayer.CurrentPosition;
2332
}
2433

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

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

44+
#if WINDOWS
45+
// On windows, without this delay, the states are not updated in time
46+
// 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
47+
await Task.Delay(50);
48+
#endif
3449
NotifyPropertyChanged(nameof(HasAudioSource));
3550
NotifyPropertyChanged(nameof(Duration));
3651
NotifyPropertyChanged(nameof(CanSetSpeed));
@@ -39,16 +54,39 @@ public async void ApplyQueryAttributes(IDictionary<string, object> query)
3954
}
4055
}
4156

57+
double currentPosition = 0;
4258
public double CurrentPosition
4359
{
44-
get => audioPlayer?.CurrentPosition ?? 0;
60+
get => currentPosition;
4561
set
4662
{
47-
if (audioPlayer is not null &&
48-
audioPlayer.CanSeek &&
49-
isPositionChangeSystemDriven is false)
63+
currentPosition = value;
64+
NotifyPropertyChanged();
65+
}
66+
}
67+
68+
bool wasPlayingBeforeSeek = false;
69+
void SeekStarted()
70+
{
71+
if (audioPlayer is not null &&
72+
audioPlayer.CanSeek)
73+
{
74+
wasPlayingBeforeSeek = audioPlayer.IsPlaying;
75+
audioPlayer.Pause();
76+
}
77+
}
78+
79+
void Seek()
80+
{
81+
if (audioPlayer is not null &&
82+
audioPlayer.CanSeek)
83+
{
84+
audioPlayer.Seek(CurrentPosition);
85+
86+
if (wasPlayingBeforeSeek)
5087
{
51-
audioPlayer.Seek(value);
88+
Play();
89+
wasPlayingBeforeSeek = false;
5290
}
5391
}
5492
}
@@ -82,6 +120,10 @@ public TimeSpan AnimationProgress
82120
public Command PlayCommand { get; }
83121
public Command PauseCommand { get; }
84122
public Command StopCommand { get; }
123+
public Command UpdateSpeedCommand { get; }
124+
public Command SeekStartedCommand { get; }
125+
public Command SeekCommand { get; }
126+
85127

86128
public double Volume
87129
{
@@ -109,25 +151,39 @@ public double Balance
109151

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

112-
public double Speed
154+
155+
double userSpeed = 1.0;
156+
public double UserSpeed
113157
{
114-
get => audioPlayer?.Speed ?? 1;
158+
get => userSpeed;
115159
set
116160
{
117-
try
118-
{
119-
if (audioPlayer?.CanSetSpeed ?? false)
120-
{
121-
audioPlayer.Speed = Math.Round(value, 1, MidpointRounding.AwayFromZero);
122-
NotifyPropertyChanged();
123-
}
124-
}
125-
catch (Exception ex)
161+
userSpeed = value;
162+
NotifyPropertyChanged();
163+
}
164+
}
165+
166+
public void UpdateSpeed()
167+
{
168+
try
169+
{
170+
if ((audioPlayer?.CanSetSpeed ?? false) && UserSpeed >= MinimumSpeed && UserSpeed <= MaximumSpeed)
126171
{
127-
App.Current.MainPage.DisplayAlert("Speed", ex.Message, "OK");
172+
audioPlayer.SetSpeed(UserSpeed);
173+
NotifyPropertyChanged(nameof(AudioSpeed));
128174
}
129175
}
176+
catch (Exception ex)
177+
{
178+
Console.WriteLine(ex.Message);
179+
}
180+
finally
181+
{
182+
UserSpeed = AudioSpeed;
183+
NotifyPropertyChanged(nameof(UserSpeed));
184+
}
130185
}
186+
public double AudioSpeed => audioPlayer?.Speed ?? 1.0;
131187

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

144200
void Play()
145201
{
202+
UpdateSpeed();
146203
audioPlayer.Play();
147204

148205
UpdatePlaybackPosition();
@@ -151,59 +208,51 @@ void Play()
151208

152209
void Pause()
153210
{
154-
if (audioPlayer.IsPlaying)
155-
{
156-
audioPlayer.Pause();
157-
}
158-
else
159-
{
160-
audioPlayer.Play();
161-
}
162-
211+
audioPlayer.Pause();
163212
UpdatePlaybackPosition();
164213
NotifyPropertyChanged(nameof(IsPlaying));
165214
}
166215

167216
void Stop()
168217
{
169-
bool wasPlaying = audioPlayer.IsPlaying;
170218
audioPlayer.Stop();
171219
AnimationProgress = TimeSpan.Zero;
172-
CurrentPosition = 0;
173-
220+
NotifyPropertyChanged(nameof(IsPlaying));
174221
NotifyPropertyChanged(nameof(CurrentPosition));
175-
176-
if (wasPlaying)
177-
{
178-
NotifyPropertyChanged(nameof(IsPlaying));
179-
}
180222
}
181223

182224
void UpdatePlaybackPosition()
183225
{
184226
if (audioPlayer?.IsPlaying is false)
185227
{
186-
return;
228+
#if WINDOWS
229+
// On windows, without this delay, the playback state is not updated in time
230+
// 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
231+
Thread.Sleep(50);
232+
#endif
233+
234+
if (audioPlayer?.IsPlaying is false)
235+
{
236+
NotifyPropertyChanged(nameof(IsPlaying));
237+
NotifyPropertyChanged(nameof(AnimationProgress));
238+
CurrentPosition = audioPlayer.CurrentPosition;
239+
return;
240+
}
187241
}
188242

189243
dispatcher.DispatchDelayed(
190244
TimeSpan.FromMilliseconds(16),
191245
() =>
192246
{
193247
Console.WriteLine($"{CurrentPosition} with duration of {Duration}");
194-
195-
isPositionChangeSystemDriven = true;
196-
197-
NotifyPropertyChanged(nameof(CurrentPosition));
198-
199-
isPositionChangeSystemDriven = false;
200-
248+
CurrentPosition = audioPlayer?.CurrentPosition ?? 0;
201249
UpdatePlaybackPosition();
202250
});
203251
}
204252

205253
public void TidyUp()
206254
{
255+
audioPlayer.PlaybackEnded -= AudioPlayer_PlaybackEnded;
207256
audioPlayer?.Dispose();
208257
audioPlayer = null;
209258
}

src/Plugin.Maui.Audio/AudioPlayer/AsyncAudioPlayer.shared.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,10 @@ public double Balance
4343
public double Speed
4444
{
4545
get => audioPlayer.Speed;
46-
set => audioPlayer.Speed = value;
4746
}
4847

48+
public void SetSpeed(double speed) => audioPlayer.SetSpeed(speed);
49+
4950
/// <inheritdoc cref="IAudio.MinimumSpeed" />
5051
public double MinimumSpeed => audioPlayer.MinimumSpeed;
5152

0 commit comments

Comments
 (0)