// audio_player_controller.dart import 'dart:async'; import 'package:get/get.dart'; import 'package:just_audio/just_audio.dart'; import '../common_widget/Song_widegt.dart'; import '../models/getMusicList_bean.dart'; import '../common/download_manager.dart'; import '../common_widget/app_data.dart'; import '../api/api_music_list.dart'; class AudioPlayerController extends GetxController { final audioPlayer = AudioPlayer(); final downloadManager = Get.find(); final appData = AppData(); // Observable values final currentSongIndex = 0.obs; final duration = Duration.zero.obs; final position = Duration.zero.obs; final isPlaying = false.obs; final isLoading = false.obs; final isRotating = false.obs; final isDisposed = false.obs; // Current song info final artistName = ''.obs; final musicName = ''.obs; final likesStatus = false.obs; final collectionsStatus = false.obs; // Song lists final songList = [].obs; final ids = [].obs; final songUrls = [].obs; final artists = [].obs; final musicNames = [].obs; final likes = [].obs; final collections = [].obs; StreamSubscription? _positionSubscription; StreamSubscription? _durationSubscription; StreamSubscription? _playerStateSubscription; void initWithSongs(List songs, int initialIndex) { songList.value = songs; currentSongIndex.value = initialIndex; _initializeSongLists(); _initializePlayer(); } void _initializeSongLists() { for (int i = 0; i < songList.length; i++) { ids.add(songList[i].id); songUrls.add(songList[i].musicurl ?? ''); artists.add(songList[i].artist); musicNames.add(songList[i].title); likes.add(songList[i].likes ?? false); collections.add(songList[i].collection ?? false); } _updateCurrentSongInfo(); } void _initializePlayer() { // Position updates _positionSubscription = audioPlayer.positionStream.listen((pos) { position.value = pos; }); // Duration updates _durationSubscription = audioPlayer.durationStream.listen((dur) { duration.value = dur ?? Duration.zero; }); // Player state updates _playerStateSubscription = audioPlayer.playerStateStream.listen((state) { // isPlaying.value = state.playing; if (state.processingState == ProcessingState.completed) { playNext(); } }); // Initial load _loadAndPlayCurrentSong(); } void _updateCurrentSongInfo() { artistName.value = artists[currentSongIndex.value]; musicName.value = musicNames[currentSongIndex.value]; likesStatus.value = likes[currentSongIndex.value]; collectionsStatus.value = collections[currentSongIndex.value]; } Future toggleLike() async { final currentIndex = currentSongIndex.value; likesStatus.value = !likesStatus.value; likes[currentIndex] = likesStatus.value; } Future toggleCollection() async { final currentIndex = currentSongIndex.value; collectionsStatus.value = !collectionsStatus.value; collections[currentIndex] = collectionsStatus.value; } Future _loadAndPlayCurrentSong() async { isLoading.value = true; position.value = Duration.zero; duration.value = Duration.zero; _updateCurrentSongInfo(); await _checkAndUpdateSongStatus(currentSongIndex.value); try { await audioPlayer.stop(); final localSong = downloadManager.getLocalSong(currentSongIndex.value); final audioSource = localSong != null ? AudioSource.file(localSong.musicurl!) : AudioSource.uri(Uri.parse(songUrls[currentSongIndex.value])); await audioPlayer.setAudioSource(audioSource, preload: true); duration.value = await audioPlayer.duration ?? Duration.zero; await audioPlayer.play(); } catch (e) { print('Error loading audio source: $e'); } finally { isLoading.value = false; } } Future _checkAndUpdateSongStatus(int index) async { if (songList[index].likes == null || songList[index].collection == null) { try { MusicListBean musicListBean = await GetMusic().getMusicById( id: ids[index], Authorization: appData.currentToken, ); if (musicListBean.code == 200) { likes[index] = musicListBean.likeOrNot!; collections[index] = musicListBean.collectOrNot!; if (index == currentSongIndex.value) { likesStatus.value = musicListBean.likeOrNot!; collectionsStatus.value = musicListBean.collectOrNot!; } } } catch (e) { print('Error fetching song status: $e'); } } } void playOrPause() async { if (audioPlayer.playing) { isPlaying.value = false; await audioPlayer.pause(); } else { await audioPlayer.play(); isPlaying.value = true; } } void playNext() { if (currentSongIndex.value < songList.length - 1) { currentSongIndex.value++; } else { currentSongIndex.value = 0; } _loadAndPlayCurrentSong(); } void playPrevious() { if (currentSongIndex.value > 0) { currentSongIndex.value--; } else { currentSongIndex.value = songList.length - 1; } _loadAndPlayCurrentSong(); } void seekTo(Duration position) async { await audioPlayer.seek(position); } void changeSong(int index) { currentSongIndex.value = index; _loadAndPlayCurrentSong(); } @override void onClose() { isDisposed.value = true; _positionSubscription?.cancel(); _durationSubscription?.cancel(); _playerStateSubscription?.cancel(); audioPlayer.dispose(); super.onClose(); } }