aboutsummaryrefslogtreecommitdiff
path: root/subsonic-main/src/main/java/net/sourceforge/subsonic/io/PlayQueueInputStream.java
diff options
context:
space:
mode:
Diffstat (limited to 'subsonic-main/src/main/java/net/sourceforge/subsonic/io/PlayQueueInputStream.java')
-rw-r--r--subsonic-main/src/main/java/net/sourceforge/subsonic/io/PlayQueueInputStream.java154
1 files changed, 154 insertions, 0 deletions
diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/PlayQueueInputStream.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/io/PlayQueueInputStream.java
new file mode 100644
index 00000000..3be7fdd9
--- /dev/null
+++ b/subsonic-main/src/main/java/net/sourceforge/subsonic/io/PlayQueueInputStream.java
@@ -0,0 +1,154 @@
+/*
+ This file is part of Subsonic.
+
+ Subsonic 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.
+
+ Subsonic 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 Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+package net.sourceforge.subsonic.io;
+
+import net.sourceforge.subsonic.Logger;
+import net.sourceforge.subsonic.domain.MediaFile;
+import net.sourceforge.subsonic.domain.VideoTranscodingSettings;
+import net.sourceforge.subsonic.service.MediaFileService;
+import net.sourceforge.subsonic.service.SearchService;
+import net.sourceforge.subsonic.util.FileUtil;
+import net.sourceforge.subsonic.domain.Player;
+import net.sourceforge.subsonic.domain.PlayQueue;
+import net.sourceforge.subsonic.domain.TransferStatus;
+import net.sourceforge.subsonic.service.AudioScrobblerService;
+import net.sourceforge.subsonic.service.TranscodingService;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * Implementation of {@link InputStream} which reads from a {@link net.sourceforge.subsonic.domain.PlayQueue}.
+ *
+ * @author Sindre Mehus
+ */
+public class PlayQueueInputStream extends InputStream {
+
+ private static final Logger LOG = Logger.getLogger(PlayQueueInputStream.class);
+
+ private final Player player;
+ private final TransferStatus status;
+ private final Integer maxBitRate;
+ private final String preferredTargetFormat;
+ private final VideoTranscodingSettings videoTranscodingSettings;
+ private final TranscodingService transcodingService;
+ private final AudioScrobblerService audioScrobblerService;
+ private final MediaFileService mediaFileService;
+ private MediaFile currentFile;
+ private InputStream currentInputStream;
+ private SearchService searchService;
+
+ public PlayQueueInputStream(Player player, TransferStatus status, Integer maxBitRate, String preferredTargetFormat,
+ VideoTranscodingSettings videoTranscodingSettings, TranscodingService transcodingService,
+ AudioScrobblerService audioScrobblerService, MediaFileService mediaFileService, SearchService searchService) {
+ this.player = player;
+ this.status = status;
+ this.maxBitRate = maxBitRate;
+ this.preferredTargetFormat = preferredTargetFormat;
+ this.videoTranscodingSettings = videoTranscodingSettings;
+ this.transcodingService = transcodingService;
+ this.audioScrobblerService = audioScrobblerService;
+ this.mediaFileService = mediaFileService;
+ this.searchService = searchService;
+ }
+
+ @Override
+ public int read() throws IOException {
+ byte[] b = new byte[1];
+ int n = read(b);
+ return n == -1 ? -1 : b[0];
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ prepare();
+ if (currentInputStream == null || player.getPlayQueue().getStatus() == PlayQueue.Status.STOPPED) {
+ return -1;
+ }
+
+ int n = currentInputStream.read(b, off, len);
+
+ // If end of song reached, skip to next song and call read() again.
+ if (n == -1) {
+ player.getPlayQueue().next();
+ close();
+ return read(b, off, len);
+ } else {
+ status.addBytesTransfered(n);
+ }
+ return n;
+ }
+
+ private void prepare() throws IOException {
+ PlayQueue playQueue = player.getPlayQueue();
+
+ // If playlist is in auto-random mode, populate it with new random songs.
+ if (playQueue.getIndex() == -1 && playQueue.getRandomSearchCriteria() != null) {
+ populateRandomPlaylist(playQueue);
+ }
+
+ MediaFile result;
+ synchronized (playQueue) {
+ result = playQueue.getCurrentFile();
+ }
+ MediaFile file = result;
+ if (file == null) {
+ close();
+ } else if (!file.equals(currentFile)) {
+ close();
+ LOG.info(player.getUsername() + " listening to \"" + FileUtil.getShortPath(file.getFile()) + "\"");
+ mediaFileService.incrementPlayCount(file);
+ if (player.getClientId() == null) { // Don't scrobble REST players.
+ audioScrobblerService.register(file, player.getUsername(), false);
+ }
+
+ TranscodingService.Parameters parameters = transcodingService.getParameters(file, player, maxBitRate, preferredTargetFormat, videoTranscodingSettings);
+ currentInputStream = transcodingService.getTranscodedInputStream(parameters);
+ currentFile = file;
+ status.setFile(currentFile.getFile());
+ }
+ }
+
+ private void populateRandomPlaylist(PlayQueue playQueue) throws IOException {
+ List<MediaFile> files = searchService.getRandomSongs(playQueue.getRandomSearchCriteria());
+ playQueue.addFiles(false, files);
+ LOG.info("Recreated random playlist with " + playQueue.size() + " songs.");
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ if (currentInputStream != null) {
+ currentInputStream.close();
+ }
+ } finally {
+ if (player.getClientId() == null) { // Don't scrobble REST players.
+ audioScrobblerService.register(currentFile, player.getUsername(), true);
+ }
+ currentInputStream = null;
+ currentFile = null;
+ }
+ }
+}