Class 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 than SyncMode.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 (see setLatency(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 (see setLatency(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 than SyncMode.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 daemon
        IllegalArgumentException - 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 - when true, 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. If listener is null 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 is null 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. If listener is null 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 is null 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 (see setCarabinerPort(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 BPM
        IllegalStateException - if the current sync mode is SyncMode.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 (see setLatency(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 (see setLatency(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 Link
        beatWithinBar - 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, use startAbletonTransport(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, use startAbletonTransport().
        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, use stopAbletonTransport(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, use startAbletonTransport().
        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 the VirtualCdj so it can be seen on the DJ Link network. Finally, if our Sync mode is SyncMode.PASSIVE or SyncMode.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 (see setSyncMode(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 calling lockTempo(double) and unlockTempo() 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’s VirtualCdj, 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 mode
        IOException - 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 daemon
        IllegalArgumentException - if the tempo is out of range for Ableton Link
        IOException - if there is a problem communicating with the Carabiner daemon