Skip to content

Commit c4f9e9e

Browse files
authored
Merge pull request #105 from librespot-org/new-spotify-api
Updating to the newest Spotify API
2 parents 002a772 + 1963f70 commit c4f9e9e

170 files changed

Lines changed: 53761 additions & 166897 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.travis.yml

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
11
language: java
22

33
before_install:
4-
- |
5-
if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
6-
echo $GPG_SECRET_KEYS | base64 --decode | $GPG_EXECUTABLE --import
7-
echo $GPG_OWNERTRUST | base64 --decode | $GPG_EXECUTABLE --import-ownertrust
8-
fi
4+
- chmod +x .travis/*.sh
5+
- .travis/load_gpg.sh
96

107
install:
118
- mvn clean install -DskipTests=true -Dgpg.skip -Dmaven.javadoc.skip=true -B -V
129

1310
script:
14-
- |
15-
if [[ -z "${TRAVIS_TAG}" ]]; then
16-
mvn deploy -Dmaven.deploy.skip=true -B -U -Pdebug
17-
else
18-
mvn deploy --settings .maven.xml -B -U -Prelease
19-
fi
11+
- .travis/script.sh
2012

2113
before_deploy:
2214
- mvn help:evaluate -N -Dexpression=project.version|grep -v '\['

.travis/load_gpg.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env bash
2+
set -ev
3+
4+
if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
5+
echo $GPG_SECRET_KEYS | base64 --decode | $GPG_EXECUTABLE --import
6+
echo $GPG_OWNERTRUST | base64 --decode | $GPG_EXECUTABLE --import-ownertrust
7+
fi

.travis/script.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
set -ev
3+
4+
if [[ -z "${TRAVIS_TAG}" ]]; then
5+
mvn deploy -Dmaven.deploy.skip=true -B -U -Pdebug
6+
else
7+
mvn deploy --settings .maven.xml -B -U -Prelease
8+
fi

LICENSE

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -199,31 +199,3 @@
199199
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200200
See the License for the specific language governing permissions and
201201
limitations under the License.
202-
203-
204-
205-
===============
206-
MP3 decoder
207-
===============
208-
209-
MIT License
210-
211-
Copyright (c) 2017 delthas
212-
213-
Permission is hereby granted, free of charge, to any person obtaining a copy
214-
of this software and associated documentation files (the "Software"), to deal
215-
in the Software without restriction, including without limitation the rights
216-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
217-
copies of the Software, and to permit persons to whom the Software is
218-
furnished to do so, subject to the following conditions:
219-
220-
The above copyright notice and this permission notice shall be included in all
221-
copies or substantial portions of the Software.
222-
223-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
224-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
225-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
226-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
227-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
228-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
229-
SOFTWARE.

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
[![Build Status](https://travis-ci.com/librespot-org/librespot-java.svg?branch=master)](https://travis-ci.com/librespot-org/librespot-java)
33
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/1ec8ca04e5054558a089bc7f640079a6)](https://www.codacy.com/manual/devgianlu/librespot-java?utm_source=github.com&utm_medium=referral&utm_content=librespot-org/librespot-java&utm_campaign=Badge_Grade)
44
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/xyz.gianlu.librespot/librespot-java/badge.svg)](https://maven-badges.herokuapp.com/maven-central/xyz.gianlu.librespot/librespot-java)
5+
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/1ec8ca04e5054558a089bc7f640079a6)](https://www.codacy.com/app/devgianlu/librespot-java?utm_source=github.com&utm_medium=referral&utm_content=librespot-org/librespot-java&utm_campaign=Badge_Grade)
56

67
`librespot-java` is a port of [librespot](https://github.com/librespot-org/librespot), originally written in Rust, which as evolved into the most up-to-date open-source Spotify client. Additionally, this implementation provides an useful API to request metadata or control the player, more [here](https://github.com/librespot-org/librespot-java/blob/master/api).
78

@@ -18,6 +19,7 @@ Its main features are:
1819
- Local content caching
1920
- Zeroconf (Spotify Connect)
2021
- Gapless playback
22+
- Mixed playlists (cuepoints and transitions)
2123

2224
## Get started
2325
All the configuration you need is inside the `config.toml` file, there you can decide to authenticate with:
@@ -58,5 +60,5 @@ To run the newly build jar run `java -jar ./core/target/librespot-core-jar-with-
5860
# Special thanks
5961

6062
- All the developers of [librespot](https://github.com/librespot-org/librespot) which started this project in Rust
61-
- All the contributors of this project for testing and fixing stuff
63+
- All the contributors of this project for testing and fixing stuff, especially [@loeffelpan](https://github.com/loeffelpan), [@crsmoro](https://github.com/crsmoro) and [@Schluggi](https://github.com/Schluggi) for the feedback provided
6264
- <a href="https://www.yourkit.com/"><img src="https://www.yourkit.com/images/yklogo.png" height="20"></a> that provided a free license for their [Java Profiler](https://www.yourkit.com/java/profiler/)

api-client/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
<configuration>
2929
<archive>
3030
<manifest>
31+
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
32+
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
3133
<mainClass>xyz.gianlu.librespot.api.client.Main</mainClass>
3234
</manifest>
3335
</archive>

api/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
<configuration>
2929
<archive>
3030
<manifest>
31+
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
32+
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
3133
<mainClass>xyz.gianlu.librespot.api.Main</mainClass>
3234
</manifest>
3335
</archive>

api/src/main/java/xyz/gianlu/librespot/api/Main.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import xyz.gianlu.librespot.core.AuthConfiguration;
88
import xyz.gianlu.librespot.core.Session;
99
import xyz.gianlu.librespot.core.ZeroconfServer;
10-
import xyz.gianlu.librespot.spirc.SpotifyIrc;
10+
import xyz.gianlu.librespot.mercury.MercuryClient;
1111

1212
import java.io.IOException;
1313
import java.security.GeneralSecurityException;
@@ -17,7 +17,7 @@
1717
*/
1818
public class Main {
1919

20-
public static void main(String[] args) throws IOException, GeneralSecurityException, SpotifyIrc.IrcException, Session.SpotifyAuthenticationException {
20+
public static void main(String[] args) throws IOException, GeneralSecurityException, Session.SpotifyAuthenticationException, MercuryClient.MercuryException {
2121
AbsConfiguration conf = new FileConfiguration(args);
2222
if (conf.authStrategy() == AuthConfiguration.Strategy.ZEROCONF) {
2323
ZeroconfServer.create(conf).addSessionListener(new ZeroconfApiServer(24879));

api/src/main/java/xyz/gianlu/librespot/api/MercuryHandler.java

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.jetbrains.annotations.NotNull;
77
import xyz.gianlu.librespot.api.server.AbsApiHandler;
88
import xyz.gianlu.librespot.api.server.ApiServer;
9+
import xyz.gianlu.librespot.api.server.ApiServer.PredefinedJsonRpcException;
910
import xyz.gianlu.librespot.core.Session;
1011
import xyz.gianlu.librespot.mercury.MercuryClient;
1112
import xyz.gianlu.librespot.mercury.RawMercuryRequest;
@@ -17,47 +18,49 @@
1718
* @author Gianlu
1819
*/
1920
public class MercuryHandler extends AbsApiHandler {
20-
private final MercuryClient client;
21+
private final Session session;
2122

2223
public MercuryHandler(@NotNull Session session) {
2324
super("mercury");
24-
this.client = session.mercury();
25+
this.session = session;
2526
}
2627

2728
@Override
28-
protected @NotNull JsonElement handleRequest(ApiServer.@NotNull Request request) throws HandlingException, ApiServer.PredefinedJsonRpcException {
29-
if (request.getSuffix().equals("request")) {
30-
JsonObject params = request.params.getAsJsonObject();
29+
protected @NotNull JsonElement handleRequest(ApiServer.@NotNull Request request) throws HandlingException, PredefinedJsonRpcException {
30+
if (!request.getSuffix().equals("request"))
31+
throw PredefinedJsonRpcException.from(request, ApiServer.PredefinedJsonRpcError.METHOD_NOT_FOUND);
3132

32-
RawMercuryRequest.Builder builder = RawMercuryRequest.newBuilder()
33-
.setMethod(params.get("method").getAsString())
34-
.setUri(params.get("uri").getAsString());
33+
if (request.params == null || !request.params.isJsonArray())
34+
throw PredefinedJsonRpcException.from(request, ApiServer.PredefinedJsonRpcError.INVALID_PARAMS);
3535

36-
if (params.has("headers")) {
37-
JsonArray headers = params.getAsJsonArray("headers");
38-
for (JsonElement element : headers) {
39-
JsonObject header = element.getAsJsonObject();
40-
builder.addUserField(header.get("key").getAsString(), header.get("value").getAsString());
41-
}
36+
JsonObject params = request.params.getAsJsonObject();
37+
38+
RawMercuryRequest.Builder builder = RawMercuryRequest.newBuilder()
39+
.setMethod(params.get("method").getAsString())
40+
.setUri(params.get("uri").getAsString());
41+
42+
if (params.has("headers")) {
43+
JsonArray headers = params.getAsJsonArray("headers");
44+
for (JsonElement element : headers) {
45+
JsonObject header = element.getAsJsonObject();
46+
builder.addUserField(header.get("key").getAsString(), header.get("value").getAsString());
4247
}
48+
}
4349

44-
try {
45-
MercuryClient.Response response = client.sendSync(builder.build());
50+
try {
51+
MercuryClient.Response response = session.mercury().sendSync(builder.build());
4652

47-
JsonArray payloads = new JsonArray(response.payload.size());
48-
for (byte[] bytes : response.payload)
49-
payloads.add(Base64.getEncoder().encodeToString(bytes));
53+
JsonArray payloads = new JsonArray(response.payload.size());
54+
for (byte[] bytes : response.payload)
55+
payloads.add(Base64.getEncoder().encodeToString(bytes));
5056

51-
JsonObject obj = new JsonObject();
52-
obj.addProperty("code", response.statusCode);
53-
obj.addProperty("uri", response.uri);
54-
obj.add("payloads", payloads);
55-
return obj;
56-
} catch (IOException ex) {
57-
throw new HandlingException(ex, ErrorCode.IO_EXCEPTION);
58-
}
59-
} else {
60-
throw ApiServer.PredefinedJsonRpcException.from(request, ApiServer.PredefinedJsonRpcError.METHOD_NOT_FOUND);
57+
JsonObject obj = new JsonObject();
58+
obj.addProperty("code", response.statusCode);
59+
obj.addProperty("uri", response.uri);
60+
obj.add("payloads", payloads);
61+
return obj;
62+
} catch (IOException ex) {
63+
throw new HandlingException(ex, ErrorCode.IO_EXCEPTION);
6164
}
6265
}
6366

api/src/main/java/xyz/gianlu/librespot/api/MetadataHandler.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import org.jetbrains.annotations.NotNull;
66
import xyz.gianlu.librespot.api.server.AbsApiHandler;
77
import xyz.gianlu.librespot.api.server.ApiServer;
8+
import xyz.gianlu.librespot.api.server.ApiServer.PredefinedJsonRpcError;
9+
import xyz.gianlu.librespot.api.server.ApiServer.PredefinedJsonRpcException;
810
import xyz.gianlu.librespot.core.Session;
911
import xyz.gianlu.librespot.mercury.MercuryClient;
1012
import xyz.gianlu.librespot.mercury.MercuryRequests;
@@ -17,20 +19,18 @@
1719
* @author Gianlu
1820
*/
1921
public class MetadataHandler extends AbsApiHandler {
20-
private final MercuryClient client;
2122
private final Session session;
2223

2324
public MetadataHandler(@NotNull Session session) {
2425
super("metadata");
2526
this.session = session;
26-
this.client = session.mercury();
2727
}
2828

2929
@Override
30-
protected @NotNull JsonElement handleRequest(ApiServer.@NotNull Request request) throws ApiServer.PredefinedJsonRpcException, HandlingException {
30+
protected @NotNull JsonElement handleRequest(ApiServer.@NotNull Request request) throws PredefinedJsonRpcException, HandlingException {
3131
switch (request.getSuffix()) {
3232
case "rootlists":
33-
return handle(MercuryRequests.getRootPlaylists(session.apWelcome().getCanonicalUsername()));
33+
return handle(MercuryRequests.getRootPlaylists(session.username()));
3434
case "playlist":
3535
return handle(MercuryRequests.getPlaylist(ApiUtils.extractId(PlaylistId.class, request, request.params)));
3636
case "track":
@@ -42,14 +42,14 @@ public MetadataHandler(@NotNull Session session) {
4242
case "episode":
4343
return handle(MercuryRequests.getEpisode(ApiUtils.extractId(EpisodeId.class, request, request.params)));
4444
default:
45-
throw ApiServer.PredefinedJsonRpcException.from(request, ApiServer.PredefinedJsonRpcError.METHOD_NOT_FOUND);
45+
throw PredefinedJsonRpcException.from(request, PredefinedJsonRpcError.METHOD_NOT_FOUND);
4646
}
4747
}
4848

4949
@NotNull
5050
private <P extends Message> JsonElement handle(@NotNull ProtobufMercuryRequest<P> req) throws HandlingException {
5151
try {
52-
return client.sendSync(req).json();
52+
return session.mercury().sendSync(req).json();
5353
} catch (MercuryClient.MercuryException ex) {
5454
throw new HandlingException(ex, ErrorCode.MERCURY_EXCEPTION);
5555
} catch (IOException ex) {

0 commit comments

Comments
 (0)