From 0d65693cd81a9f04b6a0dbac84656abbe9c66645 Mon Sep 17 00:00:00 2001 From: Gianlu Date: Mon, 21 Dec 2020 15:36:25 +0100 Subject: [PATCH 1/2] Making PacketsManager (PacketsReceiver) sync --- .../librespot/audio/AudioKeyManager.java | 14 ++---- .../audio/storage/ChannelManager.java | 21 +++----- .../gianlu/librespot/core/PacketsManager.java | 50 ------------------- .../librespot/core/PacketsReceiver.java | 11 ++++ .../xyz/gianlu/librespot/core/Session.java | 11 +--- .../librespot/mercury/MercuryClient.java | 23 ++++----- 6 files changed, 33 insertions(+), 97 deletions(-) delete mode 100644 lib/src/main/java/xyz/gianlu/librespot/core/PacketsManager.java create mode 100644 lib/src/main/java/xyz/gianlu/librespot/core/PacketsReceiver.java diff --git a/lib/src/main/java/xyz/gianlu/librespot/audio/AudioKeyManager.java b/lib/src/main/java/xyz/gianlu/librespot/audio/AudioKeyManager.java index d3d23fa5..3502e70f 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/audio/AudioKeyManager.java +++ b/lib/src/main/java/xyz/gianlu/librespot/audio/AudioKeyManager.java @@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import xyz.gianlu.librespot.common.Utils; -import xyz.gianlu.librespot.core.PacketsManager; +import xyz.gianlu.librespot.core.PacketsReceiver; import xyz.gianlu.librespot.core.Session; import xyz.gianlu.librespot.crypto.Packet; @@ -22,15 +22,16 @@ /** * @author Gianlu */ -public final class AudioKeyManager extends PacketsManager { +public final class AudioKeyManager implements PacketsReceiver { private static final byte[] ZERO_SHORT = new byte[]{0, 0}; private static final Logger LOGGER = LogManager.getLogger(AudioKeyManager.class); private static final long AUDIO_KEY_REQUEST_TIMEOUT = 2000; private final AtomicInteger seqHolder = new AtomicInteger(0); private final Map callbacks = Collections.synchronizedMap(new HashMap<>()); + private final Session session; public AudioKeyManager(@NotNull Session session) { - super(session, "audio-keys"); + this.session = session; } @NotNull @@ -67,7 +68,7 @@ else throw new AesKeyException(String.format("Failed fetching audio key! {gid: % } @Override - protected void handle(@NotNull Packet packet) { + public void dispatch(@NotNull Packet packet) { ByteBuffer payload = ByteBuffer.wrap(packet.payload); int seq = payload.getInt(); @@ -89,11 +90,6 @@ protected void handle(@NotNull Packet packet) { } } - @Override - protected void exception(@NotNull Exception ex) { - LOGGER.fatal("Failed handling packet!", ex); - } - private interface Callback { void key(byte[] key); diff --git a/lib/src/main/java/xyz/gianlu/librespot/audio/storage/ChannelManager.java b/lib/src/main/java/xyz/gianlu/librespot/audio/storage/ChannelManager.java index d63ae8e1..10043a29 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/audio/storage/ChannelManager.java +++ b/lib/src/main/java/xyz/gianlu/librespot/audio/storage/ChannelManager.java @@ -6,11 +6,12 @@ import org.jetbrains.annotations.NotNull; import xyz.gianlu.librespot.common.NameThreadFactory; import xyz.gianlu.librespot.common.Utils; -import xyz.gianlu.librespot.core.PacketsManager; +import xyz.gianlu.librespot.core.PacketsReceiver; import xyz.gianlu.librespot.core.Session; import xyz.gianlu.librespot.crypto.Packet; import java.io.ByteArrayOutputStream; +import java.io.Closeable; import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; @@ -25,15 +26,16 @@ /** * @author Gianlu */ -public class ChannelManager extends PacketsManager { +public class ChannelManager implements Closeable, PacketsReceiver { public static final int CHUNK_SIZE = 128 * 1024; private static final Logger LOGGER = LogManager.getLogger(ChannelManager.class); private final Map channels = new HashMap<>(); private final AtomicInteger seqHolder = new AtomicInteger(0); private final ExecutorService executorService = Executors.newCachedThreadPool(new NameThreadFactory(r -> "channel-queue-" + r.hashCode())); + private final Session session; public ChannelManager(@NotNull Session session) { - super(session, "channels"); + this.session = session; } void requestChunk(@NotNull ByteString fileId, int index, @NotNull AudioFile file) throws IOException { @@ -59,12 +61,7 @@ void requestChunk(@NotNull ByteString fileId, int index, @NotNull AudioFile file } @Override - protected void handle(@NotNull Packet packet) { - throw new UnsupportedOperationException(); - } - - @Override - protected void appendToQueue(@NotNull Packet packet) { + public void dispatch(@NotNull Packet packet) { ByteBuffer payload = ByteBuffer.wrap(packet.payload); if (packet.is(Packet.Type.StreamChunkRes)) { short id = payload.getShort(); @@ -89,15 +86,9 @@ protected void appendToQueue(@NotNull Packet packet) { } } - @Override - protected void exception(@NotNull Exception ex) { - LOGGER.fatal("Failed handling packet!", ex); - } - @Override public void close() { executorService.shutdown(); - super.close(); } public class Channel { diff --git a/lib/src/main/java/xyz/gianlu/librespot/core/PacketsManager.java b/lib/src/main/java/xyz/gianlu/librespot/core/PacketsManager.java deleted file mode 100644 index 18944f17..00000000 --- a/lib/src/main/java/xyz/gianlu/librespot/core/PacketsManager.java +++ /dev/null @@ -1,50 +0,0 @@ -package xyz.gianlu.librespot.core; - -import org.jetbrains.annotations.NotNull; -import xyz.gianlu.librespot.common.AsyncWorker; -import xyz.gianlu.librespot.crypto.Packet; - -import java.io.Closeable; -import java.io.IOException; -import java.util.concurrent.ExecutorService; - -/** - * @author Gianlu - */ -public abstract class PacketsManager implements Closeable { - protected final Session session; - private final ExecutorService executorService; - private final AsyncWorker asyncWorker; - - public PacketsManager(@NotNull Session session, @NotNull String name) { - this.session = session; - this.executorService = session.executor(); - this.asyncWorker = new AsyncWorker<>("pm-" + name, packet -> executorService.execute(() -> { - try { - handle(packet); - } catch (IOException ex) { - exception(ex); - } - })); - } - - public final void dispatch(@NotNull Packet packet) { - appendToQueue(packet); - } - - @Override - public void close() { - asyncWorker.close(); - } - - /** - * This method can be overridden to process packet synchronously. This MUST not block for a long period of time. - */ - protected void appendToQueue(@NotNull Packet packet) { - asyncWorker.submit(packet); - } - - protected abstract void handle(@NotNull Packet packet) throws IOException; - - protected abstract void exception(@NotNull Exception ex); -} diff --git a/lib/src/main/java/xyz/gianlu/librespot/core/PacketsReceiver.java b/lib/src/main/java/xyz/gianlu/librespot/core/PacketsReceiver.java new file mode 100644 index 00000000..6ce811e6 --- /dev/null +++ b/lib/src/main/java/xyz/gianlu/librespot/core/PacketsReceiver.java @@ -0,0 +1,11 @@ +package xyz.gianlu.librespot.core; + +import org.jetbrains.annotations.NotNull; +import xyz.gianlu.librespot.crypto.Packet; + +/** + * @author Gianlu + */ +public interface PacketsReceiver { + void dispatch(@NotNull Packet packet); +} diff --git a/lib/src/main/java/xyz/gianlu/librespot/core/Session.java b/lib/src/main/java/xyz/gianlu/librespot/core/Session.java index 83f34a14..78d30d55 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/core/Session.java +++ b/lib/src/main/java/xyz/gianlu/librespot/core/Session.java @@ -15,7 +15,6 @@ import okio.Okio; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.w3c.dom.Document; @@ -428,7 +427,6 @@ public void close() throws IOException { } if (audioKeyManager != null) { - audioKeyManager.close(); audioKeyManager = null; } @@ -625,11 +623,6 @@ public boolean reconnecting() { return !closing && !closed && conn == null; } - @NotNull - ExecutorService executor() { - return executorService; - } - @Nullable public String countryCode() { return countryCode; @@ -737,7 +730,7 @@ public String getUserAttribute(@NotNull String key) { return userAttributes.get(key); } - @Contract("_, !null -> !null") + @NotNull public String getUserAttribute(@NotNull String key, @NotNull String fallback) { return userAttributes.getOrDefault(key, fallback); } @@ -1366,7 +1359,7 @@ public void run() { try { parseProductInfo(new ByteArrayInputStream(packet.payload)); } catch (IOException | ParserConfigurationException | SAXException ex) { - LOGGER.warn("Failed parsing prodcut info!", ex); + LOGGER.warn("Failed parsing product info!", ex); } break; default: diff --git a/lib/src/main/java/xyz/gianlu/librespot/mercury/MercuryClient.java b/lib/src/main/java/xyz/gianlu/librespot/mercury/MercuryClient.java index 545256ff..1a0cad21 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/mercury/MercuryClient.java +++ b/lib/src/main/java/xyz/gianlu/librespot/mercury/MercuryClient.java @@ -13,11 +13,12 @@ import xyz.gianlu.librespot.common.BytesArrayList; import xyz.gianlu.librespot.common.ProtobufToJson; import xyz.gianlu.librespot.common.Utils; -import xyz.gianlu.librespot.core.PacketsManager; +import xyz.gianlu.librespot.core.PacketsReceiver; import xyz.gianlu.librespot.core.Session; import xyz.gianlu.librespot.crypto.Packet; import java.io.ByteArrayOutputStream; +import java.io.Closeable; import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; @@ -28,7 +29,7 @@ /** * @author Gianlu */ -public final class MercuryClient extends PacketsManager { +public final class MercuryClient implements PacketsReceiver, Closeable { private static final Logger LOGGER = LogManager.getLogger(MercuryClient.class); private static final int MERCURY_REQUEST_TIMEOUT = 3000; private final AtomicInteger seqHolder = new AtomicInteger(1); @@ -36,9 +37,10 @@ public final class MercuryClient extends PacketsManager { private final Object removeCallbackLock = new Object(); private final List subscriptions = Collections.synchronizedList(new ArrayList<>()); private final Map partials = new HashMap<>(); + private final Session session; public MercuryClient(@NotNull Session session) { - super(session, "mercury"); + this.session = session; } public void subscribe(@NotNull String uri, @NotNull SubListener listener) throws IOException, PubSubException { @@ -160,7 +162,7 @@ public int send(@NotNull RawMercuryRequest request, @NotNull Callback callback) } @Override - protected void handle(@NotNull Packet packet) throws InvalidProtocolBufferException { + public void dispatch(@NotNull Packet packet) { ByteBuffer payload = ByteBuffer.wrap(packet.payload); int seqLength = payload.getShort(); long seq; @@ -196,7 +198,7 @@ protected void handle(@NotNull Packet packet) throws InvalidProtocolBufferExcept header = Mercury.Header.parseFrom(partial.get(0)); } catch (InvalidProtocolBufferException ex) { LOGGER.fatal("Couldn't parse header! {bytes: {}}", Utils.bytesToHex(partial.get(0))); - throw ex; + return; } Response resp = new Response(header, partial); @@ -216,11 +218,10 @@ protected void handle(@NotNull Packet packet) throws InvalidProtocolBufferExcept LOGGER.debug("Couldn't dispatch Mercury event {seq: {}, uri: {}, code: {}, payload: {}}", seq, header.getUri(), header.getStatusCode(), resp.payload.toHex()); } else if (packet.is(Packet.Type.MercuryReq) || packet.is(Packet.Type.MercurySub) || packet.is(Packet.Type.MercuryUnsub)) { Callback callback = callbacks.remove(seq); - if (callback != null) { + if (callback != null) callback.response(resp); - } else { + else LOGGER.warn("Skipped Mercury response, seq: {}, uri: {}, code: {}", seq, header.getUri(), header.getStatusCode()); - } synchronized (removeCallbackLock) { removeCallbackLock.notifyAll(); @@ -230,11 +231,6 @@ protected void handle(@NotNull Packet packet) throws InvalidProtocolBufferExcept } } - @Override - protected void exception(@NotNull Exception ex) { - LOGGER.fatal("Failed handling packet!", ex); - } - public void interestedIn(@NotNull String uri, @NotNull SubListener listener) { subscriptions.add(new InternalSubListener(uri, listener, false)); } @@ -266,7 +262,6 @@ public void close() { } callbacks.clear(); - super.close(); } public interface JsonCallback { From 4faab365547dabbba823d9f77e1ada8375e324dc Mon Sep 17 00:00:00 2001 From: Gianlu Date: Mon, 21 Dec 2020 16:19:05 +0100 Subject: [PATCH 2/2] Clean up --- api/pom.xml | 2 +- .../java/xyz/gianlu/librespot/api/Utils.java | 2 +- .../librespot/api/handlers/PlayerHandler.java | 12 ++----- lib/pom.xml | 2 +- .../audio/decrypt/AesAudioDecrypt.java | 2 +- .../gianlu/librespot/cache/CacheJournal.java | 10 +++--- .../gianlu/librespot/cache/CacheManager.java | 6 ++-- .../gianlu/librespot/common/ProtoUtils.java | 36 ++++++++++++------- .../xyz/gianlu/librespot/core/Session.java | 3 -- .../gianlu/librespot/core/TokenProvider.java | 2 +- .../gianlu/librespot/metadata/PlayableId.java | 8 ++--- player/pom.xml | 2 +- .../xyz/gianlu/librespot/player/Player.java | 2 +- .../librespot/player/codecs/VorbisCodec.java | 2 +- 14 files changed, 45 insertions(+), 46 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index e9fab148..01bcb018 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -6,7 +6,7 @@ xyz.gianlu.librespot librespot-java 1.5.3-SNAPSHOT - ../ + ../pom.xml librespot-api diff --git a/api/src/main/java/xyz/gianlu/librespot/api/Utils.java b/api/src/main/java/xyz/gianlu/librespot/api/Utils.java index e5a4ae67..c3f005ba 100644 --- a/api/src/main/java/xyz/gianlu/librespot/api/Utils.java +++ b/api/src/main/java/xyz/gianlu/librespot/api/Utils.java @@ -30,7 +30,7 @@ public static Map> readParameters(@NotNull HttpServerExcha byte[] buffer = new byte[1024]; int count; while ((count = in.read(buffer)) > 0) out.write(buffer, 0, count); - body = new String(out.toByteArray()); + body = out.toString(); } return QueryParameterUtils.mergeQueryParametersWithNewQueryString(map, body, "UTF-8"); diff --git a/api/src/main/java/xyz/gianlu/librespot/api/handlers/PlayerHandler.java b/api/src/main/java/xyz/gianlu/librespot/api/handlers/PlayerHandler.java index edbb682d..6a08cbd3 100644 --- a/api/src/main/java/xyz/gianlu/librespot/api/handlers/PlayerHandler.java +++ b/api/src/main/java/xyz/gianlu/librespot/api/handlers/PlayerHandler.java @@ -54,17 +54,11 @@ private static void setVolume(HttpServerExchange exchange, @NotNull Player playe return; } - if (val > 0) { - player.volumeUp(val); - } else if (val < 0) { - player.volumeDown(Math.abs(val)); - } else { - Utils.invalidParameter(exchange, "step", "Must be non zero"); - return; - } + if (val > 0) player.volumeUp(val); + else if (val < 0) player.volumeDown(Math.abs(val)); + else Utils.invalidParameter(exchange, "step", "Must be non zero"); } else { Utils.invalidParameter(exchange, "volume"); - return; } } diff --git a/lib/pom.xml b/lib/pom.xml index 552e98eb..31780880 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -6,7 +6,7 @@ xyz.gianlu.librespot librespot-java 1.5.3-SNAPSHOT - ../ + ../pom.xml librespot-lib diff --git a/lib/src/main/java/xyz/gianlu/librespot/audio/decrypt/AesAudioDecrypt.java b/lib/src/main/java/xyz/gianlu/librespot/audio/decrypt/AesAudioDecrypt.java index d88094c7..af3ff3f5 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/audio/decrypt/AesAudioDecrypt.java +++ b/lib/src/main/java/xyz/gianlu/librespot/audio/decrypt/AesAudioDecrypt.java @@ -37,7 +37,7 @@ public AesAudioDecrypt(byte[] key) { @Override public synchronized void decryptChunk(int chunkIndex, @NotNull byte[] buffer) throws IOException { - BigInteger iv = IV_INT.add(BigInteger.valueOf(CHUNK_SIZE * chunkIndex / 16)); + BigInteger iv = IV_INT.add(BigInteger.valueOf((long) CHUNK_SIZE * chunkIndex / 16)); try { long start = System.nanoTime(); for (int i = 0; i < buffer.length; i += 4096) { diff --git a/lib/src/main/java/xyz/gianlu/librespot/cache/CacheJournal.java b/lib/src/main/java/xyz/gianlu/librespot/cache/CacheJournal.java index 87cf8a09..574c9bb5 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/cache/CacheJournal.java +++ b/lib/src/main/java/xyz/gianlu/librespot/cache/CacheJournal.java @@ -138,7 +138,7 @@ List getEntries() throws IOException { int i = 0; while (true) { - io.seek(i * JOURNAL_ENTRY_SIZE); + io.seek((long) i * JOURNAL_ENTRY_SIZE); int first = io.read(); if (first == -1) // EOF @@ -178,7 +178,7 @@ private Entry find(@NotNull String id) throws IOException { int i = 0; while (true) { - io.seek(i * JOURNAL_ENTRY_SIZE); + io.seek((long) i * JOURNAL_ENTRY_SIZE); int first = io.read(); if (first == -1) // EOF @@ -208,7 +208,7 @@ void createIfNeeded(@NotNull String id) throws IOException { int i = 0; while (true) { - io.seek(i * JOURNAL_ENTRY_SIZE); + io.seek((long) i * JOURNAL_ENTRY_SIZE); int first = io.read(); if (first == 0 || first == -1) { // First empty spot or EOF @@ -280,7 +280,7 @@ void setHeader(int id, @NotNull String value) throws IOException { if (index == -1) throw new IllegalStateException(); } - io.seek(offset + MAX_ID_LENGTH + MAX_CHUNKS_SIZE + index * (MAX_HEADER_LENGTH + 1)); + io.seek(offset + MAX_ID_LENGTH + MAX_CHUNKS_SIZE + (long) index * (MAX_HEADER_LENGTH + 1)); io.write(id); io.write(value.getBytes(StandardCharsets.US_ASCII)); } @@ -308,7 +308,7 @@ JournalHeader getHeader(int id) throws IOException { int index = findHeader(id); if (index == -1) return null; - io.seek(offset + MAX_ID_LENGTH + MAX_CHUNKS_SIZE + index * (MAX_HEADER_LENGTH + 1) + 1); + io.seek(offset + MAX_ID_LENGTH + MAX_CHUNKS_SIZE + (long) index * (MAX_HEADER_LENGTH + 1) + 1); byte[] read = new byte[MAX_HEADER_LENGTH]; io.read(read); diff --git a/lib/src/main/java/xyz/gianlu/librespot/cache/CacheManager.java b/lib/src/main/java/xyz/gianlu/librespot/cache/CacheManager.java index fdf93e27..0d896310 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/cache/CacheManager.java +++ b/lib/src/main/java/xyz/gianlu/librespot/cache/CacheManager.java @@ -197,7 +197,7 @@ public boolean hasChunk(int index) throws IOException { updateTimestamp(); synchronized (io) { - if (io.length() < (index + 1) * CHUNK_SIZE) + if (io.length() < (long) (index + 1) * CHUNK_SIZE) return false; } @@ -219,7 +219,7 @@ public byte[] readChunk(int index) throws IOException, BadChunkHashException { updateTimestamp(); synchronized (io) { - io.seek(index * CHUNK_SIZE); + io.seek((long) index * CHUNK_SIZE); byte[] buffer = new byte[CHUNK_SIZE]; int read = io.read(buffer); @@ -248,7 +248,7 @@ public byte[] readChunk(int index) throws IOException, BadChunkHashException { public void writeChunk(byte[] buffer, int index) throws IOException { synchronized (io) { - io.seek(index * CHUNK_SIZE); + io.seek((long) index * CHUNK_SIZE); io.write(buffer); } diff --git a/lib/src/main/java/xyz/gianlu/librespot/common/ProtoUtils.java b/lib/src/main/java/xyz/gianlu/librespot/common/ProtoUtils.java index 653e36a1..87cdea10 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/common/ProtoUtils.java +++ b/lib/src/main/java/xyz/gianlu/librespot/common/ProtoUtils.java @@ -165,12 +165,12 @@ public static Player.PlayOrigin convertPlayOrigin(@Nullable PlayOrigin po) { Player.PlayOrigin.Builder builder = Player.PlayOrigin.newBuilder(); - Optional.ofNullable(po.getFeatureIdentifier()).ifPresent(builder::setFeatureIdentifier); - Optional.ofNullable(po.getFeatureVersion()).ifPresent(builder::setFeatureVersion); - Optional.ofNullable(po.getViewUri()).ifPresent(builder::setViewUri); - Optional.ofNullable(po.getExternalReferrer()).ifPresent(builder::setExternalReferrer); - Optional.ofNullable(po.getReferrerIdentifier()).ifPresent(builder::setReferrerIdentifier); - Optional.ofNullable(po.getDeviceIdentifier()).ifPresent(builder::setDeviceIdentifier); + if (po.hasFeatureIdentifier()) builder.setFeatureIdentifier(po.getFeatureIdentifier()); + if (po.hasFeatureVersion()) builder.setFeatureVersion(po.getFeatureVersion()); + if (po.hasViewUri()) builder.setViewUri(po.getViewUri()); + if (po.hasExternalReferrer()) builder.setExternalReferrer(po.getExternalReferrer()); + if (po.hasReferrerIdentifier()) builder.setReferrerIdentifier(po.getReferrerIdentifier()); + if (po.hasDeviceIdentifier()) builder.setDeviceIdentifier(po.getDeviceIdentifier()); if (po.getFeatureClassesCount() > 0) for (String feature : po.getFeatureClassesList()) @@ -254,9 +254,11 @@ public static int indexOfTrackByUri(@NotNull List tracks, @NotNull } public static boolean isQueued(@NotNull ContextTrack track) { - String value = track.getMetadataOrDefault("is_queued", null); - if (value == null) return false; - else return Boolean.parseBoolean(value); + try { + return Boolean.parseBoolean(track.getMetadataOrThrow("is_queued")); + } catch (IllegalArgumentException ex) { + return false; + } } public static void enrichTrack(@NotNull ContextTrack.Builder subject, @NotNull ContextTrack track) { @@ -283,10 +285,18 @@ public static Player.ProvidedTrack convertToProvidedTrack(@Nullable ContextTrack Player.ProvidedTrack.Builder builder = Player.ProvidedTrack.newBuilder(); builder.setProvider("context"); - Optional.ofNullable(track.getUri()).ifPresent(builder::setUri); - Optional.ofNullable(track.getUid()).ifPresent(builder::setUid); - Optional.ofNullable(track.getMetadataOrDefault("album_uri", null)).ifPresent(builder::setAlbumUri); - Optional.ofNullable(track.getMetadataOrDefault("artist_uri", null)).ifPresent(builder::setArtistUri); + if (track.hasUri()) builder.setUri(track.getUri()); + if (track.hasUid()) builder.setUid(track.getUid()); + + try { + builder.setAlbumUri(track.getMetadataOrThrow("album_uri")); + } catch (IllegalArgumentException ignored) { + } + + try { + builder.setArtistUri(track.getMetadataOrThrow("artist_uri")); + } catch (IllegalArgumentException ignored) { + } builder.putAllMetadata(track.getMetadataMap()); diff --git a/lib/src/main/java/xyz/gianlu/librespot/core/Session.java b/lib/src/main/java/xyz/gianlu/librespot/core/Session.java index 78d30d55..fe8bc9a3 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/core/Session.java +++ b/lib/src/main/java/xyz/gianlu/librespot/core/Session.java @@ -86,7 +86,6 @@ public final class Session implements Closeable, SubListener, DealerClient.Messa private final DiffieHellman keys; private final Inner inner; private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new NameThreadFactory(r -> "session-scheduler-" + r.hashCode())); - private final ExecutorService executorService = Executors.newCachedThreadPool(new NameThreadFactory(r -> "handle-packet-" + r.hashCode())); private final AtomicBoolean authLock = new AtomicBoolean(false); private final OkHttpClient client; private final List closeListeners = Collections.synchronizedList(new ArrayList<>()); @@ -450,8 +449,6 @@ public void close() throws IOException { receiver = null; } - executorService.shutdown(); - client.dispatcher().executorService().shutdownNow(); client.connectionPool().evictAll(); diff --git a/lib/src/main/java/xyz/gianlu/librespot/core/TokenProvider.java b/lib/src/main/java/xyz/gianlu/librespot/core/TokenProvider.java index f3774c48..ad426b78 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/core/TokenProvider.java +++ b/lib/src/main/java/xyz/gianlu/librespot/core/TokenProvider.java @@ -81,7 +81,7 @@ private StoredToken(@NotNull JsonObject obj) { } public boolean expired() { - return timestamp + (expiresIn - TOKEN_EXPIRE_THRESHOLD) * 1000 < TimeProvider.currentTimeMillis(); + return timestamp + (expiresIn - TOKEN_EXPIRE_THRESHOLD) * 1000L < TimeProvider.currentTimeMillis(); } @Override diff --git a/lib/src/main/java/xyz/gianlu/librespot/metadata/PlayableId.java b/lib/src/main/java/xyz/gianlu/librespot/metadata/PlayableId.java index 521372ab..791059f1 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/metadata/PlayableId.java +++ b/lib/src/main/java/xyz/gianlu/librespot/metadata/PlayableId.java @@ -61,8 +61,7 @@ static boolean isSupported(@NotNull String uri) { } static boolean shouldPlay(@NotNull ContextTrack track) { - String forceRemoveReasons = track.getMetadataOrDefault("force_remove_reasons", null); - return forceRemoveReasons == null || forceRemoveReasons.isEmpty(); + return track.getMetadataOrDefault("force_remove_reasons", "").isEmpty(); } @NotNull @@ -92,9 +91,8 @@ static PlayableId from(@NotNull Metadata.Episode episode) { @NotNull String toSpotifyUri(); default boolean matches(@NotNull ContextTrack current) { - String uri = current.getUri(); - if (uri != null && !uri.isEmpty()) return toSpotifyUri().equals(uri); - else if (current.getGid() != null) return Arrays.equals(current.getGid().toByteArray(), getGid()); + if (current.hasUri()) return toSpotifyUri().equals(current.getUri()); + else if (current.hasGid()) return Arrays.equals(current.getGid().toByteArray(), getGid()); else return false; } } diff --git a/player/pom.xml b/player/pom.xml index bc822e6b..cfef0a53 100644 --- a/player/pom.xml +++ b/player/pom.xml @@ -6,7 +6,7 @@ xyz.gianlu.librespot librespot-java 1.5.3-SNAPSHOT - ../ + ../pom.xml librespot-player diff --git a/player/src/main/java/xyz/gianlu/librespot/player/Player.java b/player/src/main/java/xyz/gianlu/librespot/player/Player.java index 026fb7e3..9ce1aaea 100644 --- a/player/src/main/java/xyz/gianlu/librespot/player/Player.java +++ b/player/src/main/java/xyz/gianlu/librespot/player/Player.java @@ -177,7 +177,7 @@ public void ready() { } @Override - public void command(DeviceStateHandler.@NotNull Endpoint endpoint, DeviceStateHandler.@NotNull CommandBody data) throws InvalidProtocolBufferException { + public void command(DeviceStateHandler.@NotNull Endpoint endpoint, DeviceStateHandler.@NotNull CommandBody data) { } @Override diff --git a/player/src/main/java/xyz/gianlu/librespot/player/codecs/VorbisCodec.java b/player/src/main/java/xyz/gianlu/librespot/player/codecs/VorbisCodec.java index a9575af4..113a0894 100644 --- a/player/src/main/java/xyz/gianlu/librespot/player/codecs/VorbisCodec.java +++ b/player/src/main/java/xyz/gianlu/librespot/player/codecs/VorbisCodec.java @@ -207,7 +207,7 @@ private int decodeCurrentPacket(@NotNull OutputStream out) throws IOException { long granulepos = joggPacket.granulepos; if (granulepos != -1 && joggPacket.e_o_s == 0) { granulepos -= samples; - granulepos -= BUFFER_SIZE * 6 * sampleSizeBytes(); // Account for buffer between the decoder and the player + granulepos -= (long) BUFFER_SIZE * 6 * sampleSizeBytes(); // Account for buffer between the decoder and the player pcm_offset = granulepos; } }