|
|
|
/*
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
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.
|
|
|
|
* <p/>
|
|
|
|
* 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<TransferStatus> streamStatuses = new ArrayList<TransferStatus>();
|
|
|
|
private final List<TransferStatus> downloadStatuses = new ArrayList<TransferStatus>();
|
|
|
|
private final List<TransferStatus> uploadStatuses = new ArrayList<TransferStatus>();
|
|
|
|
private final List<PlayStatus> remotePlays = new ArrayList<PlayStatus>();
|
|
|
|
|
|
|
|
// Maps from player ID to latest inactive stream status.
|
|
|
|
private final Map<Integer, TransferStatus> inactiveStreamStatuses = new LinkedHashMap<Integer, TransferStatus>();
|
|
|
|
|
|
|
|
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<TransferStatus> getAllStreamStatuses() {
|
|
|
|
|
|
|
|
List<TransferStatus> result = new ArrayList<TransferStatus>(streamStatuses);
|
|
|
|
|
|
|
|
// Add inactive status for those players that have no active status.
|
|
|
|
Set<Integer> activePlayers = new HashSet<Integer>();
|
|
|
|
for (TransferStatus status : streamStatuses) {
|
|
|
|
activePlayers.add(status.getPlayer().getId());
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Map.Entry<Integer, TransferStatus> entry : inactiveStreamStatuses.entrySet()) {
|
|
|
|
if (!activePlayers.contains(entry.getKey())) {
|
|
|
|
result.add(entry.getValue());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized List<TransferStatus> getStreamStatusesForPlayer(Player player) {
|
|
|
|
List<TransferStatus> result = new ArrayList<TransferStatus>();
|
|
|
|
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<TransferStatus> getAllDownloadStatuses() {
|
|
|
|
return new ArrayList<TransferStatus>(downloadStatuses);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized TransferStatus createUploadStatus(Player player) {
|
|
|
|
return createStatus(player, uploadStatuses);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void removeUploadStatus(TransferStatus status) {
|
|
|
|
uploadStatuses.remove(status);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized List<TransferStatus> getAllUploadStatuses() {
|
|
|
|
return new ArrayList<TransferStatus>(uploadStatuses);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void addRemotePlay(PlayStatus playStatus) {
|
|
|
|
remotePlays.removeIf(PlayStatus::isExpired);
|
|
|
|
remotePlays.add(playStatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized List<PlayStatus> getPlayStatuses() {
|
|
|
|
Map<Integer, PlayStatus> result = new LinkedHashMap<Integer, PlayStatus>();
|
|
|
|
for (PlayStatus remotePlay : remotePlays) {
|
|
|
|
if (!remotePlay.isExpired()) {
|
|
|
|
result.put(remotePlay.getPlayer().getId(), remotePlay);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
List<TransferStatus> statuses = new ArrayList<TransferStatus>();
|
|
|
|
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<PlayStatus>(result.values());
|
|
|
|
}
|
|
|
|
|
|
|
|
private synchronized TransferStatus createStatus(Player player, List<TransferStatus> statusList) {
|
|
|
|
TransferStatus status = new TransferStatus();
|
|
|
|
status.setPlayer(player);
|
|
|
|
statusList.add(status);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setMediaFileService(MediaFileService mediaFileService) {
|
|
|
|
this.mediaFileService = mediaFileService;
|
|
|
|
}
|
|
|
|
}
|