@@ -72,7 +72,6 @@ class MusifyAudioHandler extends BaseAudioHandler {
7272 bool _isUpdatingState = false ;
7373 int _songTransitionCounter = 0 ;
7474 bool _completionEventPending = false ;
75- bool _completionHandlerLoadStarted = false ;
7675
7776 String ? _lastError;
7877 int _consecutiveErrors = 0 ;
@@ -301,37 +300,31 @@ class MusifyAudioHandler extends BaseAudioHandler {
301300 void _handleProcessingStateChange (ProcessingState state) {
302301 try {
303302 if (state == ProcessingState .completed) {
304- if (! sleepTimerExpired && ! _completionEventPending) {
303+ // Only process completion once - prevent re-entrancy
304+ if (! _completionEventPending && ! sleepTimerExpired) {
305305 _completionEventPending = true ;
306-
307- Future .microtask (() async {
308- try {
309- if (! sleepTimerExpired && _completionEventPending) {
310- await _handleSongCompletion ();
311- }
312- } finally {
313- // Only reset if still marked as pending (another event didn't override)
314- if (_completionEventPending) {
315- _completionEventPending = false ;
316- _completionHandlerLoadStarted = false ;
317- } else {
318- logger.log (
319- '[COMPLETION] Flag already false in finally block (was overridden)' ,
320- null ,
321- null ,
322- );
323- }
324- }
325- });
306+ // Schedule immediately to process completion
307+ Future .microtask (_processCompletion);
326308 }
327- } else if (state == ProcessingState .ready) {
328- _completionEventPending = false ;
329309 }
330310 } catch (e, stackTrace) {
331311 logger.log ('Error handling processing state change' , e, stackTrace);
332312 }
333313 }
334314
315+ Future <void > _processCompletion () async {
316+ try {
317+ if (_completionEventPending && ! sleepTimerExpired) {
318+ await _handleSongCompletion ();
319+ }
320+ } catch (e, stackTrace) {
321+ logger.log ('Error processing song completion' , e, stackTrace);
322+ } finally {
323+ // Always reset the flag to allow next completion to be processed
324+ _completionEventPending = false ;
325+ }
326+ }
327+
335328 void _handlePlaybackError () {
336329 _consecutiveErrors++ ;
337330 logger.log (
@@ -789,19 +782,8 @@ class MusifyAudioHandler extends BaseAudioHandler {
789782 return ;
790783 }
791784
792- // If already loading any song, skip the request
793- // UNLESS we're in the middle of handling a completion event (allow one load attempt)
794- if (_currentLoadingIndex >= 0 && ! _completionEventPending) {
795- return ;
796- }
797-
798- if (_currentLoadingIndex >= 0 &&
799- _completionEventPending &&
800- ! _completionHandlerLoadStarted) {
801- _completionHandlerLoadStarted = true ;
802- } else if (_currentLoadingIndex >= 0 &&
803- _completionEventPending &&
804- _completionHandlerLoadStarted) {
785+ // If already loading any song, skip to prevent race conditions
786+ if (_currentLoadingIndex >= 0 ) {
805787 return ;
806788 }
807789
@@ -1053,10 +1035,6 @@ class MusifyAudioHandler extends BaseAudioHandler {
10531035 audioSource,
10541036 songUrl,
10551037 isOffline,
1056- onPlayStarted: () {
1057- _currentLoadingIndex = - 1 ;
1058- _currentLoadingTransitionId = - 1 ;
1059- },
10601038 );
10611039 } catch (e, stackTrace) {
10621040 logger.log ('Error playing song' , e, stackTrace);
@@ -1111,9 +1089,8 @@ class MusifyAudioHandler extends BaseAudioHandler {
11111089 Map song,
11121090 AudioSource audioSource,
11131091 String songUrl,
1114- bool isOffline, {
1115- Function ()? onPlayStarted,
1116- }) async {
1092+ bool isOffline,
1093+ ) async {
11171094 try {
11181095 await audioPlayer
11191096 .setAudioSource (audioSource)
@@ -1129,9 +1106,6 @@ class MusifyAudioHandler extends BaseAudioHandler {
11291106
11301107 await audioPlayer.play ();
11311108
1132- // Invoke callback immediately after play() succeeds
1133- onPlayStarted? .call ();
1134-
11351109 if (! isOffline) {
11361110 final cacheKey =
11371111 'song_${song ['ytid' ]}_${audioQualitySetting .value }_url' ;
0 commit comments