Skip to content

Commit 26818c6

Browse files
committed
Infer track URI from context
1 parent e70fb43 commit 26818c6

File tree

6 files changed

+42
-12
lines changed

6 files changed

+42
-12
lines changed

lib/src/main/java/xyz/gianlu/librespot/common/ProtoUtils.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import com.spotify.context.ContextPlayerOptionsOuterClass;
1313
import com.spotify.metadata.Metadata;
1414
import com.spotify.playlist4.Playlist4ApiProto;
15+
import org.apache.logging.log4j.LogManager;
16+
import org.apache.logging.log4j.Logger;
1517
import org.jetbrains.annotations.Contract;
1618
import org.jetbrains.annotations.NotNull;
1719
import org.jetbrains.annotations.Nullable;
@@ -28,6 +30,8 @@
2830
* @author Gianlu
2931
*/
3032
public final class ProtoUtils {
33+
private static final Logger LOGGER = LogManager.getLogger(ProtoUtils.class);
34+
3135
private ProtoUtils() {
3236
}
3337

@@ -61,11 +65,15 @@ private static JsonObject trackToJson(@NotNull Player.ProvidedTrack track) {
6165
}
6266

6367
@NotNull
64-
private static JsonObject trackToJson(@NotNull ContextTrack track) {
68+
private static JsonObject trackToJson(@NotNull ContextTrack track, String uriPrefix) {
6569
JsonObject obj = new JsonObject();
66-
if (track.hasUri() && !track.getUri().isEmpty()) obj.addProperty("uri", track.getUri());
6770
if (track.hasUid()) obj.addProperty("uid", track.getUid());
6871
obj.add("metadata", mapToJson(track.getMetadataMap()));
72+
if (track.hasUri() && !track.getUri().isEmpty())
73+
obj.addProperty("uri", track.getUri());
74+
else if (track.hasGid() && uriPrefix != null)
75+
obj.addProperty("uri", uriPrefix + new String(PlayableId.BASE62.encode(track.getGid().toByteArray(), 22)));
76+
6977
return obj;
7078
}
7179

@@ -83,7 +91,7 @@ public static JsonObject craftContextStateCombo(@NotNull Player.PlayerStateOrBui
8391
page.addProperty("page_url", "");
8492
page.addProperty("next_page_url", "");
8593
JsonArray tracksJson = new JsonArray(tracks.size());
86-
for (ContextTrack t : tracks) tracksJson.add(trackToJson(t));
94+
for (ContextTrack t : tracks) tracksJson.add(trackToJson(t, PlayableId.inferUriPrefix(ps.getContextUri())));
8795
page.add("tracks", tracksJson);
8896
page.add("metadata", mapToJson(ps.getPageMetadataMap()));
8997
pages.add(page);

lib/src/main/java/xyz/gianlu/librespot/metadata/EpisodeId.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package xyz.gianlu.librespot.metadata;
22

33
import org.jetbrains.annotations.NotNull;
4-
import xyz.gianlu.librespot.common.Base62;
54
import xyz.gianlu.librespot.common.Utils;
65

76
import java.util.regex.Matcher;
@@ -12,7 +11,6 @@
1211
*/
1312
public final class EpisodeId implements SpotifyId, PlayableId {
1413
static final Pattern PATTERN = Pattern.compile("spotify:episode:(.{22})");
15-
private static final Base62 BASE62 = Base62.createInstanceWithInvertedCharacterSet();
1614
private final String hexId;
1715

1816
private EpisodeId(@NotNull String hex) {

lib/src/main/java/xyz/gianlu/librespot/metadata/PlayableId.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.spotify.metadata.Metadata;
66
import org.jetbrains.annotations.NotNull;
77
import org.jetbrains.annotations.Nullable;
8+
import xyz.gianlu.librespot.common.Base62;
89
import xyz.gianlu.librespot.common.Utils;
910

1011
import java.util.Arrays;
@@ -17,6 +18,8 @@
1718
* @author Gianlu
1819
*/
1920
public interface PlayableId {
21+
Base62 BASE62 = Base62.createInstanceWithInvertedCharacterSet();
22+
2023
@NotNull
2124
static PlayableId fromUri(@NotNull String uri) {
2225
if (!isSupported(uri)) return new UnsupportedId(uri);
@@ -80,6 +83,14 @@ static PlayableId from(@NotNull Metadata.Episode episode) {
8083
return EpisodeId.fromHex(Utils.bytesToHex(episode.getGid()));
8184
}
8285

86+
@NotNull
87+
static String inferUriPrefix(@NotNull String contextUri) {
88+
if (contextUri.startsWith("spotify:episode:") || contextUri.startsWith("spotify:show:"))
89+
return "spotify:episode:";
90+
else
91+
return "spotify:track:";
92+
}
93+
8394
@NotNull
8495
String toString();
8596

lib/src/main/java/xyz/gianlu/librespot/metadata/TrackId.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package xyz.gianlu.librespot.metadata;
22

33
import org.jetbrains.annotations.NotNull;
4-
import xyz.gianlu.librespot.common.Base62;
54
import xyz.gianlu.librespot.common.Utils;
65

76
import java.util.regex.Matcher;
@@ -12,7 +11,6 @@
1211
*/
1312
public final class TrackId implements SpotifyId, PlayableId {
1413
static final Pattern PATTERN = Pattern.compile("spotify:track:(.{22})");
15-
private static final Base62 BASE62 = Base62.createInstanceWithInvertedCharacterSet();
1614
private final String hexId;
1715

1816
private TrackId(@NotNull String hex) {

player/src/main/java/xyz/gianlu/librespot/player/PagesLoader.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import xyz.gianlu.librespot.mercury.MercuryClient;
1111
import xyz.gianlu.librespot.mercury.MercuryRequests;
1212
import xyz.gianlu.librespot.mercury.RawMercuryRequest;
13+
import xyz.gianlu.librespot.metadata.PlayableId;
1314

1415
import java.io.IOException;
1516
import java.io.InputStreamReader;
@@ -46,10 +47,20 @@ public static PagesLoader from(@NotNull Session session, @NotNull Context contex
4647
if (pages.isEmpty()) return from(session, context.getUri());
4748

4849
PagesLoader loader = new PagesLoader(session);
49-
loader.pages.addAll(pages);
50+
loader.putFirstPages(pages, PlayableId.inferUriPrefix(context.getUri()));
5051
return loader;
5152
}
5253

54+
private static void sanitizeTracks(List<ContextTrack> tracks, String uriPrefix) {
55+
for (int i = 0; i < tracks.size(); i++) {
56+
ContextTrack.Builder builder = tracks.get(i).toBuilder();
57+
if (builder.hasUri() || !builder.hasGid()) continue;
58+
59+
builder.setUri(uriPrefix + new String(PlayableId.BASE62.encode(builder.getGid().toByteArray(), 22)));
60+
tracks.set(i, builder.build());
61+
}
62+
}
63+
5364
@NotNull
5465
private List<ContextTrack> fetchTracks(@NotNull String url) throws IOException {
5566
MercuryClient.Response resp = session.mercury().sendSync(RawMercuryRequest.newBuilder()
@@ -123,13 +134,17 @@ boolean nextPage() throws IOException, MercuryClient.MercuryException {
123134
}
124135
}
125136

126-
void putFirstPages(@NotNull List<ContextPage> pages) {
137+
void putFirstPages(@NotNull List<ContextPage> pages, String contextUri) {
127138
if (currentPage != -1 || !this.pages.isEmpty()) throw new IllegalStateException();
128-
this.pages.addAll(pages);
139+
for (ContextPage page : pages) {
140+
sanitizeTracks(page.getTracksList(), contextUri == null ? null : PlayableId.inferUriPrefix(contextUri));
141+
this.pages.add(page);
142+
}
129143
}
130144

131-
void putFirstPage(@NotNull List<ContextTrack> tracks) {
145+
void putFirstPage(@NotNull List<ContextTrack> tracks, String contextUri) {
132146
if (currentPage != -1 || !pages.isEmpty()) throw new IllegalStateException();
147+
sanitizeTracks(tracks, contextUri == null ? null : PlayableId.inferUriPrefix(contextUri));
133148
pages.add(ContextPage.newBuilder().addAllTracks(tracks).build());
134149
}
135150
}

player/src/main/java/xyz/gianlu/librespot/player/StateWrapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ String loadContextWithTracks(@NotNull String uri, @NotNull List<ContextTrack> tr
442442
state.setOptions(ContextPlayerOptions.newBuilder().build());
443443

444444
String sessionId = setContext(uri);
445-
pages.putFirstPage(tracks);
445+
pages.putFirstPage(tracks, uri);
446446
tracksKeeper.initializeStart();
447447
setPosition(0);
448448

0 commit comments

Comments
 (0)