Skip to content

Commit bdc9279

Browse files
committed
Minor tweaks
1 parent 972f417 commit bdc9279

4 files changed

Lines changed: 73 additions & 17 deletions

File tree

core/src/main/java/xyz/gianlu/librespot/player/AudioFile.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
import org.jetbrains.annotations.NotNull;
44

5+
import java.io.Closeable;
56
import java.io.IOException;
67

78
/**
89
* @author Gianlu
910
*/
10-
public interface AudioFile {
11+
public interface AudioFile extends Closeable {
1112
void writeChunk(byte[] chunk, int chunkIndex, boolean cached) throws IOException;
1213

1314
void cacheFailedChunk(int index, @NotNull AudioFile file);

core/src/main/java/xyz/gianlu/librespot/player/AudioFileFetch.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class AudioFileFetch implements AudioFile {
2121
private final BytesArrayList headersData = new BytesArrayList();
2222
private int size = -1;
2323
private int chunks = -1;
24+
private volatile boolean closed = false;
2425

2526
AudioFileFetch(@Nullable CacheManager.Handler cache) {
2627
this.cache = cache;
@@ -34,6 +35,8 @@ public void writeChunk(byte[] chunk, int chunkIndex, boolean cached) {
3435

3536
@Override
3637
public synchronized void writeHeader(byte id, byte[] bytes, boolean cached) {
38+
if (closed) return;
39+
3740
if (!cached && cache != null) {
3841
headersId.write(id);
3942
headersData.add(bytes);
@@ -54,6 +57,8 @@ public void cacheFailedHeader(@NotNull AudioFile file) {
5457

5558
@Override
5659
public synchronized void headerEnd(boolean cached) {
60+
if (closed) return;
61+
5762
if (!cached && cache != null) {
5863
headersId.write(CacheManager.BYTE_CREATED_AT);
5964
headersData.add(BigInteger.valueOf(System.currentTimeMillis() / 1000).toByteArray());
@@ -91,4 +96,9 @@ public int getChunks() {
9196
if (chunks == -1) throw new IllegalStateException("Headers not received yet!");
9297
return chunks;
9398
}
99+
100+
@Override
101+
public void close() {
102+
closed = true;
103+
}
94104
}

core/src/main/java/xyz/gianlu/librespot/player/AudioFileStreaming.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import xyz.gianlu.librespot.common.proto.Metadata;
88
import xyz.gianlu.librespot.core.Session;
99

10+
import java.io.Closeable;
1011
import java.io.IOException;
1112
import java.io.InputStream;
1213
import java.util.concurrent.ExecutorService;
@@ -41,7 +42,7 @@ String getFileIdHex() {
4142
}
4243

4344
@NotNull
44-
InputStream stream() {
45+
public InputStream stream() {
4546
if (chunksBuffer == null) throw new IllegalStateException("Stream not open!");
4647
return chunksBuffer.stream();
4748
}
@@ -124,7 +125,14 @@ public void streamError(short code) {
124125
LOGGER.fatal(String.format("Stream error, code: %d", code));
125126
}
126127

127-
private class ChunksBuffer {
128+
@Override
129+
public void close() {
130+
executorService.shutdown();
131+
if (chunksBuffer != null)
132+
chunksBuffer.close();
133+
}
134+
135+
private class ChunksBuffer implements Closeable {
128136
private final int size;
129137
private final byte[][] buffer;
130138
private final boolean[] available;
@@ -143,6 +151,8 @@ private class ChunksBuffer {
143151
}
144152

145153
void writeChunk(@NotNull byte[] chunk, int chunkIndex) throws IOException {
154+
if (internalStream != null && internalStream.closed) return;
155+
146156
if (chunk.length != buffer[chunkIndex].length)
147157
throw new IllegalArgumentException(String.format("Buffer size mismatch, required: %d, received: %d, index: %d", buffer[chunkIndex].length, chunk.length, chunkIndex));
148158

@@ -158,6 +168,8 @@ void writeChunk(@NotNull byte[] chunk, int chunkIndex) throws IOException {
158168
}
159169

160170
private void waitFor(int chunkIndex) throws IOException {
171+
if (internalStream != null && internalStream.closed) return;
172+
161173
synchronized (waitForChunk) {
162174
try {
163175
waitForChunk.set(chunkIndex);
@@ -174,13 +186,25 @@ InputStream stream() {
174186
return internalStream;
175187
}
176188

189+
@Override
190+
public void close() {
191+
if (internalStream != null)
192+
internalStream.close();
193+
}
194+
177195
private class InternalStream extends InputStream {
178196
private int pos = 0;
179197
private int mark = 0;
198+
private volatile boolean closed = false;
180199

181200
private InternalStream() {
182201
}
183202

203+
@Override
204+
public void close() {
205+
closed = true;
206+
}
207+
184208
@Override
185209
public synchronized int available() {
186210
return size - pos;
@@ -203,6 +227,8 @@ public synchronized void reset() {
203227

204228
@Override
205229
public synchronized long skip(long n) throws IOException {
230+
if (closed) throw new IOException("Stream is closed!");
231+
206232
long k = size - pos;
207233
if (n < k) k = n < 0 ? 0 : n;
208234
pos += k;
@@ -230,6 +256,8 @@ private void checkAvailability(int chunk, boolean wait) throws IOException {
230256

231257
@Override
232258
public int read(@NotNull byte[] b, int off, int len) throws IOException {
259+
if (closed) throw new IOException("Stream is closed!");
260+
233261
if (off < 0 || len < 0 || len > b.length - off) {
234262
throw new IndexOutOfBoundsException(String.format("off: %d, len: %d, buffer: %d", off, len, buffer.length));
235263
} else if (len == 0) {
@@ -258,6 +286,8 @@ public int read(@NotNull byte[] b, int off, int len) throws IOException {
258286

259287
@Override
260288
public synchronized int read() throws IOException {
289+
if (closed) throw new IOException("Stream is closed!");
290+
261291
if (pos >= size)
262292
return -1;
263293

core/src/main/java/xyz/gianlu/librespot/player/StreamFeeder.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,7 @@ private static Metadata.Track pickAlternativeIfNecessary(@NotNull Metadata.Track
4747
}
4848

4949
@NotNull
50-
public LoadedStream load(@NotNull Spirc.TrackRef ref, @NotNull AudioQualityPreference audioQualityPreference) throws IOException, MercuryClient.MercuryException {
51-
Metadata.Track track = session.mercury().sendSync(MercuryRequests.getTrack(TrackId.fromTrackRef(ref))).proto();
52-
track = pickAlternativeIfNecessary(track);
53-
if (track == null) {
54-
LOGGER.fatal("Couldn't find playable track: " + Utils.bytesToHex(ref.getGid()));
55-
throw new FeederException();
56-
}
57-
58-
Metadata.AudioFile file = audioQualityPreference.getFile(track);
59-
if (file == null) {
60-
LOGGER.fatal(String.format("Couldn't find any suitable audio file, available: %s", AudioQuality.listFormats(track)));
61-
throw new FeederException();
62-
}
63-
50+
public LoadedStream load(@NotNull Metadata.Track track, @NotNull Metadata.AudioFile file) throws IOException {
6451
session.send(Packet.Type.Unknown_0x4f, new byte[0]);
6552

6653
byte[] key = session.audioKey().getAudioKey(track, file);
@@ -78,6 +65,34 @@ public LoadedStream load(@NotNull Spirc.TrackRef ref, @NotNull AudioQualityPrefe
7865
return new LoadedStream(track, audioStreaming, normalizationData);
7966
}
8067

68+
@NotNull
69+
public LoadedStream load(@NotNull Metadata.Track track, @NotNull AudioQualityPreference audioQualityPreference) throws IOException {
70+
Metadata.AudioFile file = audioQualityPreference.getFile(track);
71+
if (file == null) {
72+
LOGGER.fatal(String.format("Couldn't find any suitable audio file, available: %s", AudioQuality.listFormats(track)));
73+
throw new FeederException();
74+
}
75+
76+
return load(track, file);
77+
}
78+
79+
@NotNull
80+
public LoadedStream load(@NotNull TrackId id, @NotNull AudioQualityPreference audioQualityPreference) throws IOException, MercuryClient.MercuryException {
81+
Metadata.Track track = session.mercury().sendSync(MercuryRequests.getTrack(id)).proto();
82+
track = pickAlternativeIfNecessary(track);
83+
if (track == null) {
84+
LOGGER.fatal("Couldn't find playable track: " + Utils.bytesToHex(id.getGid()));
85+
throw new FeederException();
86+
}
87+
88+
return load(track, audioQualityPreference);
89+
}
90+
91+
@NotNull
92+
public LoadedStream load(@NotNull Spirc.TrackRef ref, @NotNull AudioQualityPreference audioQualityPreference) throws IOException, MercuryClient.MercuryException {
93+
return load(TrackId.fromTrackRef(ref), audioQualityPreference);
94+
}
95+
8196
public enum AudioQuality {
8297
VORBIS_96(Metadata.AudioFile.Format.OGG_VORBIS_96),
8398
VORBIS_160(Metadata.AudioFile.Format.OGG_VORBIS_160),

0 commit comments

Comments
 (0)