diff --git a/b0esche_cloud/lib/widgets/web_audio_player.dart b/b0esche_cloud/lib/widgets/web_audio_player.dart index c24d11e..58f0eab 100644 --- a/b0esche_cloud/lib/widgets/web_audio_player.dart +++ b/b0esche_cloud/lib/widgets/web_audio_player.dart @@ -12,43 +12,74 @@ class AudioPlayer { final StreamController _errorController = StreamController.broadcast(); + // Store subscriptions for cleanup + StreamSubscription? _durationSubscription; + StreamSubscription? _positionSubscription; + StreamSubscription? _playSubscription; + StreamSubscription? _pauseSubscription; + StreamSubscription? _endedSubscription; + StreamSubscription? _errorSubscription; + Stream get positionStream => _positionController.stream; Stream get durationStream => _durationController.stream; Stream get playingStream => _playingController.stream; Stream get errorStream => _errorController.stream; + void _disposeSubscriptions() { + _durationSubscription?.cancel(); + _positionSubscription?.cancel(); + _playSubscription?.cancel(); + _pauseSubscription?.cancel(); + _endedSubscription?.cancel(); + _errorSubscription?.cancel(); + + _durationSubscription = null; + _positionSubscription = null; + _playSubscription = null; + _pauseSubscription = null; + _endedSubscription = null; + _errorSubscription = null; + } + Future setUrl(String url) async { + // Clean up any existing subscriptions + _disposeSubscriptions(); + try { _audioElement = web.HTMLAudioElement(); _audioElement!.src = url; _audioElement!.crossOrigin = 'anonymous'; // Handle CORS - // Set up event listeners - _audioElement!.onLoadedMetadata.listen((_) { - _durationController.add( - Duration(milliseconds: (_audioElement!.duration * 1000).toInt()), - ); + // Set up event listeners and store subscriptions + _durationSubscription = _audioElement!.onLoadedMetadata.listen((_) { + if (_audioElement != null) { + _durationController.add( + Duration(milliseconds: (_audioElement!.duration * 1000).toInt()), + ); + } }); - _audioElement!.onTimeUpdate.listen((_) { - _positionController.add( - Duration(milliseconds: (_audioElement!.currentTime * 1000).toInt()), - ); + _positionSubscription = _audioElement!.onTimeUpdate.listen((_) { + if (_audioElement != null) { + _positionController.add( + Duration(milliseconds: (_audioElement!.currentTime * 1000).toInt()), + ); + } }); - _audioElement!.onPlay.listen((_) { + _playSubscription = _audioElement!.onPlay.listen((_) { _playingController.add(true); }); - _audioElement!.onPause.listen((_) { + _pauseSubscription = _audioElement!.onPause.listen((_) { _playingController.add(false); }); - _audioElement!.onEnded.listen((_) { + _endedSubscription = _audioElement!.onEnded.listen((_) { _playingController.add(false); }); - _audioElement!.onError.listen((_) { + _errorSubscription = _audioElement!.onError.listen((_) { _errorController.add('Failed to load audio'); }); @@ -82,6 +113,7 @@ class AudioPlayer { } void dispose() { + _disposeSubscriptions(); _audioElement?.pause(); _audioElement = null; _positionController.close();