Prevent ExoPlayer skipping beginning audio.
This commit is contained in:
parent
c0c2f7b592
commit
4322b36518
|
@ -75,6 +75,7 @@ public class AudioPlayer implements MethodCallHandler, Player.EventListener, Aud
|
|||
private IcyInfo icyInfo;
|
||||
private IcyHeaders icyHeaders;
|
||||
private int errorCount;
|
||||
private AudioAttributes pendingAudioAttributes;
|
||||
|
||||
private SimpleExoPlayer player;
|
||||
private Integer audioSessionId;
|
||||
|
@ -211,6 +212,10 @@ public class AudioPlayer implements MethodCallHandler, Player.EventListener, Aud
|
|||
response.put("duration", getDuration() == C.TIME_UNSET ? null : (1000 * getDuration()));
|
||||
prepareResult.success(response);
|
||||
prepareResult = null;
|
||||
if (pendingAudioAttributes != null) {
|
||||
player.setAudioAttributes(pendingAudioAttributes);
|
||||
pendingAudioAttributes = null;
|
||||
}
|
||||
} else {
|
||||
transition(ProcessingState.ready);
|
||||
}
|
||||
|
@ -500,7 +505,8 @@ public class AudioPlayer implements MethodCallHandler, Player.EventListener, Aud
|
|||
|
||||
private void load(final MediaSource mediaSource, final long initialPosition, final Integer initialIndex, final Result result) {
|
||||
this.initialPos = initialPosition;
|
||||
this.initialIndex = currentIndex = initialIndex;
|
||||
this.initialIndex = initialIndex;
|
||||
currentIndex = initialIndex != null ? initialIndex : 0;
|
||||
switch (processingState) {
|
||||
case none:
|
||||
break;
|
||||
|
@ -535,7 +541,14 @@ public class AudioPlayer implements MethodCallHandler, Player.EventListener, Aud
|
|||
builder.setFlags(flags);
|
||||
builder.setUsage(usage);
|
||||
//builder.setAllowedCapturePolicy((Integer)json.get("allowedCapturePolicy"));
|
||||
player.setAudioAttributes(builder.build());
|
||||
AudioAttributes audioAttributes = builder.build();
|
||||
if (processingState == ProcessingState.loading) {
|
||||
// audio attributes should be set either before or after loading to
|
||||
// avoid an ExoPlayer glitch.
|
||||
pendingAudioAttributes = audioAttributes;
|
||||
} else {
|
||||
player.setAudioAttributes(audioAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcastPlaybackEvent() {
|
||||
|
@ -652,6 +665,7 @@ public class AudioPlayer implements MethodCallHandler, Player.EventListener, Aud
|
|||
}
|
||||
|
||||
public void setSpeed(final float speed) {
|
||||
if (player.getPlaybackParameters().speed != speed)
|
||||
player.setPlaybackParameters(new PlaybackParameters(speed));
|
||||
broadcastPlaybackEvent();
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ class AudioPlayer {
|
|||
AudioSource _audioSource;
|
||||
Map<String, AudioSource> _audioSources = {};
|
||||
bool _disposed = false;
|
||||
_InitialSeekValues _initialSeekValues;
|
||||
|
||||
PlaybackEvent _playbackEvent;
|
||||
final _playbackEventSubject = BehaviorSubject<PlaybackEvent>(sync: true);
|
||||
|
@ -84,6 +85,7 @@ class AudioPlayer {
|
|||
BehaviorSubject<Duration> _positionSubject;
|
||||
bool _automaticallyWaitsToMinimizeStalling = true;
|
||||
bool _playInterrupted = false;
|
||||
AndroidAudioAttributes _androidAudioAttributes;
|
||||
|
||||
/// Creates an [AudioPlayer]. The player will automatically pause/duck and
|
||||
/// resume/unduck when audio interruptions occur (e.g. a phone call) or when
|
||||
|
@ -466,7 +468,7 @@ class AudioPlayer {
|
|||
Future<Duration> setUrl(
|
||||
String url, {
|
||||
Map headers,
|
||||
Duration initialPosition = Duration.zero,
|
||||
Duration initialPosition,
|
||||
bool preload = true,
|
||||
}) =>
|
||||
setAudioSource(AudioSource.uri(Uri.parse(url), headers: headers),
|
||||
|
@ -483,7 +485,7 @@ class AudioPlayer {
|
|||
/// See [setAudioSource] for a detailed explanation of the options.
|
||||
Future<Duration> setFilePath(
|
||||
String filePath, {
|
||||
Duration initialPosition = Duration.zero,
|
||||
Duration initialPosition,
|
||||
bool preload = true,
|
||||
}) =>
|
||||
setAudioSource(AudioSource.uri(Uri.file(filePath)),
|
||||
|
@ -530,14 +532,16 @@ class AudioPlayer {
|
|||
Future<Duration> setAudioSource(
|
||||
AudioSource source, {
|
||||
bool preload = true,
|
||||
int initialIndex = 0,
|
||||
Duration initialPosition = Duration.zero,
|
||||
int initialIndex,
|
||||
Duration initialPosition,
|
||||
}) async {
|
||||
if (_disposed) return null;
|
||||
// Idea: always keep the idle player around and make it possible
|
||||
// to switch between idle and active players without disposing either
|
||||
// one.
|
||||
_audioSource = null;
|
||||
_initialSeekValues =
|
||||
_InitialSeekValues(position: initialPosition, index: initialIndex);
|
||||
_playbackEventSubject.add(_playbackEvent = PlaybackEvent(
|
||||
currentIndex: initialIndex, updatePosition: initialPosition));
|
||||
_broadcastSequence();
|
||||
|
@ -596,8 +600,6 @@ class AudioPlayer {
|
|||
|
||||
Future<Duration> _load(AudioPlayerPlatform platform, AudioSource source,
|
||||
{Duration initialPosition, int initialIndex}) async {
|
||||
initialIndex ??= 0;
|
||||
initialPosition ??= Duration.zero;
|
||||
try {
|
||||
if (!kIsWeb && source._requiresHeaders) {
|
||||
if (_proxy == null) {
|
||||
|
@ -790,6 +792,7 @@ class AudioPlayer {
|
|||
/// an audio source has been loaded.
|
||||
Future<void> seek(final Duration position, {int index}) async {
|
||||
if (_disposed) return;
|
||||
_initialSeekValues = null;
|
||||
switch (processingState) {
|
||||
case ProcessingState.loading:
|
||||
return;
|
||||
|
@ -824,8 +827,14 @@ class AudioPlayer {
|
|||
AndroidAudioAttributes audioAttributes) async {
|
||||
if (_disposed) return;
|
||||
if (audioAttributes == null) return;
|
||||
await (await _platform).setAndroidAudioAttributes(
|
||||
SetAndroidAudioAttributesRequest(
|
||||
if (audioAttributes == _androidAudioAttributes) return;
|
||||
_androidAudioAttributes = audioAttributes;
|
||||
await _internalSetAndroidAudioAttributes(await _platform, audioAttributes);
|
||||
}
|
||||
|
||||
Future<void> _internalSetAndroidAudioAttributes(AudioPlayerPlatform platform,
|
||||
AndroidAudioAttributes audioAttributes) async {
|
||||
await platform.setAndroidAudioAttributes(SetAndroidAudioAttributesRequest(
|
||||
contentType: audioAttributes.contentType.index,
|
||||
flags: audioAttributes.flags.value,
|
||||
usage: audioAttributes.usage.value));
|
||||
|
@ -922,13 +931,16 @@ class AudioPlayer {
|
|||
if (active) {
|
||||
final automaticallyWaitsToMinimizeStalling =
|
||||
this.automaticallyWaitsToMinimizeStalling;
|
||||
final setAndroidAudioAttributesRequest =
|
||||
_idlePlatform.setAndroidAudioAttributesRequest;
|
||||
if (setAndroidAudioAttributesRequest != null) {
|
||||
// Only set if there was an unfulfilled pending request.
|
||||
await platform
|
||||
.setAndroidAudioAttributes(setAndroidAudioAttributesRequest);
|
||||
_idlePlatform.setAndroidAudioAttributesRequest = null;
|
||||
// To avoid a glitch in ExoPlayer, ensure that any requested audio
|
||||
// attributes are set before loading the audio source.
|
||||
final audioSession = await AudioSession.instance;
|
||||
if (_androidAudioAttributes == null) {
|
||||
_androidAudioAttributes =
|
||||
audioSession.configuration?.androidAudioAttributes;
|
||||
}
|
||||
if (_androidAudioAttributes != null) {
|
||||
await _internalSetAndroidAudioAttributes(
|
||||
platform, _androidAudioAttributes);
|
||||
}
|
||||
if (!automaticallyWaitsToMinimizeStalling) {
|
||||
// Only set if different from default.
|
||||
|
@ -947,8 +959,17 @@ class AudioPlayer {
|
|||
}
|
||||
if (audioSource != null) {
|
||||
try {
|
||||
Duration initialPosition;
|
||||
int initialIndex;
|
||||
if (_initialSeekValues != null) {
|
||||
initialPosition = _initialSeekValues.position;
|
||||
initialIndex = _initialSeekValues.index;
|
||||
} else {
|
||||
initialPosition = position;
|
||||
initialIndex = currentIndex;
|
||||
}
|
||||
final duration = await _load(platform, _audioSource,
|
||||
initialPosition: position, initialIndex: currentIndex);
|
||||
initialPosition: initialPosition, initialIndex: initialIndex);
|
||||
// Wait for loading state to pass.
|
||||
await processingStateStream
|
||||
.firstWhere((state) => state != ProcessingState.loading);
|
||||
|
@ -2054,3 +2075,12 @@ class _IdleAudioPlayer extends AudioPlayerPlatform {
|
|||
return ConcatenatingMoveResponse();
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds the initial requested position and index for a newly loaded audio
|
||||
/// source.
|
||||
class _InitialSeekValues {
|
||||
final Duration position;
|
||||
final int index;
|
||||
|
||||
_InitialSeekValues({@required this.position, @required this.index});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue