public class MetadataFinder extends LifecycleParticipant
Watches for new tracks to be loaded on players, and queries the appropriate player for the metadata information when that happens.
Maintains a hot cache of metadata about any track currently loaded in a player, either on the main playback deck, or as a hot cue, since those tracks could start playing instantly.
Can also create cache files containing metadata about either all tracks in a media library, or tracks from a
specific play list, and attach those cache files to be used instead of actually querying the player about tracks
loaded from that library. This can be used in busy performance situations where all four usable player numbers
are in use by actual players, to avoid conflicting queries yet still have useful metadata available. In such
situations, you may want to go into passive mode, using setPassive(boolean), to prevent metadata queries
about tracks that are not available from the attached metadata cache files.
| Modifier and Type | Field and Description |
|---|---|
static String |
CACHE_FORMAT_IDENTIFIER
The comment string used to identify a ZIP file as one of our metadata caches.
|
| Modifier and Type | Method and Description |
|---|---|
void |
addAutoAttachCacheFile(File metadataCacheFile)
Add a metadata cache file to the set being automatically attached when matching media is inserted.
|
void |
addCacheListener(MetadataCacheListener listener)
Adds the specified cache update listener to receive updates when a metadata cache is attached or detached.
|
void |
addMountListener(MountListener listener)
Adds the specified mount update listener to receive updates when media is mounted or unmounted by any player.
|
void |
addTrackMetadataListener(TrackMetadataListener listener)
Adds the specified track metadata listener to receive updates when the track metadata for a player changes.
|
void |
attachMetadataCache(SlotReference slot,
File cache)
Attach a metadata cache file to a particular player media slot, so the cache will be used instead of querying
the player for metadata.
|
void |
createMetadataCache(SlotReference slot,
int playlistId,
File cache)
Creates a metadata cache archive file of all tracks in the specified slot on the specified player.
|
void |
createMetadataCache(SlotReference slot,
int playlistId,
File cache,
MetadataCacheCreationListener listener)
Creates a metadata cache archive file of all tracks in the specified slot on the specified player.
|
void |
detachMetadataCache(SlotReference slot)
Removes any metadata cache file that might have been assigned to a particular player media slot, so metadata
will be looked up from the player itself.
|
List<File> |
getAutoAttachCacheFiles()
Get the metadata cache files that are currently configured to be automatically attached when matching media is
mounted in a player on the network.
|
int |
getAutoAttachProbeCount()
Get the number of tracks examined when considering auto-attaching a metadata cache file to a newly-mounted
media database.
|
CueList |
getCachedCueList(ZipFile cache,
int rekordboxId)
Look up a cue list in a metadata cache.
|
TrackMetadata |
getCachedMetadata(ZipFile cache,
DataReference track)
Look up track metadata from a cache.
|
Set<MetadataCacheListener> |
getCacheListeners()
Get the set of currently-registered metadata cache update listeners.
|
long |
getCachePauseInterval()
Check how long we pause between requesting metadata entries while building a cache to give the player
a chance to perform its other tasks.
|
int |
getCacheSourcePlaylist(ZipFile cache)
Reports the ID of the playlist that was used to create the cache, or 0 of it is an all-tracks cache.
|
int |
getCacheTrackCount(ZipFile cache)
Reports the number of tracks contained in a metadata cache.
|
List<Integer> |
getCacheTrackIds(ZipFile cache)
Returns a list of the rekordbox IDs of the tracks contained in a metadata cache.
|
static MetadataFinder |
getInstance()
Get the singleton instance of this class.
|
TrackMetadata |
getLatestMetadataFor(DeviceUpdate update)
Look up the track metadata we have for a given player, identified by a status update received from that player.
|
TrackMetadata |
getLatestMetadataFor(int player)
Look up the track metadata we have for the track loaded in the main deck of a given player number.
|
Map<DeckReference,TrackMetadata> |
getLoadedTracks()
Get the metadata of all tracks currently loaded in any player, either on the play deck, or in a hot cue.
|
ZipFile |
getMetadataCache(SlotReference slot)
Finds the metadata cache file assigned to a particular player media slot, if any.
|
Set<SlotReference> |
getMountedMediaSlots()
Returns the set of media slots on the network that currently have media mounted in them.
|
Set<MountListener> |
getMountListeners()
Get the set of currently-registered mount update listeners.
|
Set<TrackMetadataListener> |
getTrackMetadataListeners()
Get the set of currently-registered track metadata update listeners.
|
boolean |
isPassive()
Check whether we are configured to use metadata only from caches, never actively requesting it from a player.
|
boolean |
isRunning()
Check whether we are currently running.
|
ZipFile |
openMetadataCache(File cache)
Open and validate a metadata cache file.
|
void |
removeAutoAttacheCacheFile(File metadataCacheFile)
Remove a metadata cache file from the set being automatically attached when matching media is inserted.
|
void |
removeCacheListener(MetadataCacheListener listener)
Removes the specified cache update listener so that it no longer receives updates when there
are changes to the available set of metadata caches.
|
void |
removeMountListener(MountListener listener)
Removes the specified mount update listener so that it no longer receives updates when a player mounts or
unmounts media in one of its media slots.
|
void |
removeTrackMetadataListener(TrackMetadataListener listener)
Removes the specified track metadata update listener so that it no longer receives updates when track
metadata for a player changes.
|
TrackMetadata |
requestMetadataFrom(CdjStatus status)
Given a status update from a CDJ, find the metadata for the track that it has loaded, if any.
|
TrackMetadata |
requestMetadataFrom(DataReference track)
Ask the specified player for metadata about the track in the specified slot with the specified rekordbox ID,
unless we have a metadata cache available for the specified media slot, in which case that will be used instead.
|
List<Message> |
requestPlaylistItemsFrom(int player,
CdjStatus.TrackSourceSlot slot,
int sortOrder,
int playlistOrFolderId,
boolean folder)
Ask the specified player for the playlist entries of the specified playlist (if
folder is false,
or the list of playlists and folders inside the specified playlist folder (if folder is true. |
void |
setAutoAttachProbeCount(int numTracks)
Set the number of tracks examined when considering auto-attaching a metadata cache file to a newly-mounted
media database.
|
void |
setCachePauseInterval(long milliseconds)
Set how long to pause between requesting metadata entries while building a cache to give the player
a chance to perform its other tasks.
|
void |
setPassive(boolean passive)
Set whether we are configured to use metadata only from caches, never actively requesting it from a player.
|
void |
start()
Start finding track metadata for all active players.
|
void |
stop()
Stop finding track metadata for all active players.
|
String |
toString() |
addLifecycleListener, deliverLifecycleAnnouncement, ensureRunning, getLifecycleListeners, removeLifecycleListenerpublic static final String CACHE_FORMAT_IDENTIFIER
public TrackMetadata requestMetadataFrom(CdjStatus status)
status - the CDJ status update that will be used to determine the loaded track and ask the appropriate
player for metadata about itpublic TrackMetadata requestMetadataFrom(DataReference track)
track - uniquely identifies the track whose metadata is desiredpublic TrackMetadata getCachedMetadata(ZipFile cache, DataReference track)
cache - the appropriate metadata cache filetrack - identifies the track whose metadata is desirednullpublic CueList getCachedCueList(ZipFile cache, int rekordboxId)
cache - the appropriate metadata cache filerekordboxId - the track whose cue list is desirednullpublic List<Message> requestPlaylistItemsFrom(int player, CdjStatus.TrackSourceSlot slot, int sortOrder, int playlistOrFolderId, boolean folder) throws Exception
folder is false,
or the list of playlists and folders inside the specified playlist folder (if folder is true.player - the player number whose playlist entries are of interestslot - the slot in which the playlist can be foundsortOrder - the order in which responses should be sorted, 0 for default, see Section 5.10.1 of the
Packet Analysis
document for detailsplaylistOrFolderId - the database ID of the desired playlist or folderfolder - indicates whether we are asking for the contents of a folder or playlistException - if there is a problem obtaining the playlist informationpublic void createMetadataCache(SlotReference slot, int playlistId, File cache) throws Exception
slot - the slot in which the media to be cached can be foundplaylistId - the id of playlist to be cached, or 0 of all tracks should be cachedcache - the file into which the metadata cache should be writtenException - if there is a problem communicating with the player or writing the cache file.public void setCachePauseInterval(long milliseconds)
milliseconds - the delay to add between each track that gets added to the metadata cachepublic long getCachePauseInterval()
public void createMetadataCache(SlotReference slot, int playlistId, File cache, MetadataCacheCreationListener listener) throws Exception
null listener is
supplied, its MetadataCacheCreationListener.cacheCreationContinuing(TrackMetadata, int, int) method
will be called after each track is added to the cache, allowing it to display progress updates to the user,
and to continue or cancel the process by returning true or false.
Because this takes a huge amount of time relative to CDJ status updates, it can only be performed while
the MetadataFinder is in passive mode.slot - the slot in which the media to be cached can be foundplaylistId - the id of playlist to be cached, or 0 of all tracks should be cachedcache - the file into which the metadata cache should be writtenlistener - will be informed after each track is added to the cache file being created and offered
the opportunity to cancel the processException - if there is a problem communicating with the player or writing the cache filepublic boolean isRunning()
isRunning in class LifecycleParticipantisPassive()public boolean isPassive()
ArtFinder, BeatGridFinder,
and WaveformFinder) are in passive mode as well, because their activity is triggered by the availability
of new track metadata.true if only cached metadata will be used, or false if metadata will be requested from
a player if a track is loaded from a media slot to which no cache has been assignedpublic void setPassive(boolean passive)
ArtFinder, BeatGridFinder,
and WaveformFinder) into a passive mode as well, because their activity is triggered by the availability
of new track metadata.passive - true if only cached metadata will be used, or false if metadata will be requested
from a player if a track is loaded from a media slot to which no cache has been assignedpublic Map<DeckReference,TrackMetadata> getLoadedTracks()
IllegalStateException - if the MetadataFinder is not runningpublic TrackMetadata getLatestMetadataFor(int player)
player - the device number whose track metadata for the playing track is desiredIllegalStateException - if the MetadataFinder is not runningpublic TrackMetadata getLatestMetadataFor(DeviceUpdate update)
update - a status update from the player for which track metadata is desiredIllegalStateException - if the MetadataFinder is not runningpublic void attachMetadataCache(SlotReference slot, File cache) throws IOException
slot - the media slot to which a meta data cache is to be attachedcache - the metadata cache to be attachedIOException - if there is a problem reading the cache fileIllegalArgumentException - if an invalid player number or slot is suppliedIllegalStateException - if the metadata finder is not runningpublic ZipFile openMetadataCache(File cache) throws IOException
cache - the file the user wants to work withIOException - if there is a problem reading the file, or it does not contain a valid metadata cachepublic int getCacheSourcePlaylist(ZipFile cache) throws IOException
cache - the metadata cache whose contents are of interestIOException - if there is a problem reading the cache filepublic int getCacheTrackCount(ZipFile cache) throws IOException
cache - the metadata cache whose contents are of interestIOException - if there is a problem reading the cache filepublic List<Integer> getCacheTrackIds(ZipFile cache) throws IOException
cache - the metadata cache whose contents are of interestIOException - if there is a problem reading the cache filepublic void detachMetadataCache(SlotReference slot)
slot - the media slot to which a meta data cache is to be attachedpublic void addAutoAttachCacheFile(File metadataCacheFile) throws IOException
metadataCacheFile - the file to be auto-attached when matching media is seen on the networkIOException - if the specified file cannot be read or is not a valid metadata cachepublic void removeAutoAttacheCacheFile(File metadataCacheFile)
detachMetadataCache(SlotReference).metadataCacheFile - the file that should no longer be auto-attached when matching media is seenpublic List<File> getAutoAttachCacheFiles()
public void setAutoAttachProbeCount(int numTracks)
numTracks - the number of tracks that will be compared between the cache files and the media in the playerpublic int getAutoAttachProbeCount()
public ZipFile getMetadataCache(SlotReference slot)
slot - the media slot to which a meta data cache is to be attachednull if no cache
has been attachedpublic Set<SlotReference> getMountedMediaSlots()
public void addMountListener(MountListener listener)
listener is null or already present in the set of registered listeners, no exception is
thrown and no action is performed.
To reduce latency, updates are delivered to listeners directly on the thread that is receiving packets
from the network, so if you want to interact with user interface objects in listener methods, you need to use
javax.swing.SwingUtilities.invokeLater(Runnable)
to do so on the Event Dispatch Thread.
Even if you are not interacting with user interface objects, any code in the listener method
must finish quickly, or it will add latency for other listeners, and updates will back up.
If you want to perform lengthy processing of any sort, do so on another thread.
listener - the mount update listener to addpublic void removeMountListener(MountListener listener)
listener is null or not present
in the set of registered listeners, no exception is thrown and no action is performed.listener - the mount update listener to removepublic Set<MountListener> getMountListeners()
public void addCacheListener(MetadataCacheListener listener)
listener is null or already present in the set of registered listeners, no exception is
thrown and no action is performed.
To reduce latency, updates are delivered to listeners directly on the thread that is receiving packets
from the network, so if you want to interact with user interface objects in listener methods, you need to use
javax.swing.SwingUtilities.invokeLater(Runnable)
to do so on the Event Dispatch Thread.
Even if you are not interacting with user interface objects, any code in the listener method
must finish quickly, or it will add latency for other listeners, and updates will back up.
If you want to perform lengthy processing of any sort, do so on another thread.
listener - the cache update listener to addpublic void removeCacheListener(MetadataCacheListener listener)
listener is null or not present
in the set of registered listeners, no exception is thrown and no action is performed.listener - the cache update listener to removepublic Set<MetadataCacheListener> getCacheListeners()
public void addTrackMetadataListener(TrackMetadataListener listener)
listener is null or already present in the set of registered listeners, no exception is
thrown and no action is performed.
To reduce latency, updates are delivered to listeners directly on the thread that is receiving packets
from the network, so if you want to interact with user interface objects in listener methods, you need to use
javax.swing.SwingUtilities.invokeLater(Runnable)
to do so on the Event Dispatch Thread.
Even if you are not interacting with user interface objects, any code in the listener method
must finish quickly, or it will add latency for other listeners, and updates will back up.
If you want to perform lengthy processing of any sort, do so on another thread.
listener - the track metadata update listener to addpublic void removeTrackMetadataListener(TrackMetadataListener listener)
listener is null or not present
in the set of registered listeners, no exception is thrown and no action is performed.listener - the track metadata update listener to removepublic Set<TrackMetadataListener> getTrackMetadataListeners()
public void start()
throws Exception
VirtualCdj if it is not already
running, because we need it to send us device status updates to notice when new tracks are loaded; this
starts the DeviceFinder (which is also needed by the VirtualCdj) so we can keep track of
the comings and goings of players themselves. We start the ConnectionManager in order to make queries
to obtain metadata.Exception - if there is a problem starting the required componentspublic void stop()
public static MetadataFinder getInstance()
Copyright © 2016–2018 Deep Symmetry, LLC. All rights reserved.