Class Carabiner
- java.lang.Object
-
- org.deepsymmetry.bcj.Carabiner
-
@API(status=MAINTAINED) public class Carabiner extends Object
Manages tempo synchronization between an Ableton Link session and a Pro DJ Link network.
-
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
abletonLinkIsMaster(boolean enabled)
Controls whether the Ableton link session timeline should be the tempo master for the Pro DJ Link devices.void
addDisconnectionListener(DisconnectionListener listener)
Adds the specified disconnection listener to be notified when we close our Carabiner connection.void
addStateListener(StateListener listener)
Adds the specified state listener to receive the current connection state whenever we receive status updates from Carabiner.void
connect()
Try to establish a connection to Carabiner.void
disconnect()
Closes any active Carabiner connection.int
getCarabinerPort()
Gets the port number that is being used to connect to Carabiner.Set<DisconnectionListener>
getDisconnectionListeners()
Get the set of disconnection listeners that are currently registered.static Carabiner
getInstance()
Get the singleton instance of this class.int
getLatency()
Get the estimated latency in milliseconds between an actual beat played on a CDJ and when we receive the packet.State
getState()
Get the current synchronization state.Set<StateListener>
getStateListeners()
Get the set of state listeners that are currently registered.boolean
getSyncToBars()
Check whether we should synchronize the Ableton Link and Pioneer timelines at the level of entire measures, rather than individual beats.boolean
isActive()
Check whether there is currently an active connection to a Carabiner daemon, so synchronization is possible.boolean
isSyncEnabled()
Check whether we have an active connection and are in any sync mode other thanSyncMode.OFF
.boolean
isTempoValid(double bpm)
Checks whether a tempo is a reasonable number of beats per minute.void
lockTempo(double bpm)
Starts holding the tempo of the Ableton Link session to the specified number of beats per minute.void
probeAbletonBeatAtTime(long beatMilliseconds)
Find out what beat falls at the specified time in the link timeline, assuming 4 beats per bar since we are also dealing with Pro DJ Link, and taking into account the configured latency (seesetLatency(int)
).void
probeAbletonBeatAtTime(long beatMilliseconds, int beatWithinBar)
Find out what beat falls at the specified time in the link timeline, assuming 4 beats per bar since we are also dealing with Pro DJ Link, and taking into account the configured latency (seesetLatency(int)
).void
removeDisconnectionListener(DisconnectionListener listener)
Removes the specified disconnection listener so it no longer receives notifications when we close our Carabiner connection.void
removeStateListener(StateListener listener)
Removes the specified state listener so it no longer receives connection state updates when we receive status updates from Carabiner.void
setAbletonLinkTempo(double bpm)
Sets the Ableton Link session tempo to the specified number of beats per minute, unless it is already close enough (within 0.005 beats per minute).void
setCarabinerPort(int port)
Set the port number to be used to connect to Carabiner.void
setLatency(int latency)
Sets the estimated latency in milliseconds between an actual beat played on a CDJ and when we receive the packet.void
setSyncMode(SyncMode mode)
Validates that the desired mode is compatible with the current state, and if so, updates our state to put us in that mode and performs any necessary synchronization.void
setSyncToBars(boolean syncToBars)
Set whether we should synchronize the Ableton Link and Pioneer timelines at the level of entire measures, rather than individual beats.void
startAbletonTransport()
Tell Carabiner to start the Link session playing immediately, for any participants using Start/Stop Sync.void
startAbletonTransport(long microsecondTime)
Tell Carabiner to start the Link session playing at the specified future moment, for any participants using Start/Stop Sync.void
stopAbletonTransport()
Tell Carabiner to stop the Link session playing immediately, for any participants using Start/Stop Sync.void
stopAbletonTransport(long microsecondTime)
Tell Carabiner to stop the Link session playing at the specified future moment, for any participants using Start/Stop Sync.void
syncAbletonLink(boolean enabled)
Controls whether the Ableton Link session timeline is tied to the tempo and beat grid of the Pro DJ Link devices.void
unlockTempo()
Allow the tempo of the Ableton Link session to be controlled by other participants.
-
-
-
Method Detail
-
getInstance
@API(status=MAINTAINED) public static Carabiner getInstance()
Get the singleton instance of this class.- Returns:
- the only instance of this class that exists.
-
isActive
@API(status=MAINTAINED) public boolean isActive()
Check whether there is currently an active connection to a Carabiner daemon, so synchronization is possible.- Returns:
true
if we are connected to a Carabiner daemon and can synchronize tempos.
-
isSyncEnabled
@API(status=MAINTAINED) public boolean isSyncEnabled()
Check whether we have an active connection and are in any sync mode other thanSyncMode.OFF
.- Returns:
true
if some form of synchronization is taking place.
-
setCarabinerPort
@API(status=MAINTAINED) public void setCarabinerPort(int port)
Set the port number to be used to connect to Carabiner. Can only be called when not connected.- Parameters:
port
- a TCP port number, which must be between 1 and 65,535.- Throws:
IllegalStateException
- if called while connected to a Carabiner daemonIllegalArgumentException
- if port is less than 1 or more than 65,535
-
getCarabinerPort
@API(status=MAINTAINED) public int getCarabinerPort()
Gets the port number that is being used to connect to Carabiner.- Returns:
- a TCP port number, between 1 and 65,535
-
setLatency
@API(status=MAINTAINED) public void setLatency(int latency)
Sets the estimated latency in milliseconds between an actual beat played on a CDJ and when we receive the packet. Negative values mean we are receiving the packets before the actual beats occur.- Parameters:
latency
- estimated latency in milliseconds until we receive packets reporting a beat has occurred
-
getLatency
@API(status=MAINTAINED) public int getLatency()
Get the estimated latency in milliseconds between an actual beat played on a CDJ and when we receive the packet. Negative values mean we are receiving the packets before the actual beats occur.- Returns:
- estimated latency in milliseconds until we receive packets reporting a beat has occurred
-
setSyncToBars
@API(status=MAINTAINED) public void setSyncToBars(boolean syncToBars)
Set whether we should synchronize the Ableton Link and Pioneer timelines at the level of entire measures, rather than individual beats.- Parameters:
syncToBars
- whentrue
, synchronization will be at the level of musical bars rather than beats
-
getSyncToBars
@API(status=MAINTAINED) public boolean getSyncToBars()
Check whether we should synchronize the Ableton Link and Pioneer timelines at the level of entire measures, rather than individual beats.- Returns:
- an indication of whether synchronization will be at the level of musical bars rather than beats
-
addStateListener
@API(status=MAINTAINED) public void addStateListener(StateListener listener)
Adds the specified state listener to receive the current connection state whenever we receive status updates from Carabiner. Iflistener
isnull
or already present in the list of registered listeners, no exception is thrown, and no action is performed.To reduce latency, listeners are called on the same thread which is receiving updates from Carabiner. If you are going to do anything that takes significant time or might block, you must do so on another thread. If you are going to interact with user interface objects in response to such events, you need to use
javax.swing.SwingUtilities.invokeLater(Runnable)
to do so on the Event Dispatch Thread.- Parameters:
listener
- the state listener to add
-
removeStateListener
@API(status=MAINTAINED) public void removeStateListener(StateListener listener)
Removes the specified state listener so it no longer receives connection state updates when we receive status updates from Carabiner.If
listener
isnull
or not present in the list of registered listeners, no exception is thrown and no action is performed.- Parameters:
listener
- the state listener to remove
-
getStateListeners
@API(status=MAINTAINED) public Set<StateListener> getStateListeners()
Get the set of state listeners that are currently registered.- Returns:
- the currently registered state listeners
-
getState
@API(status=MAINTAINED) public State getState()
Get the current synchronization state.- Returns:
- the current configuration and state of synchronization
-
addDisconnectionListener
@API(status=MAINTAINED) public void addDisconnectionListener(DisconnectionListener listener)
Adds the specified disconnection listener to be notified when we close our Carabiner connection. Iflistener
isnull
or already present in the list of registered listeners, no exception is thrown, and no action is performed.To reduce latency, listeners are called on the same thread which is receiving updates from Carabiner. If you are going to do anything that takes significant time or might block, you must do so on another thread. If you are going to interact with user interface objects in response to such events, you need to use
javax.swing.SwingUtilities.invokeLater(Runnable)
to do so on the Event Dispatch Thread.- Parameters:
listener
- the disconnection listener to add
-
removeDisconnectionListener
@API(status=MAINTAINED) public void removeDisconnectionListener(DisconnectionListener listener)
Removes the specified disconnection listener so it no longer receives notifications when we close our Carabiner connection.If
listener
isnull
or not present in the list of registered listeners, no exception is thrown and no action is performed.- Parameters:
listener
- the disconnection listener to remove
-
getDisconnectionListeners
@API(status=MAINTAINED) public Set<DisconnectionListener> getDisconnectionListeners()
Get the set of disconnection listeners that are currently registered.- Returns:
- the currently registered disconnection listeners
-
disconnect
@API(status=MAINTAINED) public void disconnect()
Closes any active Carabiner connection. The run loop will notice that its run ID is no longer current, and gracefully terminate, closing its socket without processing any more responses. Also shuts down the embedded Carabiner process if we started it.
-
connect
@API(status=MAINTAINED) public void connect() throws IOException
Try to establish a connection to Carabiner. Does nothing if we already have one. First checks to see if there is already an independently managed instance of Carabiner running on the configured port (seesetCarabinerPort(int)
), and if so, simply uses that. Otherwise, checks whether we are on a platform where we can install and run our own temporary copy of Carabiner. If so, tries to do that and connect to it.A successful return indicates we are now connected to Carabiner. Sets up a background thread to reject the connection if we have not received an initial status report from the Carabiner daemon within a second of opening it.
- Throws:
IOException
- if there is a problem opening the connection.
-
isTempoValid
@API(status=MAINTAINED) public boolean isTempoValid(double bpm)
Checks whether a tempo is a reasonable number of beats per minute. Ableton Link supports the range 20 to 999 BPM. If you want something outside that range, pick the closest multiple or fraction; for example for 15 BPM, propose 30 BPM.- Parameters:
bpm
- a tempo in beats per minute.- Returns:
- whether that tempo can be used with Ableton Link.
-
lockTempo
@API(status=MAINTAINED) public void lockTempo(double bpm) throws IOException
Starts holding the tempo of the Ableton Link session to the specified number of beats per minute.- Parameters:
bpm
- the desired tempo in beats per minute.- Throws:
IllegalArgumentException
- if bpm is outside the range 20 to 999 BPMIllegalStateException
- if the current sync mode isSyncMode.OFF
IOException
- if there is a problem communicating with Carabiner
-
unlockTempo
@API(status=MAINTAINED) public void unlockTempo()
Allow the tempo of the Ableton Link session to be controlled by other participants.
-
probeAbletonBeatAtTime
@API(status=EXPERIMENTAL) public void probeAbletonBeatAtTime(long beatMilliseconds) throws IOException
Find out what beat falls at the specified time in the link timeline, assuming 4 beats per bar since we are also dealing with Pro DJ Link, and taking into account the configured latency (seesetLatency(int)
).When the response comes, if we are configured to be the tempo master, we will nudge the link timeline the smallest distance possible so that it had a beat at the same time.
To align musical bars as well, use
probeAbletonBeatAtTime(long, int)
.- Parameters:
beatMilliseconds
- the time (according to the system monotonic clock) at which a beat has been received from Pro DJ Link- Throws:
IOException
- if there is a problem talking to the Carabiner daemon
-
probeAbletonBeatAtTime
@API(status=EXPERIMENTAL) public void probeAbletonBeatAtTime(long beatMilliseconds, int beatWithinBar) throws IOException
Find out what beat falls at the specified time in the link timeline, assuming 4 beats per bar since we are also dealing with Pro DJ Link, and taking into account the configured latency (seesetLatency(int)
).When the response comes, if we are configured to be the tempo master, we will nudge the link timeline the smallest distance possible so that it had a beat at the same time.
To align beats only, use
probeAbletonBeatAtTime(long)
.- Parameters:
beatMilliseconds
- the time (according to the system monotonic clock) at which a beat has been received from Pro DJ LinkbeatWithinBar
- the beat number (ranging from 1 to 4) that was assigned to the beat- Throws:
IOException
- if there is a problem talking to the Carabiner daemon
-
startAbletonTransport
@API(status=MAINTAINED) public void startAbletonTransport() throws IOException
Tell Carabiner to start the Link session playing immediately, for any participants using Start/Stop Sync. To start it at a particular point on the timeline, usestartAbletonTransport(long)
.- Throws:
IOException
- if there is a problem talking to the Carabiner daemon
-
startAbletonTransport
@API(status=MAINTAINED) public void startAbletonTransport(long microsecondTime) throws IOException
Tell Carabiner to start the Link session playing at the specified future moment, for any participants using Start/Stop Sync. To start it immediately, usestartAbletonTransport()
.- Parameters:
microsecondTime
- the time relative to the system monotonic clock at which you would like playback to begin- Throws:
IOException
- if there is a problem talking to the Carabiner daemon
-
stopAbletonTransport
@API(status=MAINTAINED) public void stopAbletonTransport() throws IOException
Tell Carabiner to stop the Link session playing immediately, for any participants using Start/Stop Sync. To start it at a particular point on the timeline, usestopAbletonTransport(long)
.- Throws:
IOException
- if there is a problem talking to the Carabiner daemon
-
stopAbletonTransport
@API(status=MAINTAINED) public void stopAbletonTransport(long microsecondTime) throws IOException
Tell Carabiner to stop the Link session playing at the specified future moment, for any participants using Start/Stop Sync. To stop it immediately, usestartAbletonTransport()
.- Parameters:
microsecondTime
- the time relative to the system monotonic clock at which you would like playback to end- Throws:
IOException
- if there is a problem talking to the Carabiner daemon
-
syncAbletonLink
@API(status=MAINTAINED) public void syncAbletonLink(boolean enabled)
Controls whether the Ableton Link session timeline is tied to the tempo and beat grid of the Pro DJ Link devices. Also reflects that in the sync state of theVirtualCdj
so it can be seen on the DJ Link network. Finally, if our Sync mode isSyncMode.PASSIVE
orSyncMode.FULL
, unless we are the tempo master, start tying the Ableton Link session timeline to the Pioneer DJ Link tempo master.- Parameters:
enabled
- specifies whether Ableton Link be tied to Pioneer DJ Link
-
abletonLinkIsMaster
@API(status=MAINTAINED) public void abletonLinkIsMaster(boolean enabled) throws IOException
Controls whether the Ableton link session timeline should be the tempo master for the Pro DJ Link devices. Has no effect if we are not in a compatible sync mode (seesetSyncMode(SyncMode)
).- Parameters:
enabled
- specifies whether the Ableton Link session should be tempo master if possible- Throws:
IOException
- if there is a problem communicating with the Carabiner daemon
-
setSyncMode
@API(status=MAINTAINED) public void setSyncMode(SyncMode mode) throws IOException
Validates that the desired mode is compatible with the current state, and if so, updates our state to put us in that mode and performs any necessary synchronization. Choices are:SyncMode.OFF
: No synchronization is attempted.SyncMode.MANUAL
: External code will be callinglockTempo(double)
andunlockTempo()
to manipulate the Ableton Link session timeline.SyncMode.PASSIVE
: Ableton Link always follows the Pro DJ Link network, and we do not attempt to control other Pro DJ Link players.SyncMode.FULL
: Bidirectional synchronization occurs, determined by the Master and Sync state of players on the Pro DJ Link network, including Beat Link’sVirtualCdj
, which stands in for the Ableton Link session.- Parameters:
mode
- the sync mode that is desired- Throws:
IllegalStateException
- if our current state is incompatible with the desired sync modeIOException
- if there is a problem communicating with the Carabiner daemon
-
setAbletonLinkTempo
@API(status=MAINTAINED) public void setAbletonLinkTempo(double bpm) throws IOException
Sets the Ableton Link session tempo to the specified number of beats per minute, unless it is already close enough (within 0.005 beats per minute).- Parameters:
bpm
- the desired tempo, which must be valid for Ableton Link (between 20 and 999 beats per minute)- Throws:
IllegalStateException
- if we are not connected to a Carabiner daemonIllegalArgumentException
- if the tempo is out of range for Ableton LinkIOException
- if there is a problem communicating with the Carabiner daemon
-
-