/* This file is part of Airsonic. Airsonic is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Airsonic is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Airsonic. If not, see . Copyright 2016 (C) Airsonic Authors Based upon Subsonic, Copyright 2009 (C) Sindre Mehus */ package org.airsonic.player.service; import org.airsonic.player.domain.MediaFile; import org.airsonic.player.domain.PlayStatus; import org.airsonic.player.domain.Player; import org.airsonic.player.domain.TransferStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.File; import java.util.*; /** * Provides services for maintaining the list of stream, download and upload statuses. *

* Note that for stream statuses, the last inactive status is also stored. * * @author Sindre Mehus * @see TransferStatus */ @Service public class StatusService { @Autowired private MediaFileService mediaFileService; private final List streamStatuses = new ArrayList(); private final List downloadStatuses = new ArrayList(); private final List uploadStatuses = new ArrayList(); private final List remotePlays = new ArrayList(); // Maps from player ID to latest inactive stream status. private final Map inactiveStreamStatuses = new LinkedHashMap(); public synchronized TransferStatus createStreamStatus(Player player) { // Reuse existing status, if possible. TransferStatus status = inactiveStreamStatuses.get(player.getId()); if (status != null) { status.setActive(true); } else { status = createStatus(player, streamStatuses); } return status; } public synchronized void removeStreamStatus(TransferStatus status) { // Move it to the map of inactive statuses. status.setActive(false); inactiveStreamStatuses.put(status.getPlayer().getId(), status); streamStatuses.remove(status); } public synchronized List getAllStreamStatuses() { List result = new ArrayList(streamStatuses); // Add inactive status for those players that have no active status. Set activePlayers = new HashSet(); for (TransferStatus status : streamStatuses) { activePlayers.add(status.getPlayer().getId()); } for (Map.Entry entry : inactiveStreamStatuses.entrySet()) { if (!activePlayers.contains(entry.getKey())) { result.add(entry.getValue()); } } return result; } public synchronized List getStreamStatusesForPlayer(Player player) { List result = new ArrayList(); for (TransferStatus status : streamStatuses) { if (status.getPlayer().getId().equals(player.getId())) { result.add(status); } } // If no active statuses exists, add the inactive one. if (result.isEmpty()) { TransferStatus inactiveStatus = inactiveStreamStatuses.get(player.getId()); if (inactiveStatus != null) { result.add(inactiveStatus); } } return result; } public synchronized TransferStatus createDownloadStatus(Player player) { return createStatus(player, downloadStatuses); } public synchronized void removeDownloadStatus(TransferStatus status) { downloadStatuses.remove(status); } public synchronized List getAllDownloadStatuses() { return new ArrayList(downloadStatuses); } public synchronized TransferStatus createUploadStatus(Player player) { return createStatus(player, uploadStatuses); } public synchronized void removeUploadStatus(TransferStatus status) { uploadStatuses.remove(status); } public synchronized List getAllUploadStatuses() { return new ArrayList(uploadStatuses); } public synchronized void addRemotePlay(PlayStatus playStatus) { remotePlays.removeIf(PlayStatus::isExpired); remotePlays.add(playStatus); } public synchronized List getPlayStatuses() { Map result = new LinkedHashMap(); for (PlayStatus remotePlay : remotePlays) { if (!remotePlay.isExpired()) { result.put(remotePlay.getPlayer().getId(), remotePlay); } } List statuses = new ArrayList(); statuses.addAll(inactiveStreamStatuses.values()); statuses.addAll(streamStatuses); for (TransferStatus streamStatus : statuses) { Player player = streamStatus.getPlayer(); File file = streamStatus.getFile(); if (file == null) { continue; } MediaFile mediaFile = mediaFileService.getMediaFile(file); if (player == null || mediaFile == null) { continue; } Date time = new Date(System.currentTimeMillis() - streamStatus.getMillisSinceLastUpdate()); result.put(player.getId(), new PlayStatus(mediaFile, player, time)); } return new ArrayList(result.values()); } private synchronized TransferStatus createStatus(Player player, List statusList) { TransferStatus status = new TransferStatus(); status.setPlayer(player); statusList.add(status); return status; } public void setMediaFileService(MediaFileService mediaFileService) { this.mediaFileService = mediaFileService; } }