Skip to content

Commit 95b4dc2

Browse files
committed
Improve unanalyzed track handling.
1 parent 328bafb commit 95b4dc2

File tree

2 files changed

+64
-9
lines changed

2 files changed

+64
-9
lines changed

src/main/java/org/deepsymmetry/beatlink/DeviceFinder.java

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.net.*;
1010
import java.util.*;
1111
import java.util.concurrent.ConcurrentHashMap;
12+
import java.util.concurrent.atomic.AtomicBoolean;
1213
import java.util.concurrent.atomic.AtomicLong;
1314
import java.util.concurrent.atomic.AtomicReference;
1415

@@ -53,6 +54,12 @@ public class DeviceFinder extends LifecycleParticipant {
5354
*/
5455
private static final AtomicLong firstDeviceTime = new AtomicLong(0);
5556

57+
/**
58+
* Indicates whether we have seen any players older than a CDJ-3000, which are unable to respond to
59+
* metadata queries from more than three other players.
60+
*/
61+
private static final AtomicBoolean limit3PlayersSeen = new AtomicBoolean(false);
62+
5663
/**
5764
* Check whether we are presently listening for device announcements.
5865
*
@@ -180,6 +187,11 @@ public boolean isAddressIgnored(InetAddress address) {
180187
return ignoredAddresses.contains(address);
181188
}
182189

190+
/**
191+
* The names of devices that are able to respond to metadata requests from more than three other devices.
192+
*/
193+
public final Set<String> METADATA_FLEXIBLE_DEVICES = Set.of("CDJ-3000", "XDJ-AZ");
194+
183195
/**
184196
* Handle a device announcement packet we have received.
185197
*
@@ -347,6 +359,17 @@ public Set<DeviceAnnouncement> getCurrentDevices() {
347359
return Set.copyOf(devices.values());
348360
}
349361

362+
/**
363+
* Check whether we have seen any players that are old enough to only be able to answer metadata queries
364+
* from at most three other players.
365+
*
366+
* @return {code true} if any device on the network would return {code true} when passed to {@link #isDeviceMetadataLimited(DeviceAnnouncement)}
367+
*/
368+
@API(status = API.Status.EXPERIMENTAL)
369+
public boolean isAnyDeviceLimitedToThreeDatabaseClients() {
370+
return limit3PlayersSeen.get();
371+
}
372+
350373
/**
351374
* Find and return the device announcement that was most recently received from a device identifying itself
352375
* with the specified device number, if any.
@@ -381,7 +404,7 @@ public DeviceAnnouncement getLatestAnnouncementFrom(int deviceNumber) {
381404
* <p>Device announcements are delivered to listeners on the
382405
* <a href="https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch thread</a>,
383406
* so it is fine to interact with user interface objects in listener methods. Any code in the listener method
384-
* must finish quickly, or unhandled events will back up and the user interface will be come unresponsive.</p>
407+
* must finish quickly, or unhandled events will back up and the user interface will become unresponsive.</p>
385408
*
386409
* @param listener the device announcement listener to add
387410
*/
@@ -416,12 +439,30 @@ public Set<DeviceAnnouncementListener> getDeviceAnnouncementListeners() {
416439
return Set.copyOf(deviceListeners);
417440
}
418441

442+
/**
443+
* Checks whether the device is old enough that it is unable to respond to metadata queries from more than
444+
* three other players.
445+
*
446+
* @param announcement the device to be examined
447+
*
448+
* @return {code true} if the device appears to be a CDJ that is not known to support metadata queries from more than three other devices
449+
*/
450+
@API(status = API.Status.EXPERIMENTAL)
451+
public boolean isDeviceMetadataLimited(DeviceAnnouncement announcement) {
452+
return announcement.getDeviceNumber() < 7 && !METADATA_FLEXIBLE_DEVICES.contains(announcement.getDeviceName());
453+
}
454+
419455
/**
420456
* Send a device found announcement to all registered listeners.
421457
*
422458
* @param announcement the message announcing the new device
423459
*/
424460
private void deliverFoundAnnouncement(final DeviceAnnouncement announcement) {
461+
// If this is a metadata-query-limited device, note that there is now at least one on the network.
462+
if (isDeviceMetadataLimited(announcement)) {
463+
limit3PlayersSeen.set(true);
464+
}
465+
// Send out the device announcement.
425466
for (final DeviceAnnouncementListener listener : getDeviceAnnouncementListeners()) {
426467
SwingUtilities.invokeLater(() -> {
427468
try {
@@ -438,7 +479,16 @@ private void deliverFoundAnnouncement(final DeviceAnnouncement announcement) {
438479
*
439480
* @param announcement the last message received from the vanished device
440481
*/
482+
@API(status = API.Status.EXPERIMENTAL)
441483
private void deliverLostAnnouncement(final DeviceAnnouncement announcement) {
484+
// If the device we lost was metadata-limited, see if it was the last one, and if so, update our tracker.
485+
if (isDeviceMetadataLimited(announcement)) {
486+
if (getCurrentDevices().stream().noneMatch(this::isDeviceMetadataLimited)) {
487+
limit3PlayersSeen.set(false);
488+
}
489+
}
490+
491+
// Send out the announcement.
442492
for (final DeviceAnnouncementListener listener : getDeviceAnnouncementListeners()) {
443493
SwingUtilities.invokeLater(() -> {
444494
try {

src/main/java/org/deepsymmetry/beatlink/dbserver/ConnectionManager.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,20 +110,20 @@ private synchronized Client allocateClient(int targetPlayer, String description)
110110
Client result = openClients.get(targetPlayer);
111111
if (result == null) {
112112
// We need to open a new connection.
113-
final DeviceAnnouncement deviceAnnouncement = DeviceFinder.getInstance().getLatestAnnouncementFrom(targetPlayer);
114-
if (deviceAnnouncement == null) {
113+
final DeviceAnnouncement targetDeviceAnnouncement = DeviceFinder.getInstance().getLatestAnnouncementFrom(targetPlayer);
114+
if (targetDeviceAnnouncement == null) {
115115
throw new IllegalStateException("Player " + targetPlayer + " could not be found " + description);
116116
}
117117
final int dbServerPort = getPlayerDBServerPort(targetPlayer);
118118
if (dbServerPort < 0) {
119119
throw new IllegalStateException("Player " + targetPlayer + " does not have a db server " + description);
120120
}
121121

122-
final byte posingAsPlayerNumber = (byte) chooseAskingPlayerNumber(targetPlayer);
122+
final byte posingAsPlayerNumber = (byte) chooseAskingPlayerNumber(targetDeviceAnnouncement);
123123

124124
Socket socket = null;
125125
try {
126-
InetSocketAddress address = new InetSocketAddress(deviceAnnouncement.getAddress(), dbServerPort);
126+
InetSocketAddress address = new InetSocketAddress(targetDeviceAnnouncement.getAddress(), dbServerPort);
127127
socket = new Socket();
128128
socket.connect(address, socketTimeout.get());
129129
socket.setSoTimeout(socketTimeout.get());
@@ -436,18 +436,23 @@ private byte[] readResponseWithExpectedSize(InputStream is) throws IOException {
436436
*
437437
* @throws IllegalStateException if there is no other player number available to use
438438
*/
439-
private int chooseAskingPlayerNumber(int targetPlayer) {
439+
private int chooseAskingPlayerNumber(DeviceAnnouncement targetPlayer) {
440440
final int fakeDevice = VirtualCdj.getInstance().getDeviceNumber();
441-
if ((targetPlayer > 15) || (fakeDevice >= 1 && fakeDevice <= 4)) {
441+
442+
if (fakeDevice > 4 && !DeviceFinder.getInstance().isDeviceMetadataLimited(targetPlayer)) {
443+
return targetPlayer.getDeviceNumber();
444+
}
445+
446+
if ((targetPlayer.getDeviceNumber() > 15) || (fakeDevice >= 1 && fakeDevice <= 4)) {
442447
return fakeDevice;
443448
}
444449

445450
for (DeviceAnnouncement candidate : DeviceFinder.getInstance().getCurrentDevices()) {
446451
final int realDevice = candidate.getDeviceNumber();
447-
if (realDevice != targetPlayer && realDevice >= 1 && realDevice <= 4) {
452+
if (realDevice != targetPlayer.getDeviceNumber() && realDevice >= 1 && realDevice <= 4) {
448453
final DeviceUpdate lastUpdate = VirtualCdj.getInstance().getLatestStatusFor(realDevice);
449454
if (lastUpdate instanceof CdjStatus &&
450-
((CdjStatus) lastUpdate).getTrackSourcePlayer() != targetPlayer) {
455+
((CdjStatus) lastUpdate).getTrackSourcePlayer() != targetPlayer.getDeviceNumber()) {
451456
return candidate.getDeviceNumber();
452457
}
453458
}

0 commit comments

Comments
 (0)