Skip to content

Commit 446c868

Browse files
committed
Merge branch 'fix/event_order' into minor
2 parents fbd38bf + f310717 commit 446c868

File tree

4 files changed

+78
-63
lines changed

4 files changed

+78
-63
lines changed

just_audio/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.10.2
2+
3+
* Fix playing/playbackEvent emission order.
4+
* Fix rxdart errors on lower bound rxdart 0.26.0.
5+
* Fix MissingPluginException in dispose on iOS.
6+
17
## 0.10.1
28

39
* Fix unhandled PlayerInterruptedException.

just_audio/example/lib/main.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ class ControlButtons extends StatelessWidget {
185185
}
186186
},
187187
),
188+
IconButton(
189+
icon: const Icon(Icons.stop),
190+
iconSize: 64.0,
191+
onPressed: player.stop,
192+
),
188193
// Opens speed slider dialog
189194
StreamBuilder<double>(
190195
stream: player.speedStream,

just_audio/lib/just_audio.dart

Lines changed: 66 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ JustAudioPlatform get _pluginPlatform {
5757
/// player, including any temporary files created to cache assets.
5858
class AudioPlayer {
5959
static String _generateId() => _uuid.v4();
60+
final _lock = Lock();
6061

6162
/// The user agent to set on all HTTP requests.
6263
final String? _userAgent;
@@ -279,7 +280,7 @@ class AudioPlayer {
279280
.pairwise()
280281
.listen((rec) {
281282
if (_seeking) return;
282-
final [(prevEvent, prevSource), (currEvent, currSource)] = rec;
283+
final [(prevEvent, prevSource), (currEvent, currSource)] = rec.toList();
283284
if (prevSource == null || currSource == null) return;
284285
if (currSource._id != prevSource._id) {
285286
// If we've changed item without seeking, it must be an autoAdvance.
@@ -447,7 +448,7 @@ class AudioPlayer {
447448
AudioSource? get audioSource => _playlist.children.firstOrNull;
448449

449450
/// The latest [PlaybackEvent].
450-
PlaybackEvent get playbackEvent => _playbackEventSubject.value;
451+
PlaybackEvent get playbackEvent => _playbackEventSubject.nvalue!;
451452

452453
/// A stream of [PlaybackEvent]s.
453454
Stream<PlaybackEvent> get playbackEventStream => _playbackEventSubject.stream;
@@ -520,14 +521,14 @@ class AudioPlayer {
520521
Stream<PlayerState> get playerStateStream => _playerStateSubject.stream;
521522

522523
/// The current sequence of indexed audio sources.
523-
List<IndexedAudioSource> get sequence => _sequenceSubject.value;
524+
List<IndexedAudioSource> get sequence => _sequenceSubject.nvalue!;
524525

525526
/// A stream broadcasting the current sequence of indexed audio sources.
526527
Stream<List<IndexedAudioSource>> get sequenceStream =>
527528
_sequenceSubject.stream;
528529

529530
/// The current shuffled sequence of indexed audio sources.
530-
List<int> get shuffleIndices => _shuffleIndicesSubject.value;
531+
List<int> get shuffleIndices => _shuffleIndicesSubject.nvalue!;
531532

532533
/// A stream broadcasting the current shuffled sequence of indexed audio
533534
/// sources.
@@ -541,7 +542,7 @@ class AudioPlayer {
541542
Stream<int?> get currentIndexStream => _currentIndexSubject.stream;
542543

543544
/// The current [SequenceState].
544-
SequenceState get sequenceState => _sequenceStateSubject.value;
545+
SequenceState get sequenceState => _sequenceStateSubject.nvalue!;
545546

546547
/// A stream broadcasting the current [SequenceState].
547548
Stream<SequenceState> get sequenceStateStream => _sequenceStateSubject.stream;
@@ -1068,11 +1069,11 @@ class AudioPlayer {
10681069
// Broadcast to clients immediately, but revert to false if we fail to
10691070
// activate the audio session. This allows setAudioSource to be aware of a
10701071
// prior play request.
1072+
_playingSubject.add(true);
10711073
_playbackEventSubject.add(playbackEvent.copyWith(
10721074
updatePosition: position,
10731075
updateTime: DateTime.now(),
10741076
));
1075-
_playingSubject.add(true);
10761077
final playCompleter = Completer<dynamic>();
10771078
final audioSession = await AudioSession.instance;
10781079
if (!_handleAudioSessionActivation || await audioSession.setActive(true)) {
@@ -1108,11 +1109,11 @@ class AudioPlayer {
11081109
if (!playing) return;
11091110
_playInterrupted = false;
11101111
// Update local state immediately so that queries aren't surprised.
1112+
_playingSubject.add(false);
11111113
_playbackEventSubject.add(playbackEvent.copyWith(
11121114
updatePosition: position,
11131115
updateTime: DateTime.now(),
11141116
));
1115-
_playingSubject.add(false);
11161117
// TODO: perhaps modify platform side to ensure new state is broadcast
11171118
// before this method returns.
11181119
await (await _platform).pause(PauseRequest());
@@ -1373,61 +1374,64 @@ class AudioPlayer {
13731374

13741375
/// Releases all resources associated with this player. You must invoke this
13751376
/// after you are done with the player.
1376-
Future<void> dispose() async {
1377-
if (_disposed) return;
1378-
_disposed = true;
1379-
if (_nativePlatform != null) {
1380-
await _disposePlatform(await _nativePlatform!);
1381-
_nativePlatform = null;
1382-
}
1383-
if (_idlePlatform != null) {
1384-
await _disposePlatform(_idlePlatform!);
1385-
_idlePlatform = null;
1386-
}
1387-
_playlist.children.clear();
1388-
for (var s in _audioSources.values) {
1389-
s._dispose();
1390-
}
1391-
_audioSources.clear();
1392-
_proxy.stop();
1393-
await _playerDataSubscription?.cancel();
1394-
await _playbackEventSubscription?.cancel();
1395-
await _androidAudioAttributesSubscription?.cancel();
1396-
await _becomingNoisyEventSubscription?.cancel();
1397-
await _interruptionEventSubscription?.cancel();
1398-
await _positionDiscontinuitySubscription?.cancel();
1399-
await _currentIndexSubscription?.cancel();
1400-
await _errorsSubscription?.cancel();
1401-
await _errorsResetSubscription?.cancel();
1402-
1403-
await _playbackEventSubject.close();
1404-
await _sequenceStateSubject.close();
1405-
await _playingSubject.close();
1406-
await _volumeSubject.close();
1407-
await _speedSubject.close();
1408-
await _pitchSubject.close();
1409-
1410-
await Future<void>.delayed(Duration.zero);
1411-
await _durationSubject.close();
1412-
await _processingStateSubject.close();
1413-
await _bufferedPositionSubject.close();
1414-
await _icyMetadataSubject.close();
1415-
await _androidAudioSessionIdSubject.close();
1416-
await _errorSubject.close();
1417-
await _playerStateSubject.close();
1418-
await _skipSilenceEnabledSubject.close();
1419-
await _positionDiscontinuitySubject.close();
1420-
await _sequenceSubject.close();
1421-
await _shuffleIndicesSubject.close();
1422-
await _currentIndexSubject.close();
1423-
await _loopModeSubject.close();
1424-
await _shuffleModeEnabledSubject.close();
1425-
await _shuffleModeEnabledSubject.close();
1426-
1427-
if (playbackEvent.processingState != ProcessingState.idle) {
1428-
_playbackEventSubject
1429-
.add(playbackEvent.copyWith(processingState: ProcessingState.idle));
1430-
}
1377+
Future<void> dispose() {
1378+
return _lock.synchronized(() async {
1379+
if (_disposed) return;
1380+
await stop();
1381+
_disposed = true;
1382+
if (_nativePlatform != null) {
1383+
await _disposePlatform(await _nativePlatform!);
1384+
_nativePlatform = null;
1385+
}
1386+
if (_idlePlatform != null) {
1387+
await _disposePlatform(_idlePlatform!);
1388+
_idlePlatform = null;
1389+
}
1390+
_playlist.children.clear();
1391+
for (var s in _audioSources.values) {
1392+
s._dispose();
1393+
}
1394+
_audioSources.clear();
1395+
_proxy.stop();
1396+
await _playerDataSubscription?.cancel();
1397+
await _playbackEventSubscription?.cancel();
1398+
await _androidAudioAttributesSubscription?.cancel();
1399+
await _becomingNoisyEventSubscription?.cancel();
1400+
await _interruptionEventSubscription?.cancel();
1401+
await _positionDiscontinuitySubscription?.cancel();
1402+
await _currentIndexSubscription?.cancel();
1403+
await _errorsSubscription?.cancel();
1404+
await _errorsResetSubscription?.cancel();
1405+
1406+
await _playbackEventSubject.close();
1407+
await _sequenceStateSubject.close();
1408+
await _playingSubject.close();
1409+
await _volumeSubject.close();
1410+
await _speedSubject.close();
1411+
await _pitchSubject.close();
1412+
1413+
await Future<void>.delayed(Duration.zero);
1414+
await _durationSubject.close();
1415+
await _processingStateSubject.close();
1416+
await _bufferedPositionSubject.close();
1417+
await _icyMetadataSubject.close();
1418+
await _androidAudioSessionIdSubject.close();
1419+
await _errorSubject.close();
1420+
await _playerStateSubject.close();
1421+
await _skipSilenceEnabledSubject.close();
1422+
await _positionDiscontinuitySubject.close();
1423+
await _sequenceSubject.close();
1424+
await _shuffleIndicesSubject.close();
1425+
await _currentIndexSubject.close();
1426+
await _loopModeSubject.close();
1427+
await _shuffleModeEnabledSubject.close();
1428+
await _shuffleModeEnabledSubject.close();
1429+
1430+
if (playbackEvent.processingState != ProcessingState.idle) {
1431+
_playbackEventSubject
1432+
.add(playbackEvent.copyWith(processingState: ProcessingState.idle));
1433+
}
1434+
});
14311435
}
14321436

14331437
/// Switches to using the native platform when [active] is `true` and using the

just_audio/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: just_audio
22
description: A feature-rich audio player for Flutter. Loop, clip and sequence any sound from any source (asset/file/URL/stream) in gapless playlists.
3-
version: 0.10.1
3+
version: 0.10.2
44
repository: https://github.com/ryanheise/just_audio/tree/minor/just_audio
55
issue_tracker: https://github.com/ryanheise/just_audio/issues
66
topics:

0 commit comments

Comments
 (0)