- java.lang.Object
-
- org.deepsymmetry.beatlink.dbserver.Client
-
@API(status=STABLE) public class Client extends Object
Manages a connection to the dbserver port on a particular player, allowing queries to be sent, and their responses to be interpreted. Direct instantiation is not available outside the package, insteadConnectionManager.invokeWithClientSession(int, ConnectionManager.ClientTask, String)
must be used.- Author:
- James Elliott
-
-
Field Summary
Fields Modifier and Type Field Description static int
DEFAULT_MENU_BATCH_SIZE
The default maximum number of menu items we will request at a single time.static NumberField
GREETING_FIELD
The greeting message exchanged over a new connection consists of a 4-byte number field containing the value 1.int
posingAsPlayer
The player we are pretending to be.int
targetPlayer
The player number we are communicating with.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description static NumberField
buildRMST(int requestingPlayer, Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot)
Build the R:M:S:T parameter that begins many queries, when T=1.static NumberField
buildRMST(int requestingPlayer, Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, CdjStatus.TrackType trackType)
Build the R:M:S:T parameter that begins many queries.NumberField
buildRMST(Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot)
Build the R:M:S:T parameter that begins many queries.NumberField
buildRMST(Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, CdjStatus.TrackType trackType)
Build the R:M:S:T parameter that begins many queries.static long
getMenuBatchSize()
Ghe maximum number of menu items we will request at a single time.boolean
isConnected()
Check whether our connection is still available for use.Message
menuRequest(Message.KnownType requestType, Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, Field... arguments)
Send a request for a menu that we will retrieve items from in subsequent requests.Message
menuRequestTyped(Message.KnownType requestType, Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, CdjStatus.TrackType trackType, Field... arguments)
Send a request for a menu that we will retrieve items from in subsequent requests, when the request must reflect the actual type of track being asked about.List<Message>
renderMenuItems(Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, CdjStatus.TrackType trackType, int offset, int count)
Gather the specified range of responses for a menu request.List<Message>
renderMenuItems(Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, CdjStatus.TrackType trackType, Message availableResponse)
Gather all the responses that are available for a menu request.static void
setMenuBatchSize(int batchSize)
Set the maximum number of menu items we will request at a single time.Message
simpleRequest(Message.KnownType requestType, Message.KnownType responseType, Field... arguments)
Send a request that expects a single message as its response, then read and return that response.String
toString()
boolean
tryLockingForMenuOperations(long timeout, TimeUnit unit)
Attempt to secure exclusive access to this player for performing a menu operation, which requires multiple request/response cycles.void
unlockForMenuOperations()
Allow other threads to perform menu operations.
-
-
-
Field Detail
-
targetPlayer
@API(status=STABLE) public final int targetPlayer
The player number we are communicating with.
-
posingAsPlayer
@API(status=STABLE) public final int posingAsPlayer
The player we are pretending to be.
-
GREETING_FIELD
@API(status=STABLE) public static final NumberField GREETING_FIELD
The greeting message exchanged over a new connection consists of a 4-byte number field containing the value 1.
-
DEFAULT_MENU_BATCH_SIZE
@API(status=STABLE) public static final int DEFAULT_MENU_BATCH_SIZE
The default maximum number of menu items we will request at a single time. We are not sure what the largest safe value to use is, but 64 seems to work well for CDJ-2000 nexus players.- See Also:
- Constant Field Values
-
-
Method Detail
-
isConnected
@API(status=STABLE) public boolean isConnected()
Check whether our connection is still available for use. We will close it if there is ever a problem communicating with the dbserver.- Returns:
true
if this instance can still be used to query the connected dbserver
-
buildRMST
@API(status=STABLE) public static NumberField buildRMST(int requestingPlayer, Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot)
Build the R:M:S:T parameter that begins many queries, when T=1.
Many request messages take, as their first argument, a 4-byte value where each byte has a special meaning. The first byte is the player number of the requesting player. The second identifies the menu into which the response is being loaded, as described by
Message.MenuIdentifier
. The third specifies the media slot from which information is desired, as described byCdjStatus.TrackSourceSlot
, and the fourth byte identifies the type of track about which information is being requested; in most requests this has the value 1, which corresponds to rekordbox tracks, and this version of the function assumes that.- Parameters:
requestingPlayer
- the player number that is asking the questiontargetMenu
- the destination for the response to this queryslot
- the media library of interest for this query- Returns:
- the first argument to send with the query in order to obtain the desired information
-
buildRMST
@API(status=STABLE) public static NumberField buildRMST(int requestingPlayer, Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, CdjStatus.TrackType trackType)
Build the R:M:S:T parameter that begins many queries.
Many request messages take, as their first argument, a 4-byte value where each byte has a special meaning. The first byte is the player number of the requesting player. The second identifies the menu into which the response is being loaded, as described by
Message.MenuIdentifier
. The third specifies the media slot from which information is desired, as described byCdjStatus.TrackSourceSlot
, and the fourth byte identifies the type of track about which information is being requested; in most requests this has the value 1, which corresponds to rekordbox tracks.- Parameters:
requestingPlayer
- the player number that is asking the questiontargetMenu
- the destination for the response to this queryslot
- the media library of interest for this querytrackType
- the type of track about which information is being requested- Returns:
- the first argument to send with the query in order to obtain the desired information
-
buildRMST
@API(status=STABLE) public NumberField buildRMST(Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot)
Build the R:M:S:T parameter that begins many queries.
Many request messages take, as their first argument, a 4-byte value where each byte has a special meaning. The first byte is the player number of the requesting player. The second identifies the menu into which the response is being loaded, as described by
Message.MenuIdentifier
. The third specifies the media slot from which information is desired, as described byCdjStatus.TrackSourceSlot
, and the fourth byte identifies the type of track about which information is being requested; in most requests this has the value 1, which corresponds to rekordbox tracks, and this version of the function assumes that.- Parameters:
targetMenu
- the destination for the response to this queryslot
- the media library of interest for this query- Returns:
- the first argument to send with the query in order to obtain the desired information
-
buildRMST
@API(status=STABLE) public NumberField buildRMST(Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, CdjStatus.TrackType trackType)
Build the R:M:S:T parameter that begins many queries.
Many request messages take, as their first argument, a 4-byte value where each byte has a special meaning. The first byte is the player number of the requesting player. The second identifies the menu into which the response is being loaded, as described by
Message.MenuIdentifier
. The third specifies the media slot from which information is desired, as described byCdjStatus.TrackSourceSlot
, and the fourth byte identifies the type of track about which information is being requested; in most requests this has the value 1, which corresponds to rekordbox tracks.- Parameters:
targetMenu
- the destination for the response to this queryslot
- the media library of interest for this querytrackType
- the type of track about which information is being requested- Returns:
- the first argument to send with the query in order to obtain the desired information
-
simpleRequest
@API(status=STABLE) public Message simpleRequest(Message.KnownType requestType, Message.KnownType responseType, Field... arguments) throws IOException
Send a request that expects a single message as its response, then read and return that response.- Parameters:
requestType
- identifies what kind of request to sendresponseType
- identifies the type of response we expect, ornull
if we’ll accept anythingarguments
- The argument fields to send in the request- Returns:
- the response from the player
- Throws:
IOException
- if there is a communication problem, or if the response does not have the same transaction ID as the request.
-
menuRequest
@API(status=STABLE) public Message menuRequest(Message.KnownType requestType, Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, Field... arguments) throws IOException
Send a request for a menu that we will retrieve items from in subsequent requests. This variant works for nearly all menus, but when you are trying to request metadata for an unanalyzed (non-rekordbox) track, you need to usemenuRequestTyped(Message.KnownType, Message.MenuIdentifier, CdjStatus.TrackSourceSlot, CdjStatus.TrackType, Field...)
and specify the actual type of the track whose metadata you want to retrieve.- Parameters:
requestType
- identifies what kind of menu request to sendtargetMenu
- the destination for the response to this queryslot
- the media library of interest for this queryarguments
- the additional arguments needed, if any, to complete the request- Returns:
- the
Message.KnownType.MENU_AVAILABLE
response reporting how many items are available in the menu - Throws:
IOException
- if there is a problem communicating, or if the requested menu is not availableIllegalStateException
- iftryLockingForMenuOperations(long, TimeUnit)
was not called successfully before attempting this call
-
menuRequestTyped
@API(status=STABLE) public Message menuRequestTyped(Message.KnownType requestType, Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, CdjStatus.TrackType trackType, Field... arguments) throws IOException
Send a request for a menu that we will retrieve items from in subsequent requests, when the request must reflect the actual type of track being asked about.- Parameters:
requestType
- identifies what kind of menu request to sendtargetMenu
- the destination for the response to this queryslot
- the media library of interest for this querytrackType
- the type of track for which metadata is being requested, since this affects the request formatarguments
- the additional arguments needed, if any, to complete the request- Returns:
- the
Message.KnownType.MENU_AVAILABLE
response reporting how many items are available in the menu - Throws:
IOException
- if there is a problem communicating, or if the requested menu is not availableIllegalStateException
- iftryLockingForMenuOperations(long, TimeUnit)
was not called successfully before attempting this call
-
getMenuBatchSize
@API(status=STABLE) public static long getMenuBatchSize()
Ghe maximum number of menu items we will request at a single time. We are not sure what the largest safe value to use is, but 64 seems to work well for CDJ-2000 nexus players. Changing this will affect future calls torenderMenuItems(Message.MenuIdentifier, CdjStatus.TrackSourceSlot, CdjStatus.TrackType trackType, Message)
.- Returns:
- the maximum number of items
renderMenuItems(Message.MenuIdentifier, CdjStatus.TrackSourceSlot, CdjStatus.TrackType trackType, Message)
will request at once
-
setMenuBatchSize
@API(status=STABLE) public static void setMenuBatchSize(int batchSize)
Set the maximum number of menu items we will request at a single time. We are not sure what the largest safe value to use is, but 64 seems to work well for CDJ-2000 nexus players. Changing this will affect future calls torenderMenuItems(Message.MenuIdentifier, CdjStatus.TrackSourceSlot, CdjStatus.TrackType trackType, Message)
.- Parameters:
batchSize
- the maximum number of itemsrenderMenuItems(Message.MenuIdentifier, CdjStatus.TrackSourceSlot, CdjStatus.TrackType trackType, Message)
will request at once
-
tryLockingForMenuOperations
@API(status=STABLE) public boolean tryLockingForMenuOperations(long timeout, TimeUnit unit) throws InterruptedException
Attempt to secure exclusive access to this player for performing a menu operation, which requires multiple request/response cycles. The caller must callunlockForMenuOperations()
as soon as it is done (even if it is failing because of an exception), or no future menu operations will be possible by any other thread, unlessfalse
was returned, meaning the attempt failed.- Parameters:
timeout
- the time to wait for the lockunit
- the time unit of the timeout argument- Returns:
true
if the lock was acquired within the specified time- Throws:
InterruptedException
- if the thread is interrupted while waiting for the lock
-
unlockForMenuOperations
@API(status=STABLE) public void unlockForMenuOperations()
Allow other threads to perform menu operations. This must be called promptly, once for each time thattryLockingForMenuOperations(long, TimeUnit)
was called with atrue
return value.
-
renderMenuItems
@API(status=STABLE) public List<Message> renderMenuItems(Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, CdjStatus.TrackType trackType, Message availableResponse) throws IOException
Gather all the responses that are available for a menu request. Will involve multiple requests if the number of responses available is larger than our maximum batch size (seegetMenuBatchSize()
).- Parameters:
targetMenu
- the destination for the response to this queryslot
- the media library of interest for this querytrackType
- the type of track about which information is being requestedavailableResponse
- the response to the initial menu setup request, reporting how many responses are available, as well as the target menu we are working with- Returns:
- all the response items, using as many queries as necessary to gather them safely, and omitting all the header and footer items
- Throws:
IOException
- if there is a problem reading the menu itemsIllegalStateException
- iftryLockingForMenuOperations(long, TimeUnit)
was not called successfully before attempting this call
-
renderMenuItems
@API(status=STABLE) public List<Message> renderMenuItems(Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot, CdjStatus.TrackType trackType, int offset, int count) throws IOException
Gather the specified range of responses for a menu request. Will involve multiple requests if the number of responses requested is larger than our maximum batch size (seegetMenuBatchSize()
). It is the caller's responsibility to make sure thatoffset
andcount
remain within the legal, available menu items based on the initial menu setup request. Most use cases will be best served by the simplerrenderMenuItems(Message.MenuIdentifier, CdjStatus.TrackSourceSlot, CdjStatus.TrackType, Message)
.- Parameters:
targetMenu
- the destination for the response to this queryslot
- the media library of interest for this querytrackType
- the type of track about which information is being requestedoffset
- the first response desired (the first one available has offset 0)count
- the number of responses desired- Returns:
- the response items, using as many queries as necessary to gather them safely, and omitting all the header and footer items
- Throws:
IOException
- if there is a problem reading the menu itemsIllegalStateException
- iftryLockingForMenuOperations(long, TimeUnit)
was not called successfully before attempting this call
-
-