refreshPlayerList method

Future<void> refreshPlayerList()

Refresh the list of available players

Implementation

Future<void> refreshPlayerList() async {
  // Prevent concurrent refreshes
  if (_isRefreshing) {
    PlayerctlLogger.debug(
      'Skipping refresh - already in progress',
      'Refresh',
    );
    return;
  }

  _isRefreshing = true;
  try {
    final players = await _service.getAvailablePlayers();
    final hasPlayer = players.isNotEmpty;
    final previousSelected = _state.selectedPlayer;

    String selected = _state.selectedPlayer;
    bool needsReconnect = false;

    // Case 1: No players available
    if (players.isEmpty) {
      selected = '';
      PlayerctlLogger.player('No players available');
    }
    // Case 2: First time selecting a player
    else if (selected.isEmpty) {
      selected = players.first;
      needsReconnect = true;
      PlayerctlLogger.player('Auto-selecting first player: $selected');
    }
    // Case 3: Currently selected player no longer exists
    else if (!players.contains(selected)) {
      selected = players.first;
      needsReconnect = true;
      PlayerctlLogger.player(
        'Selected player "$previousSelected" no longer available, switching to: $selected',
      );
    }
    // Case 4: Selected player still exists (no change needed)
    else {
      PlayerctlLogger.debug(
        'Current player "$selected" still available',
        'Player',
      );
    }

    _updateState(
      _state.copyWith(
        availablePlayers: players,
        hasActivePlayer: hasPlayer,
        selectedPlayer: selected,
        currentMedia: hasPlayer ? _state.currentMedia : MediaInfo.empty(),
      ),
    );

    // If we switched to a different player, reconnect
    if (needsReconnect && hasPlayer && selected != previousSelected) {
      PlayerctlLogger.player('Reconnecting to new player: $selected');

      // Stop all current syncing
      stopListening();
      _stopVolumeSync();
      _stopMetadataRefresh();

      // Small delay to ensure clean disconnect
      await Future.delayed(const Duration(milliseconds: 100));

      // Fetch metadata immediately for new player
      try {
        final metadata = await _service.getCurrentMetadata(selected);
        if (metadata.isNotEmpty) {
          _updateMediaInfo(metadata);
        }
      } catch (e) {
        PlayerctlLogger.error(
          'Error fetching metadata for player $selected',
          'Player',
          e,
        );
      }

      // Fetch current state
      await updateCurrentVolume();
      await updateShuffleStatus();
      await updateLoopStatus();

      // Start listening and all sync timers
      startListening(selected);
      _startVolumeSync();
      _startMetadataRefresh();
    }
  } catch (e) {
    PlayerctlLogger.error('Error refreshing player list', 'Player', e);
  } finally {
    _isRefreshing = false;
  }
}