Skip to content

Commit 2a996af

Browse files
committed
Added /discovery/list API endpoint (#352)
1 parent 0a8e685 commit 2a996af

File tree

6 files changed

+91
-2
lines changed

6 files changed

+91
-2
lines changed

api/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ All the endpoints will respond with `200` if successful or:
4545
- `POST /instance/terminate` Terminates the API server.
4646
- `POST /instance/close` Closes the current session (and player).
4747

48+
### Discovery (Spotify Connect)
49+
- `POST /discovery/list` List all Spotify Connect devices on the network.
50+
51+
4852
### Events
4953
You can subscribe for players events by creating a WebSocket connection to `/events`.
5054
The currently available events are:

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public ApiServer(int port, @NotNull String host, @NotNull SessionWrapper wrapper
4646
.post("/profile/{user_id}/{action}", new ProfileHandler(wrapper))
4747
.post("/web-api/{endpoint}", new WebApiHandler(wrapper))
4848
.post("/instance/{action}", InstanceHandler.forSession(this, wrapper))
49+
.post("/discovery/{action}", new DiscoveryHandler())
4950
.get("/events", events)
5051
.setFallbackHandler(new PathHandler(ResponseCodeHandler.HANDLE_404)
5152
.addPrefixPath("/web-api", new WebApiHandler(wrapper)));
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2021 devgianlu
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package xyz.gianlu.librespot.api.handlers;
18+
19+
import com.google.gson.JsonArray;
20+
import com.google.gson.JsonObject;
21+
import io.undertow.server.HttpHandler;
22+
import io.undertow.server.HttpServerExchange;
23+
import io.undertow.util.Headers;
24+
import xyz.gianlu.librespot.ZeroconfServer;
25+
import xyz.gianlu.librespot.api.Utils;
26+
import xyz.gianlu.zeroconf.DiscoveredService;
27+
import xyz.gianlu.zeroconf.Zeroconf;
28+
29+
import java.util.Deque;
30+
import java.util.Map;
31+
32+
/**
33+
* @author devgianlu
34+
*/
35+
public final class DiscoveryHandler implements HttpHandler {
36+
private final Zeroconf zeroconf;
37+
38+
public DiscoveryHandler() {
39+
zeroconf = new Zeroconf();
40+
}
41+
42+
@Override
43+
public void handleRequest(HttpServerExchange exchange) throws Exception {
44+
exchange.startBlocking();
45+
if (exchange.isInIoThread()) {
46+
exchange.dispatch(this);
47+
return;
48+
}
49+
50+
Map<String, Deque<String>> params = Utils.readParameters(exchange);
51+
String action = Utils.getFirstString(params, "action");
52+
if (action == null) {
53+
Utils.invalidParameter(exchange, "action");
54+
return;
55+
}
56+
57+
switch (action) {
58+
case "list":
59+
JsonArray array = new JsonArray();
60+
for (DiscoveredService service : zeroconf.discover(ZeroconfServer.SERVICE, "tcp", ".local")) {
61+
JsonObject obj = new JsonObject();
62+
obj.addProperty("name", service.name);
63+
obj.addProperty("target", service.target);
64+
obj.addProperty("port", service.port);
65+
array.add(obj);
66+
}
67+
68+
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json");
69+
exchange.getResponseSender().send(array.toString());
70+
break;
71+
default:
72+
Utils.invalidParameter(exchange, "action");
73+
break;
74+
}
75+
}
76+
}

lib/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
<dependency>
117117
<groupId>xyz.gianlu.zeroconf</groupId>
118118
<artifactId>zeroconf</artifactId>
119-
<version>1.1.3</version>
119+
<version>1.2.1</version>
120120
</dependency>
121121

122122
<!-- HTTP -->

lib/src/main/java/xyz/gianlu/librespot/ZeroconfServer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
* @author Gianlu
5555
*/
5656
public class ZeroconfServer implements Closeable {
57+
public static final String SERVICE = "spotify-connect";
5758
private final static int MAX_PORT = 65536;
5859
private final static int MIN_PORT = 1024;
5960
private static final Logger LOGGER = LoggerFactory.getLogger(ZeroconfServer.class);
@@ -154,7 +155,7 @@ private ZeroconfServer(@NotNull Inner inner, int listenPort, boolean listenAllIn
154155
txt.put("CPath", "/");
155156
txt.put("VERSION", "1.0");
156157
txt.put("Stack", "SP");
157-
Service service = new Service(inner.deviceName, "spotify-connect", listenPort);
158+
Service service = new Service(inner.deviceName, SERVICE, listenPort);
158159
service.setText(txt);
159160

160161
zeroconf.announce(service);

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@
4949
<url>https://github.com/librespot-org/librespot-java/</url>
5050
</scm>
5151

52+
<repositories>
53+
<repository>
54+
<id>github</id>
55+
<url>https://maven.pkg.github.com/devgianlu/*</url>
56+
</repository>
57+
</repositories>
58+
5259
<properties>
5360
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
5461
<maven.compiler.source>1.8</maven.compiler.source>

0 commit comments

Comments
 (0)