diff --git a/src/main/java/org/deepsymmetry/beatlink/CdjStatus.java b/src/main/java/org/deepsymmetry/beatlink/CdjStatus.java index 31eb8db..87dcade 100644 --- a/src/main/java/org/deepsymmetry/beatlink/CdjStatus.java +++ b/src/main/java/org/deepsymmetry/beatlink/CdjStatus.java @@ -28,7 +28,7 @@ public class CdjStatus extends DeviceUpdate { /** * The byte within a status packet which indicates that the device is in the process of handing off the tempo - * master role to anther device, labeled Mh in the + * master role to another device, labeled Mh in the * Packet Analysis document. * *

Normally it holds the value 0xff, but during a tempo master hand-off, it holds @@ -570,8 +570,8 @@ private PlayState3 findPlayState3() { } /** - * Contains the sizes we expect CDJ status packets to have so we can log a warning if we get an unusual - * one. We will then add the new size to the list so it only gets logged once per run. + * Contains the sizes we expect CDJ status packets to have, so we can log a warning if we get an unusual + * one. We will then add the new size to the list, so it only gets logged once per run. */ private static final Set expectedStatusPacketSizes = Collections.newSetFromMap(new ConcurrentHashMap<>()); static { @@ -610,8 +610,7 @@ public CdjStatus(DatagramPacket packet) { if (packetBytes.length != reportedPacketSize) { final String reportedKey = reportedPacketSize + "," + packetBytes.length; if (misreportedPacketSizes.add(reportedKey)) { - logger.warn("Received CDJ status packet with reported payload length of " + payloadLength + " and actual payload length of " + - (packetBytes.length - 0x24)); + logger.warn("Received CDJ status packet with reported payload length of {} and actual payload length of {}", payloadLength, packetBytes.length - 0x24); } } @@ -630,7 +629,7 @@ public CdjStatus(DatagramPacket packet) { handingMasterToDevice = Util.unsign(packetBytes[MASTER_HAND_OFF]); final byte trackSourceByte = packetBytes[40]; - if (Util.isOpusQuad(deviceName) && (trackSourceByte < 16)) { + if (isFromOpusQuad() && (trackSourceByte < 16)) { int sourcePlayer = Util.translateOpusPlayerNumbers(trackSourceByte); if (sourcePlayer != 0) { final SlotReference matchedSourceSlot = VirtualRekordbox.getInstance().findMatchedTrackSourceSlotForPlayer(deviceNumber); @@ -707,7 +706,7 @@ public int getBpm() { /** * Get the position within a measure of music at which the most recent beat occurred (a value from 1 to 4, where 1 - * represents the down beat). This value will be accurate when the track was properly configured within rekordbox + * represents the downbeat). This value will be accurate when the track was properly configured within rekordbox * (and if the music follows a standard House 4/4 time signature). * *

When the track being played has not been analyzed by rekordbox, or is playing on a non-nexus player, this @@ -766,7 +765,7 @@ public double getEffectiveTempo() { public boolean isPlaying() { if (packetBytes.length >= 212) { final boolean simpleResult = (packetBytes[STATUS_FLAGS] & PLAYING_FLAG) > 0; - if (!simpleResult && Util.isOpusQuad(deviceName)) { + if (!simpleResult && isFromOpusQuad()) { // Sometimes the Opus Quad lies and reports that it is not playing in this flag, even though it actually is. // Try to recover from that. return playState1 == PlayState1.PLAYING || playState1 == PlayState1.LOOPING || @@ -897,7 +896,7 @@ public boolean isDiscSlotAsleep() { * Audio CDs will reflect the audio track count, while data discs * will generally have one track regardless of how many usable audio files they contain when mounted. Also, * if the CD drive has powered off because of an extended period of not being used, when a track had been loaded - * from that disc, this seems to return 1 (you can check for that condition by calling {@link #isDiscSlotAsleep()}. + * from that disc, this seems to return 1 (you can check for that condition by calling {@link #isDiscSlotAsleep()}). * * @return the number of tracks found on the mounted disc or loaded playlist/player menu, or zero if no disc is mounted nor is a playlist/menu in use */ diff --git a/src/main/java/org/deepsymmetry/beatlink/DeviceAnnouncement.java b/src/main/java/org/deepsymmetry/beatlink/DeviceAnnouncement.java index 1420080..73d6296 100644 --- a/src/main/java/org/deepsymmetry/beatlink/DeviceAnnouncement.java +++ b/src/main/java/org/deepsymmetry/beatlink/DeviceAnnouncement.java @@ -1,5 +1,7 @@ package org.deepsymmetry.beatlink; +import org.deepsymmetry.beatlink.data.OpusProvider; + import java.net.DatagramPacket; import java.net.InetAddress; @@ -50,7 +52,7 @@ public DeviceAnnouncement(DatagramPacket packet) { packetBytes = new byte[packet.getLength()]; System.arraycopy(packet.getData(), 0, packetBytes, 0, packet.getLength()); timestamp = System.currentTimeMillis(); - name = new String(packetBytes, 12, 20).trim(); + name = new String(packetBytes, 12, 20).trim().intern(); number = Util.unsign(packetBytes[36]); } @@ -69,7 +71,7 @@ public DeviceAnnouncement(DatagramPacket packet, int deviceNumber) { packetBytes = new byte[packet.getLength()]; System.arraycopy(packet.getData(), 0, packetBytes, 0, packet.getLength()); timestamp = System.currentTimeMillis(); - name = new String(packetBytes, 12, 20).trim(); + name = new String(packetBytes, 12, 20).trim().intern(); number = deviceNumber; } @@ -153,6 +155,18 @@ public byte[] getPacketBytes() { return result; } + /** + * Check whether a device update came from an Opus Quad, which behaves very differently from true Pro DJ Link hardware. + * + * @return {@code true} when the device name reported in this update matches the one reported by the Opus Quad + */ + public boolean isOpusQuad() { + //noinspection StringEquality + return name == OpusProvider.opusName; // Since strings are interned, can be compared this way. + } + + + @Override public String toString() { return "DeviceAnnouncement[device:" + number + ", name:" + name + ", address:" + address.getHostAddress() + "]"; diff --git a/src/main/java/org/deepsymmetry/beatlink/DeviceFinder.java b/src/main/java/org/deepsymmetry/beatlink/DeviceFinder.java index 528f817..1d4d154 100644 --- a/src/main/java/org/deepsymmetry/beatlink/DeviceFinder.java +++ b/src/main/java/org/deepsymmetry/beatlink/DeviceFinder.java @@ -4,7 +4,6 @@ import java.net.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; @@ -38,7 +37,7 @@ public class DeviceFinder extends LifecycleParticipant { /** * The socket used to listen for announcement packets while we are active. */ - private final AtomicReference socket = new AtomicReference(null); + private final AtomicReference socket = new AtomicReference<>(null); /** * Track when we started listening for announcement packets. @@ -92,15 +91,15 @@ public long getFirstDeviceTime() { /** * Keep track of the announcements we have seen. */ - private final Map devices = new ConcurrentHashMap(); + private final Map devices = new ConcurrentHashMap<>(); /** * Remove any device announcements that are so old that the device seems to have gone away. */ private void expireDevices() { long now = System.currentTimeMillis(); - // Make a copy so we don't have to worry about concurrent modification. - Map copy = new HashMap(devices); + // Make a copy, so we don't have to worry about concurrent modification. + Map copy = new HashMap<>(devices); for (Map.Entry entry : copy.entrySet()) { if (now - entry.getValue().getTimestamp() > MAXIMUM_AGE) { devices.remove(entry.getKey()); @@ -138,7 +137,7 @@ private boolean isDeviceNew(DeviceAnnouncement announcement) { * its socket to this set when it is active so that it does not show up in the set of devices found on the network. */ private final Set ignoredAddresses = - Collections.newSetFromMap(new ConcurrentHashMap()); + Collections.newSetFromMap(new ConcurrentHashMap<>()); /** * Start ignoring any device updates which are received from the specified address. Intended for use by the @@ -161,8 +160,8 @@ public void removeIgnoredAddress(InetAddress address) { } /** - * Check whether an address is being ignored. (The {@link BeatFinder} will call this so it can filter out the - * {@link VirtualCdj}'s beat messages when it is broadcasting them, for example. + * Check whether an address is being ignored. (The {@link BeatFinder} will call this, so it can filter out the + * {@link VirtualCdj}'s beat messages when it is broadcasting them, for example). * * @param address the address to be checked as a candidate to be ignored * @@ -222,71 +221,63 @@ public synchronized void start() throws SocketException { final byte[] buffer = new byte[512]; final DatagramPacket packet = new DatagramPacket(buffer, buffer.length); - Thread receiver = new Thread(null, new Runnable() { - @Override - public void run() { - boolean received; - while (isRunning()) { - try { - if (getCurrentDevices().isEmpty()) { - socket.get().setSoTimeout(60000); // We have no devices to check for timeout; block for a whole minute to check for shutdown - } else { - socket.get().setSoTimeout(1000); // Check every second to see if a device has vanished - } - socket.get().receive(packet); - received = !ignoredAddresses.contains(packet.getAddress()); - } catch (SocketTimeoutException ste) { - received = false; - } catch (IOException e) { - // Don't log a warning if the exception was due to the socket closing at shutdown. - if (isRunning()) { - // We did not expect to have a problem; log a warning and shut down. - logger.warn("Problem reading from DeviceAnnouncement socket, stopping", e); - stop(); - } - received = false; + Thread receiver = new Thread(null, () -> { + boolean received; + while (isRunning()) { + try { + if (getCurrentDevices().isEmpty()) { + socket.get().setSoTimeout(60000); // We have no devices to check for timeout; block for a whole minute to check for shutdown + } else { + socket.get().setSoTimeout(1000); // Check every second to see if a device has vanished } - try { - if (received) { - final Util.PacketType kind = Util.validateHeader(packet, ANNOUNCEMENT_PORT); - if (kind == Util.PacketType.DEVICE_KEEP_ALIVE) { - // Looks like the kind of packet we need - if (packet.getLength() < 54) { - logger.warn("Ignoring too-short " + kind.name + " packet; expected 54 bytes, but only got " + - packet.getLength() + "."); - } else { - if (packet.getLength() > 54) { - logger.warn("Processing too-long " + kind.name + " packet; expected 54 bytes, but got " + - packet.getLength() + "."); - } - - DeviceAnnouncement announcement = new DeviceAnnouncement(packet); - - if (Util.isOpusQuad(announcement.getDeviceName())) { - - createAndProcessOpusAnnouncements(packet); - } else { + socket.get().receive(packet); + received = !ignoredAddresses.contains(packet.getAddress()); + } catch (SocketTimeoutException ste) { + received = false; + } catch (IOException e) { + // Don't log a warning if the exception was due to the socket closing at shutdown. + if (isRunning()) { + // We did not expect to have a problem; log a warning and shut down. + logger.warn("Problem reading from DeviceAnnouncement socket, stopping", e); + stop(); + } + received = false; + } + try { + if (received) { + final Util.PacketType kind = Util.validateHeader(packet, ANNOUNCEMENT_PORT); + if (kind == Util.PacketType.DEVICE_KEEP_ALIVE) { + // Looks like the kind of packet we need + if (packet.getLength() < 54) { + logger.warn("Ignoring too-short {} packet; expected 54 bytes, but only got {}.", kind.name, packet.getLength()); + } else { + if (packet.getLength() > 54) { + logger.warn("Processing too-long {} packet; expected 54 bytes, but got {}.", kind.name, packet.getLength()); + } - processAnnouncement(announcement); + DeviceAnnouncement announcement = new DeviceAnnouncement(packet); + if (announcement.isOpusQuad()) { + createAndProcessOpusAnnouncements(packet); + } else { + processAnnouncement(announcement); - if (VirtualCdj.getInstance().isRunning() && - announcement.getDeviceNumber() == VirtualCdj.getInstance().getDeviceNumber()) { - // Someone is using the same device number as we are! Try to defend it. - VirtualCdj.getInstance().defendDeviceNumber(announcement.getAddress()); - } + if (VirtualCdj.getInstance().isRunning() && + announcement.getDeviceNumber() == VirtualCdj.getInstance().getDeviceNumber()) { + // Someone is using the same device number as we are! Try to defend it. + VirtualCdj.getInstance().defendDeviceNumber(announcement.getAddress()); } } - } else if (kind == Util.PacketType.DEVICE_HELLO) { - logger.debug("Received device hello packet."); - } else if (kind != null) { - VirtualCdj.getInstance().handleSpecialAnnouncementPacket(kind, packet); } + } else if (kind == Util.PacketType.DEVICE_HELLO) { + logger.debug("Received device hello packet."); + } else if (kind != null) { + VirtualCdj.getInstance().handleSpecialAnnouncementPacket(kind, packet); } - expireDevices(); - } catch (Throwable t) { - logger.warn("Problem processing DeviceAnnouncement packet", t); } + expireDevices(); + } catch (Throwable t) { + logger.warn("Problem processing DeviceAnnouncement packet", t); } } }, "beat-link DeviceFinder receiver"); @@ -301,17 +292,14 @@ public void run() { * reachable. */ synchronized void flush() { - final Set lastDevices = new HashSet(devices.values()); + final Set lastDevices = new HashSet<>(devices.values()); devices.clear(); firstDeviceTime.set(0); // Report the loss of all our devices, on the proper thread, also outside our lock. - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - for (DeviceAnnouncement announcement : lastDevices) { - deliverLostAnnouncement(announcement); - } + SwingUtilities.invokeLater(() -> { + for (DeviceAnnouncement announcement : lastDevices) { + deliverLostAnnouncement(announcement); } }); } @@ -345,7 +333,7 @@ public Set getCurrentDevices() { } expireDevices(); // Get rid of anything past its sell-by date. // Make a copy so callers get an immutable snapshot of the current state. - return Collections.unmodifiableSet(new HashSet(devices.values())); + return Collections.unmodifiableSet(new HashSet<>(devices.values())); } /** @@ -372,7 +360,7 @@ public DeviceAnnouncement getLatestAnnouncementFrom(int deviceNumber) { * Keeps track of the registered device announcement listeners. */ private final Set deviceListeners = - Collections.newSetFromMap(new ConcurrentHashMap()); + Collections.newSetFromMap(new ConcurrentHashMap<>()); /** * Adds the specified device announcement listener to receive device announcements when DJ Link devices * are found on or leave the network. If {@code listener} is {@code null} or already present in the list @@ -412,7 +400,7 @@ public void removeDeviceAnnouncementListener(DeviceAnnouncementListener listener @SuppressWarnings("WeakerAccess") public Set getDeviceAnnouncementListeners() { // Make a copy so callers get an immutable snapshot of the current state. - return Collections.unmodifiableSet(new HashSet(deviceListeners)); + return Collections.unmodifiableSet(new HashSet<>(deviceListeners)); } /** @@ -422,14 +410,11 @@ public Set getDeviceAnnouncementListeners() { */ private void deliverFoundAnnouncement(final DeviceAnnouncement announcement) { for (final DeviceAnnouncementListener listener : getDeviceAnnouncementListeners()) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - try { - listener.deviceFound(announcement); - } catch (Throwable t) { - logger.warn("Problem delivering device found announcement to listener", t); - } + SwingUtilities.invokeLater(() -> { + try { + listener.deviceFound(announcement); + } catch (Throwable t) { + logger.warn("Problem delivering device found announcement to listener", t); } }); } @@ -442,14 +427,11 @@ public void run() { */ private void deliverLostAnnouncement(final DeviceAnnouncement announcement) { for (final DeviceAnnouncementListener listener : getDeviceAnnouncementListeners()) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - try { - listener.deviceLost(announcement); - } catch (Throwable t) { - logger.warn("Problem delivering device lost announcement to listener", t); - } + SwingUtilities.invokeLater(() -> { + try { + listener.deviceLost(announcement); + } catch (Throwable t) { + logger.warn("Problem delivering device lost announcement to listener", t); } }); } diff --git a/src/main/java/org/deepsymmetry/beatlink/DeviceUpdate.java b/src/main/java/org/deepsymmetry/beatlink/DeviceUpdate.java index a925ec5..deb6d98 100644 --- a/src/main/java/org/deepsymmetry/beatlink/DeviceUpdate.java +++ b/src/main/java/org/deepsymmetry/beatlink/DeviceUpdate.java @@ -1,5 +1,7 @@ package org.deepsymmetry.beatlink; +import org.deepsymmetry.beatlink.data.OpusProvider; + import java.net.DatagramPacket; import java.net.InetAddress; @@ -57,10 +59,10 @@ public DeviceUpdate(DatagramPacket packet, String name, int length) { address = packet.getAddress(); packetBytes = new byte[packet.getLength()]; System.arraycopy(packet.getData(), 0, packetBytes, 0, packet.getLength()); - deviceName = new String(packetBytes, 11, 20).trim(); + deviceName = new String(packetBytes, 11, 20).trim().intern(); preNexusCdj = deviceName.startsWith("CDJ") && (deviceName.endsWith("900") || deviceName.endsWith("2000")); - if (Util.isOpusQuad(deviceName)){ + if (isFromOpusQuad()) { deviceNumber = Util.translateOpusPlayerNumbers(packetBytes[40]); } else { deviceNumber = Util.unsign(packetBytes[33]); @@ -98,7 +100,7 @@ public String getDeviceName() { * Check whether this packet seems to have come from a CDJ older * than the original Nexus series (which means, for example, that * beat numbers will not be available, so the {@link org.deepsymmetry.beatlink.data.TimeFinder} - * can't work with it. + * can't work with it). * * @return {@code true} if the device name starts with "CDJ" and ends with "0". */ @@ -115,6 +117,16 @@ public int getDeviceNumber() { return deviceNumber; } + /** + * Check whether a device update came from an Opus Quad, which behaves very differently from true Pro DJ Link hardware. + * + * @return {@code true} when the device name reported in this update matches the one reported by the Opus Quad + */ + public boolean isFromOpusQuad() { + //noinspection StringEquality + return deviceName == OpusProvider.opusName; // Since strings are interned, can be compared this way. + } + /** * Get the raw data bytes of the device update packet. * @@ -183,9 +195,9 @@ public byte[] getPacketBytes() { /** * Get the position within a measure of music at which the most recent beat fell (a value from 1 to 4, where 1 represents - * the down beat). This value will be accurate for players when the track was properly configured within rekordbox + * the downbeat). This value will be accurate for players when the track was properly configured within rekordbox * (and if the music follows a standard House 4/4 time signature). The mixer makes no effort to synchronize - * down beats with players, however, so this value is meaningless when coming from the mixer. The usefulness of + * downbeats with players, however, so this value is meaningless when coming from the mixer. The usefulness of * this value can be checked with {@link #isBeatWithinBarMeaningful()}. * * @return the beat number within the current measure of music diff --git a/src/main/java/org/deepsymmetry/beatlink/Util.java b/src/main/java/org/deepsymmetry/beatlink/Util.java index 35d3b9b..f5661c4 100644 --- a/src/main/java/org/deepsymmetry/beatlink/Util.java +++ b/src/main/java/org/deepsymmetry/beatlink/Util.java @@ -9,7 +9,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.stream.IntStream; -import org.deepsymmetry.beatlink.data.OpusProvider; import org.deepsymmetry.cratedigger.pdb.RekordboxAnlz; import org.deepsymmetry.cratedigger.pdb.RekordboxAnlz.SongStructureEntry; import org.slf4j.Logger; @@ -140,7 +139,7 @@ public enum PacketType { /** * Metadata that includes track album art, possibly waveforms and more. We do not use this information at the moment - * because it is not complete enough to support all of the Beat Link Trigger functionality. Instead, we download + * because it is not complete enough to support all the Beat Link Trigger functionality. Instead, we download * the track data from a Rekordbox USB. */ OPUS_METADATA(0x56, "OPUS Metadata", VirtualCdj.UPDATE_PORT), @@ -289,8 +288,7 @@ public static PacketType validateHeader(DatagramPacket packet, int port) { byte[] data = packet.getData(); if (data.length < PACKET_TYPE_OFFSET) { - logger.warn("Packet is too short to be a Pro DJ Link packet; must be at least " + PACKET_TYPE_OFFSET + - " bytes long, was only " + data.length + "."); + logger.warn("Packet is too short to be a Pro DJ Link packet; must be at least " + PACKET_TYPE_OFFSET + " bytes long, was only {}.", data.length); return null; } @@ -302,8 +300,7 @@ public static PacketType validateHeader(DatagramPacket packet, int port) { final Map portMap = PACKET_TYPE_MAP.get(port); if (portMap == null) { // Warn about unrecognized port, once, and return null for packet type. if (!unknownPortsReported.contains(port)) { - logger.warn("Do not know any Pro DJ Link packets that are received on port " + port + - " (this will be reported only once)."); + logger.warn("Do not know any Pro DJ Link packets that are received on port {} (this will be reported only once).", port); unknownPortsReported.add(port); } return null; @@ -314,8 +311,7 @@ public static PacketType validateHeader(DatagramPacket packet, int port) { Set typesReportedForPort = unknownPortTypesReported.computeIfAbsent(port, k -> Collections.newSetFromMap(new ConcurrentHashMap<>())); // First problem we have seen for this port, set up set for it. if (!typesReportedForPort.contains(data[PACKET_TYPE_OFFSET])) { - logger.warn("Do not know any Pro DJ Link packets received on port " + port + " with type " + - String.format("0x%02x", data[PACKET_TYPE_OFFSET]) + " (this will be reported only once)."); + logger.warn("Do not know any Pro DJ Link packets received on port {} with type {} (this will be reported only once).", port, String.format("0x%02x", data[PACKET_TYPE_OFFSET])); typesReportedForPort.add(data[PACKET_TYPE_OFFSET]); } } @@ -434,7 +430,7 @@ public static long addressToLong(InetAddress address) { */ public static boolean sameNetwork(int prefixLength, InetAddress address1, InetAddress address2) { if (logger.isDebugEnabled()) { - logger.debug("Comparing address " + address1.getHostAddress() + " with " + address2.getHostAddress() + ", prefixLength=" + prefixLength); + logger.debug("Comparing address {} with {}, prefixLength={}", address1.getHostAddress(), address2.getHostAddress(), prefixLength); } long prefixMask = 0xffffffffL & (-1L << (32 - prefixLength)); return (addressToLong(address1) & prefixMask) == (addressToLong(address2) & prefixMask); @@ -1004,10 +1000,6 @@ public static String highResolutionPath(String artPath) { return artPath.replaceFirst("(\\.\\w+$)", "_m$1"); } - public static boolean isOpusQuad(String deviceName){ - return deviceName.equals(OpusProvider.opusName); - } - /** * Adjust the player numbers from the Opus-Quad so that they are 1-4 as expected by users and the rest of the * ecosystem. diff --git a/src/main/java/org/deepsymmetry/beatlink/VirtualCdj.java b/src/main/java/org/deepsymmetry/beatlink/VirtualCdj.java index b779950..34bbea8 100644 --- a/src/main/java/org/deepsymmetry/beatlink/VirtualCdj.java +++ b/src/main/java/org/deepsymmetry/beatlink/VirtualCdj.java @@ -42,10 +42,10 @@ public class VirtualCdj extends LifecycleParticipant { /** * The socket used to receive device status packets while we are active. */ - private final AtomicReference socket = new AtomicReference(); + private final AtomicReference socket = new AtomicReference<>(); /** - * Indicates we started {@link VirtualRekordbox} running so we are just acting as a proxy for it, to + * Indicates we started {@link VirtualRekordbox} running, so we are just acting as a proxy for it, to * work with the Opus Quad. */ private final AtomicBoolean proxyingForVirtualRekordbox = new AtomicBoolean(false); @@ -86,7 +86,7 @@ public InetAddress getLocalAddress() { * up by finding the network interface address on which we are receiving the other devices' * announcement broadcasts. */ - private final AtomicReference broadcastAddress = new AtomicReference(); + private final AtomicReference broadcastAddress = new AtomicReference<>(); /** * Return the broadcast address used to reach the DJ Link network. @@ -102,7 +102,7 @@ public InetAddress getBroadcastAddress() { /** * Keep track of the most recent updates we have seen, indexed by the address they came from. */ - private final Map updates = new ConcurrentHashMap(); + private final Map updates = new ConcurrentHashMap<>(); /** * Should we try to use a device number in the range 1 to 4 if we find one is available? @@ -142,7 +142,7 @@ public boolean getUseStandardPlayerNumber() { * This starts out being zero unless you explicitly assign another value, which means that the VirtualCdj * should assign itself an unused device number by watching the network when you call * {@link #start()}. If {@link #getUseStandardPlayerNumber()} returns {@code true}, self-assignment will try to - * find a value in the range 1 to 4. Otherwise it will try to find a value in the range 7 to 15 (so that it does + * find a value in the range 1 to 4. Otherwise, it will try to find a value in the range 7 to 15 (so that it does * not even conflict with newer CDJ-3000 networks, which can use channels 5 and 6). Even when told * to use a standard player number, if all device numbers in that range are already in use, we will be forced to * use a larger number. @@ -261,12 +261,7 @@ public synchronized void setDeviceName(String name) { /** * Reacts to player status updates to reflect the current playback state. */ - private final DeviceUpdateListener updateListener = new DeviceUpdateListener() { - @Override - public void received(DeviceUpdate update) { - processUpdate(update); - } - }; + private final DeviceUpdateListener updateListener = this::processUpdate; public DeviceUpdateListener getUpdateListener() { return updateListener; @@ -331,7 +326,7 @@ public DeviceUpdateListener getUpdateListener() { /** * Keep track of which device has reported itself as the current tempo master. */ - private final AtomicReference tempoMaster = new AtomicReference(); + private final AtomicReference tempoMaster = new AtomicReference<>(); /** * Check which device is the current tempo master, returning the {@link DeviceUpdate} packet in which it @@ -437,7 +432,7 @@ private DeviceUpdate buildUpdate(DatagramPacket packet) { switch (kind) { case MIXER_STATUS: if (length != 56) { - logger.warn("Processing a Mixer Status packet with unexpected length " + length + ", expected 56 bytes."); + logger.warn("Processing a Mixer Status packet with unexpected length {}, expected 56 bytes.", length); } if (length >= 56) { return new MixerStatus(packet); @@ -451,13 +446,12 @@ private DeviceUpdate buildUpdate(DatagramPacket packet) { return new CdjStatus(packet); } else { - logger.warn("Ignoring too-short CDJ Status packet with length " + length + " (we need " + CdjStatus.MINIMUM_PACKET_SIZE + - " bytes)."); + logger.warn("Ignoring too-short CDJ Status packet with length {} (we need " + CdjStatus.MINIMUM_PACKET_SIZE + " bytes).", length); return null; } case LOAD_TRACK_ACK: - logger.info("Received track load acknowledgment from player " + packet.getData()[0x21]); + logger.info("Received track load acknowledgment from player {}", packet.getData()[0x21]); return null; case MEDIA_QUERY: @@ -469,7 +463,7 @@ private DeviceUpdate buildUpdate(DatagramPacket packet) { return null; default: - logger.warn("Ignoring " + kind.name + " packet sent to update port."); + logger.warn("Ignoring {} packet sent to update port.", kind.name); return null; } } @@ -507,11 +501,9 @@ void processUpdate(DeviceUpdate update) { syncCounter.set(largestSyncCounter.get() + 1); } else { if (nextMaster.get() == 0xff) { - logger.warn("Saw master asserted by player " + update.deviceNumber + - " when we were not yielding it."); + logger.warn("Saw master asserted by player {} when we were not yielding it.", update.deviceNumber); } else { - logger.warn("Expected to yield master role to player " + nextMaster.get() + - " but saw master asserted by player " + update.deviceNumber); + logger.warn("Expected to yield master role to player {} but saw master asserted by player {}", nextMaster.get(), update.deviceNumber); } } } @@ -530,8 +522,7 @@ void processUpdate(DeviceUpdate update) { if (masterYieldedFrom.get() == 0) { logger.info("Accepting unsolicited Master yield; we must be the only synced device playing."); } else { - logger.warn("Expected player " + masterYieldedFrom.get() + " to yield master to us, but player " + - update.deviceNumber + " did."); + logger.warn("Expected player {} to yield master to us, but player {} did.", masterYieldedFrom.get(), update.deviceNumber); } } master.set(true); @@ -597,14 +588,14 @@ private boolean selfAssignDeviceNumber() { if (claimingNumber.get() == 0) { // We have not yet tried a number. If we are not supposed to use standard player numbers, make sure - // the first one we try is 7 (to accommodate the CDJ-3000, which can use channels 5 and 6. + // the first one we try is 7 (to accommodate the CDJ-3000, which can use channels 5 and 6). if (!getUseStandardPlayerNumber()) { claimingNumber.set(6); } } // Record what numbers we have already seen, since there is no point trying one of them. - Set numbersUsed = new HashSet(); + Set numbersUsed = new HashSet<>(); for (DeviceAnnouncement device : DeviceFinder.getInstance().getCurrentDevices()) { numbersUsed.add(device.getDeviceNumber()); } @@ -615,13 +606,12 @@ private boolean selfAssignDeviceNumber() { if (!numbersUsed.contains(result)) { // We found one that is not used, so we can use it claimingNumber.set(result); if (getUseStandardPlayerNumber() && (result > 4)) { - logger.warn("Unable to self-assign a standard player number, all are in use. Trying number " + - result + "."); + logger.warn("Unable to self-assign a standard player number, all are in use. Trying number {}.", result); } return true; } } - logger.warn("Found no unused device numbers between " + startingNumber + " and 15, giving up."); + logger.warn("Found no unused device numbers between {} and 15, giving up.", startingNumber); return false; } @@ -656,7 +646,7 @@ public List getMatchingInterfaces() { /** * If we are in the process of trying to establish a device number, this will hold the number we are - * currently trying to claim. Otherwise it will hold the value 0. + * currently trying to claim. Otherwise, it will hold the value 0. */ private final AtomicInteger claimingNumber = new AtomicInteger(0); @@ -696,8 +686,7 @@ private void requestNumberFromMixer(InetAddress mixerAddress) { try { DatagramPacket announcement = new DatagramPacket(assignmentRequestBytes, assignmentRequestBytes.length, mixerAddress, DeviceFinder.ANNOUNCEMENT_PORT); - logger.debug("Sending device number request to mixer at address " + announcement.getAddress().getHostAddress() + - ", port " + announcement.getPort()); + logger.debug("Sending device number request to mixer at address {}, port {}", announcement.getAddress().getHostAddress(), announcement.getPort()); currentSocket.send(announcement); } catch (Exception e) { logger.warn("Unable to send device number request to mixer.", e); @@ -725,8 +714,7 @@ void defendDeviceNumber(InetAddress invaderAddress) { try { DatagramPacket defense = new DatagramPacket(deviceNumberDefenseBytes, deviceNumberDefenseBytes.length, invaderAddress, DeviceFinder.ANNOUNCEMENT_PORT); - logger.info("Sending device number defense packet to invader at address " + defense.getAddress().getHostAddress() + - ", port " + defense.getPort()); + logger.info("Sending device number defense packet to invader at address {}, port {}", defense.getAddress().getHostAddress(), defense.getPort()); currentSocket.send(defense); } catch (Exception e) { logger.error("Unable to send device defense packet.", e); @@ -749,7 +737,7 @@ private boolean claimDeviceNumber() { System.arraycopy(getDeviceName().getBytes(), 0, helloBytes, DEVICE_NAME_OFFSET, getDeviceName().getBytes().length); for (int i = 1; i <= 3; i++) { try { - logger.debug("Sending hello packet " + i); + logger.debug("Sending hello packet {}", i); DatagramPacket announcement = new DatagramPacket(helloBytes, helloBytes.length, broadcastAddress.get(), DeviceFinder.ANNOUNCEMENT_PORT); socket.get().send(announcement); @@ -781,7 +769,7 @@ private boolean claimDeviceNumber() { for (int i = 1; i <= 3 && mixerAssigned.get() == 0; i++) { claimStage1bytes[0x24] = (byte)i; // The packet counter. try { - logger.debug("Sending claim stage 1 packet " + i); + logger.debug("Sending claim stage 1 packet {}", i); DatagramPacket announcement = new DatagramPacket(claimStage1bytes, claimStage1bytes.length, broadcastAddress.get(), DeviceFinder.ANNOUNCEMENT_PORT); socket.get().send(announcement); @@ -796,7 +784,7 @@ private boolean claimDeviceNumber() { if (getDeviceNumber() == 0) { // We are trying to pick a number. continue selfAssignLoop; // Try the next available number, if any. } - logger.warn("Unable to use device number " + getDeviceNumber() + ", another device has it. Failing to go online."); + logger.warn("Unable to use device number {}, another device has it. Failing to go online.", getDeviceNumber()); claimingNumber.set(0); return false; } @@ -813,7 +801,7 @@ private boolean claimDeviceNumber() { for (int i = 1; i <= 3 && mixerAssigned.get() == 0; i++) { claimStage2bytes[0x2f] = (byte)i; // The packet counter. try { - logger.debug("Sending claim stage 2 packet " + i + " for device " + claimStage2bytes[0x2e]); + logger.debug("Sending claim stage 2 packet {} for device {}", i, claimStage2bytes[0x2e]); DatagramPacket announcement = new DatagramPacket(claimStage2bytes, claimStage2bytes.length, broadcastAddress.get(), DeviceFinder.ANNOUNCEMENT_PORT); socket.get().send(announcement); @@ -828,7 +816,7 @@ private boolean claimDeviceNumber() { if (getDeviceNumber() == 0) { // We are trying to pick a number. continue selfAssignLoop; // Try the next available number, if any. } - logger.warn("Unable to use device number " + getDeviceNumber() + ", another device has it. Failing to go online."); + logger.warn("Unable to use device number {}, another device has it. Failing to go online.", getDeviceNumber()); claimingNumber.set(0); return false; } @@ -848,7 +836,7 @@ private boolean claimDeviceNumber() { for (int i = 1; i <= 3 && mixerAssigned.get() == 0; i++) { claimStage3bytes[0x25] = (byte)i; // The packet counter. try { - logger.debug("Sending claim stage 3 packet " + i + " for device " + claimStage3bytes[0x24]); + logger.debug("Sending claim stage 3 packet {} for device {}", i, claimStage3bytes[0x24]); DatagramPacket announcement = new DatagramPacket(claimStage3bytes, claimStage3bytes.length, broadcastAddress.get(), DeviceFinder.ANNOUNCEMENT_PORT); socket.get().send(announcement); @@ -863,7 +851,7 @@ private boolean claimDeviceNumber() { if (getDeviceNumber() == 0) { // We are trying to pick a number. continue selfAssignLoop; // Try the next available number, if any. } - logger.warn("Unable to use device number " + getDeviceNumber() + ", another device has it. Failing to go online."); + logger.warn("Unable to use device number {}, another device has it. Failing to go online.", getDeviceNumber()); claimingNumber.set(0); return false; } @@ -886,7 +874,7 @@ private boolean claimDeviceNumber() { */ private boolean createVirtualCdj() throws SocketException { // Find the network interface and address to use to communicate with the first device we found. - matchingInterfaces = new ArrayList(); + matchingInterfaces = new ArrayList<>(); matchedAddress = null; DeviceAnnouncement aDevice = DeviceFinder.getInstance().getCurrentDevices().iterator().next(); for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) { @@ -900,18 +888,15 @@ private boolean createVirtualCdj() throws SocketException { } if (matchedAddress == null) { - logger.warn("Unable to find network interface to communicate with " + aDevice + - ", giving up."); + logger.warn("Unable to find network interface to communicate with {}, giving up.", aDevice); return false; } - logger.info("Found matching network interface " + matchingInterfaces.get(0).getDisplayName() + " (" + - matchingInterfaces.get(0).getName() + "), will use address " + matchedAddress); + logger.info("Found matching network interface {} ({}), will use address {}", matchingInterfaces.get(0).getDisplayName(), matchingInterfaces.get(0).getName(), matchedAddress); if (matchingInterfaces.size() > 1) { for (ListIterator it = matchingInterfaces.listIterator(1); it.hasNext(); ) { NetworkInterface extra = it.next(); - logger.warn("Network interface " + extra.getDisplayName() + " (" + extra.getName() + - ") sees same network: we will likely get duplicate DJ Link packets, causing severe problems."); + logger.warn("Network interface {} ({}) sees same network: we will likely get duplicate DJ Link packets, causing severe problems.", extra.getDisplayName(), extra.getName()); } } @@ -941,12 +926,9 @@ private boolean createVirtualCdj() throws SocketException { receiver.start(); // Create the thread which announces our participation in the DJ Link network, to request update packets - Thread announcer = new Thread(null, new Runnable() { - @Override - public void run() { - while (isRunning()) { - sendAnnouncement(broadcastAddress.get()); - } + Thread announcer = new Thread(null, () -> { + while (isRunning()) { + sendAnnouncement(broadcastAddress.get()); } }, "beat-link VirtualCdj announcement sender"); announcer.setDaemon(true); @@ -965,34 +947,31 @@ private Thread createStatusReceiver() { final DatagramPacket packet = new DatagramPacket(buffer, buffer.length); // Create the update reception thread - Thread receiver = new Thread(null, new Runnable() { - @Override - public void run() { - boolean received; - while (isRunning()) { - try { - socket.get().receive(packet); - received = true; - } catch (IOException e) { - // Don't log a warning if the exception was due to the socket closing at shutdown. - if (isRunning()) { - // We did not expect to have a problem; log a warning and shut down. - logger.warn("Problem reading from DeviceStatus socket, flushing DeviceFinder due to likely network change and shutting down.", e); - DeviceFinder.getInstance().flush(); - stop(); - } - received = false; + Thread receiver = new Thread(null, () -> { + boolean received; + while (isRunning()) { + try { + socket.get().receive(packet); + received = true; + } catch (IOException e) { + // Don't log a warning if the exception was due to the socket closing at shutdown. + if (isRunning()) { + // We did not expect to have a problem; log a warning and shut down. + logger.warn("Problem reading from DeviceStatus socket, flushing DeviceFinder due to likely network change and shutting down.", e); + DeviceFinder.getInstance().flush(); + stop(); } - try { - if (received && (packet.getAddress() != socket.get().getLocalAddress())) { - DeviceUpdate update = buildUpdate(packet); - if (update != null && isRunning()) { - processUpdate(update); - } + received = false; + } + try { + if (received && (packet.getAddress() != socket.get().getLocalAddress())) { + DeviceUpdate update = buildUpdate(packet); + if (update != null && isRunning()) { + processUpdate(update); } - } catch (Throwable t) { - logger.warn("Problem processing device update packet", t); } + } catch (Throwable t) { + logger.warn("Problem processing device update packet", t); } } }, "beat-link VirtualCdj status receiver"); @@ -1011,7 +990,7 @@ public void run() { */ public Set findUnreachablePlayers() { ensureRunning(); - Set result = new HashSet(); + Set result = new HashSet<>(); for (DeviceAnnouncement candidate: DeviceFinder.getInstance().getCurrentDevices()) { if (!Util.sameNetwork(matchedAddress.getNetworkPrefixLength(), matchedAddress.getAddress(), candidate.getAddress())) { result.add(candidate); @@ -1075,7 +1054,7 @@ public synchronized boolean start() throws Exception { // Set up so we know we have to shut down if the DeviceFinder shuts down. DeviceFinder.getInstance().addLifecycleListener(deviceFinderLifecycleListener); - // Find some DJ Link devices so we can figure out the interface and address to use to talk to them + // Find some DJ Link devices, so we can figure out the interface and address to use to talk to them DeviceFinder.getInstance().start(); for (int i = 0; DeviceFinder.getInstance().getCurrentDevices().isEmpty() && i < 20; i++) { try { @@ -1094,7 +1073,7 @@ public synchronized boolean start() throws Exception { // See if there is an Opus Quad on the network, which means we need to be in the limited compatibility mode. for (DeviceAnnouncement device : DeviceFinder.getInstance().getCurrentDevices()) { - if (Util.isOpusQuad(device.getDeviceName())) { + if (device.isOpusQuad()) { proxyingForVirtualRekordbox.set(true); VirtualRekordbox.getInstance().addLifecycleListener(virtualRekordboxLifecycleListener); final boolean success = VirtualRekordbox.getInstance().start(); @@ -1195,7 +1174,7 @@ private void sendAnnouncement(InetAddress broadcastAddress) { */ public Set getLatestStatus() { ensureRunning(); - Set result = new HashSet(); + Set result = new HashSet<>(); long now = System.currentTimeMillis(); for (DeviceUpdate update : updates.values()) { if (now - update.getTimestamp() <= DeviceFinder.MAXIMUM_AGE) { @@ -1269,7 +1248,7 @@ public DeviceUpdate getLatestStatusFor(int deviceNumber) { * Keeps track of the registered master listeners. */ private final Set masterListeners = - Collections.newSetFromMap(new ConcurrentHashMap()); + Collections.newSetFromMap(new ConcurrentHashMap<>()); /** *

Adds the specified master listener to receive device updates when there are changes related @@ -1314,7 +1293,7 @@ public void removeMasterListener(MasterListener listener) { @SuppressWarnings("WeakerAccess") public Set getMasterListeners() { // Make a copy so callers get an immutable snapshot of the current state. - return Collections.unmodifiableSet(new HashSet(masterListeners)); + return Collections.unmodifiableSet(new HashSet<>(masterListeners)); } /** @@ -1366,7 +1345,7 @@ private void deliverBeatAnnouncement(final Beat beat) { * Keeps track of the registered device update listeners. */ private final Set updateListeners = - Collections.newSetFromMap(new ConcurrentHashMap()); + Collections.newSetFromMap(new ConcurrentHashMap<>()); /** *

Adds the specified device update listener to receive device updates whenever they come in. @@ -1411,7 +1390,7 @@ public void removeUpdateListener(DeviceUpdateListener listener) { */ public Set getUpdateListeners() { // Make a copy so callers get an immutable snapshot of the current state. - return Collections.unmodifiableSet(new HashSet(updateListeners)); + return Collections.unmodifiableSet(new HashSet<>(updateListeners)); } /** @@ -1433,7 +1412,7 @@ private void deliverDeviceUpdate(final DeviceUpdate update) { * Keeps track of the registered media details listeners. */ private final Set detailsListeners = - Collections.newSetFromMap(new ConcurrentHashMap()); + Collections.newSetFromMap(new ConcurrentHashMap<>()); /** *

Adds the specified media details listener to receive detail responses whenever they come in. @@ -1477,7 +1456,7 @@ public void removeMediaDetailsListener(MediaDetailsListener listener) { */ public Set getMediaDetailsListeners() { // Make a copy so callers get an immutable snapshot of the current state. - return Collections.unmodifiableSet(new HashSet(detailsListeners)); + return Collections.unmodifiableSet(new HashSet<>(detailsListeners)); } /** @@ -1959,7 +1938,7 @@ public void stopped(LifecycleParticipant sender) { * Will hold an instance when we are actively sending beats, so we can let it know when the metronome changes, * and when it is time to shut down. */ - private final AtomicReference beatSender = new AtomicReference(); + private final AtomicReference beatSender = new AtomicReference<>(); /** * Check whether we are currently running a {@link BeatSender}; if we are, notify it that there has been a change @@ -2067,17 +2046,14 @@ public synchronized void setSendingStatus(boolean send) throws IOException { final AtomicBoolean stillRunning = new AtomicBoolean(true); sendingStatus = stillRunning; // Allow other threads to stop us when necessary. - Thread sender = new Thread(null, new Runnable() { - @Override - public void run() { - while (stillRunning.get()) { - sendStatus(); - try { - //noinspection BusyWait - Thread.sleep(getStatusInterval()); - } catch (InterruptedException e) { - logger.warn("beat-link VirtualCDJ status sender thread was interrupted; continuing"); - } + Thread sender = new Thread(null, () -> { + while (stillRunning.get()) { + sendStatus(); + try { + //noinspection BusyWait + Thread.sleep(getStatusInterval()); + } catch (InterruptedException e) { + logger.warn("beat-link VirtualCDJ status sender thread was interrupted; continuing"); } } }, "beat-link VirtualCdj status sender"); @@ -2125,7 +2101,7 @@ public synchronized boolean isSendingStatus() { * playing, and it will keep time from there. When we stop again, we save the metronome's current beat here. */ private final AtomicReference whereStopped = - new AtomicReference(metronome.getSnapshot(metronome.getStartTime())); + new AtomicReference<>(metronome.getSnapshot(metronome.getStartTime())); /** * Indicates whether we should currently pretend to be playing. This will only have an impact when we are sending @@ -2216,7 +2192,7 @@ public void adjustPlaybackPosition(int ms) { /** * When have started the process of requesting the tempo master role from another player, this gets set to its - * device number. Otherwise it has the value {@code 0}. + * device number. Otherwise, it has the value {@code 0}. */ private final AtomicInteger requestingMasterRoleFromPlayer = new AtomicInteger(0); @@ -2242,7 +2218,7 @@ public synchronized void becomeTempoMaster() throws IOException { payload[2] = getDeviceNumber(); payload[8] = getDeviceNumber(); if (logger.isDebugEnabled()) { - logger.debug("Sending master yield request to player " + currentMaster); + logger.debug("Sending master yield request to player {}", currentMaster); } requestingMasterRoleFromPlayer.set(currentMaster.deviceNumber); assembleAndSendPacket(Util.PacketType.MASTER_HANDOFF_REQUEST, payload, currentMaster.address, BeatFinder.BEAT_PORT); @@ -2358,7 +2334,7 @@ public boolean isOnAir() { /** * Controls the tempo at which we report ourselves to be playing. Only meaningful if we are sending status packets. * If {@link #isSynced()} is {@code true} and we are not the tempo master, any value set by this method will - * overridden by the the next tempo master change. + * be overridden by the next tempo master change. * * @param bpm the tempo, in beats per minute, that we should report in our status and beat packets */ @@ -2503,7 +2479,7 @@ private Snapshot avoidBeatPacket() { /** * Send a status packet to all devices on the network. Used when we are actively sending status, presumably so we - * we can be the tempo master. Avoids sending one within twice {@link BeatSender#BEAT_THRESHOLD} milliseconds of + * can be the tempo master. Avoids sending one within twice {@link BeatSender#BEAT_THRESHOLD} milliseconds of * a beat, to make sure the beat packet announces the new beat before an early status packet confuses matters. */ private void sendStatus() { @@ -2537,7 +2513,7 @@ private void sendStatus() { try { socket.get().send(packet); } catch (IOException e) { - logger.warn("Unable to send status packet to " + device, e); + logger.warn("Unable to send status packet to {}", device, e); } } } @@ -2563,21 +2539,13 @@ private VirtualCdj() { masterTempo.set(Double.doubleToLongBits(0.0)); // Note that we have no master tempo yet. // Arrange to have our status accurately reflect any relevant updates and commands from the mixer. - BeatFinder.getInstance().addOnAirListener(new OnAirListener() { - @Override - public void channelsOnAir(Set audibleChannels) { - setOnAir(audibleChannels.contains((int)getDeviceNumber())); - } - }); + BeatFinder.getInstance().addOnAirListener(audibleChannels -> setOnAir(audibleChannels.contains((int)getDeviceNumber()))); - BeatFinder.getInstance().addFaderStartListener(new FaderStartListener() { - @Override - public void fadersChanged(Set playersToStart, Set playersToStop) { - if (playersToStart.contains((int)getDeviceNumber())) { - setPlaying(true); - } else if (playersToStop.contains((int)getDeviceNumber())) { - setPlaying(false); - } + BeatFinder.getInstance().addFaderStartListener((playersToStart, playersToStop) -> { + if (playersToStart.contains((int)getDeviceNumber())) { + setPlaying(true); + } else if (playersToStop.contains((int)getDeviceNumber())) { + setPlaying(false); } }); @@ -2591,14 +2559,11 @@ public void setSyncMode(boolean synced) { public void becomeMaster() { logger.debug("Received packet telling us to become master."); if (isSendingStatus()) { - new Thread(new Runnable() { - @Override - public void run() { - try { - becomeTempoMaster(); - } catch (Throwable t) { - logger.error("Problem becoming tempo master in response to sync command packet", t); - } + new Thread(() -> { + try { + becomeTempoMaster(); + } catch (Throwable t) { + logger.error("Problem becoming tempo master in response to sync command packet", t); } }).start(); } else { @@ -2611,14 +2576,14 @@ public void run() { @Override public void yieldMasterTo(int deviceNumber) { if (logger.isDebugEnabled()) { - logger.debug("Received instruction to yield master to device " + deviceNumber); + logger.debug("Received instruction to yield master to device {}", deviceNumber); } if (isTempoMaster()) { if (isSendingStatus() && getDeviceNumber() != deviceNumber) { nextMaster.set(deviceNumber); final DeviceUpdate lastStatusFromNewMaster = getLatestStatusFor(deviceNumber); if (lastStatusFromNewMaster == null) { - logger.warn("Unable to send master yield response to device " + deviceNumber + ": no status updates have been received from it!"); + logger.warn("Unable to send master yield response to device {}: no status updates have been received from it!", deviceNumber); } else { byte[] payload = new byte[YIELD_ACK_PAYLOAD.length]; System.arraycopy(YIELD_ACK_PAYLOAD, 0, payload, 0, YIELD_ACK_PAYLOAD.length); @@ -2627,12 +2592,12 @@ public void yieldMasterTo(int deviceNumber) { try { assembleAndSendPacket(Util.PacketType.MASTER_HANDOFF_RESPONSE, payload, lastStatusFromNewMaster.getAddress(), UPDATE_PORT); } catch (Throwable t) { - logger.error("Problem sending master yield acknowledgment to player " + deviceNumber, t); + logger.error("Problem sending master yield acknowledgment to player {}", deviceNumber, t); } } } } else { - logger.warn("Ignoring instruction to yield master to device " + deviceNumber + ": we were not tempo master."); + logger.warn("Ignoring instruction to yield master to device {}: we were not tempo master.", deviceNumber); } } @@ -2640,7 +2605,7 @@ public void yieldMasterTo(int deviceNumber) { @Override public void yieldResponse(int deviceNumber, boolean yielded) { if (logger.isDebugEnabled()) { - logger.debug("Received yield response of " + yielded + " from device " + deviceNumber); + logger.debug("Received yield response of {} from device {}", yielded, deviceNumber); } if (yielded) { if (isSendingStatus()) { @@ -2649,11 +2614,9 @@ public void yieldResponse(int deviceNumber, boolean yielded) { masterYieldedFrom.set(deviceNumber); } else { if (requestingMasterRoleFromPlayer.get() == 0) { - logger.warn("Ignoring master yield response from player " + deviceNumber + - " because we are not trying to become tempo master."); + logger.warn("Ignoring master yield response from player {} because we are not trying to become tempo master.", deviceNumber); } else { - logger.warn("Ignoring master yield response from player " + deviceNumber + - " because we asked player " + requestingMasterRoleFromPlayer.get()); + logger.warn("Ignoring master yield response from player {} because we asked player {}", deviceNumber, requestingMasterRoleFromPlayer.get()); } } } else { @@ -2697,7 +2660,7 @@ void handleSpecialAnnouncementPacket(Util.PacketType kind, DatagramPacket packet } else if (kind == Util.PacketType.DEVICE_NUMBER_STAGE_3) { handleDeviceClaimPacket(packet, 0x24); } else if (kind == Util.PacketType.DEVICE_NUMBER_WILL_ASSIGN) { - logger.debug("The mixer at address " + packet.getAddress().getHostAddress() + " wants to assign us a specific device number."); + logger.debug("The mixer at address {} wants to assign us a specific device number.", packet.getAddress().getHostAddress()); if (claimingNumber.get() != 0) { requestNumberFromMixer(packet.getAddress()); } else { @@ -2706,9 +2669,9 @@ void handleSpecialAnnouncementPacket(Util.PacketType kind, DatagramPacket packet } else if (kind == Util.PacketType.DEVICE_NUMBER_ASSIGN) { mixerAssigned.set(packet.getData()[0x24]); if (mixerAssigned.get() == 0) { - logger.debug("Mixer at address " + packet.getAddress().getHostAddress() + " told us to use any device."); + logger.debug("Mixer at address {} told us to use any device.", packet.getAddress().getHostAddress()); } else { - logger.info("Mixer at address " + packet.getAddress().getHostAddress() + " told us to use device number " + mixerAssigned.get()); + logger.info("Mixer at address {} told us to use device number {}", packet.getAddress().getHostAddress(), mixerAssigned.get()); } } else if (kind == Util.PacketType.DEVICE_NUMBER_ASSIGNMENT_FINISHED) { mixerAssigned.set(claimingNumber.get()); @@ -2718,20 +2681,20 @@ void handleSpecialAnnouncementPacket(Util.PacketType kind, DatagramPacket packet if (defendedDevice == 0) { logger.warn("Ignoring unexplained attempt to defend device 0."); } else if (defendedDevice == claimingNumber.get()) { - logger.warn("Another device is defending device number " + defendedDevice + ", so we can't use it."); + logger.warn("Another device is defending device number {}, so we can't use it.", defendedDevice); claimRejected.set(true); } else if (isRunning()) { if (defendedDevice == getDeviceNumber()) { logger.warn("Another device has claimed it owns our device number, shutting down."); stop(); } else { - logger.warn("Another device is defending a number we are not using, ignoring: " + defendedDevice); + logger.warn("Another device is defending a number we are not using, ignoring: {}", defendedDevice); } } else { - logger.warn("Received device number defense message for device number " + defendedDevice + " when we are not even running!"); + logger.warn("Received device number defense message for device number {} when we are not even running!", defendedDevice); } } else { - logger.warn("Received unrecognized special announcement packet type: " + kind); + logger.warn("Received unrecognized special announcement packet type: {}", kind); } } diff --git a/src/main/java/org/deepsymmetry/beatlink/data/OpusProvider.java b/src/main/java/org/deepsymmetry/beatlink/data/OpusProvider.java index 44aab18..c866bec 100644 --- a/src/main/java/org/deepsymmetry/beatlink/data/OpusProvider.java +++ b/src/main/java/org/deepsymmetry/beatlink/data/OpusProvider.java @@ -36,12 +36,10 @@ public class OpusProvider { private static final Logger logger = LoggerFactory.getLogger(OpusProvider.class); /** - * Public constant for the opus name to be used throughout the codebase. + * The device name reported by Opus Quad, so we can recognize when we are dealing with one of these devices. */ public static final String opusName = "OPUS-QUAD"; - - /** * Keep track of whether we are running. */