Class MetadataFinder


  • 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.

    Author:
    James Elliott
    • Field Detail

      • MENU_TIMEOUT

        public static final int MENU_TIMEOUT
        How many seconds are we willing to wait to lock the database client for menu operations.
        See Also:
        Constant Field Values
    • Method Detail

      • requestMetadataFrom

        public TrackMetadata requestMetadataFrom​(CdjStatus status)
        Given a status update from a CDJ, find the metadata for the track that it has loaded, if any. If there is an appropriate metadata cache, will use that, otherwise makes a query to the players dbserver.
        Parameters:
        status - the CDJ status update that will be used to determine the loaded track and ask the appropriate player for metadata about it
        Returns:
        the metadata that was obtained, if any
      • requestMetadataFrom

        public TrackMetadata requestMetadataFrom​(DataReference track,
                                                 CdjStatus.TrackType trackType)
        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.
        Parameters:
        track - uniquely identifies the track whose metadata is desired
        trackType - identifies the type of track being requested, which affects the type of metadata request message that must be used
        Returns:
        the metadata, if any
      • requestPlaylistItemsFrom

        public List<Message> requestPlaylistItemsFrom​(int player,
                                                      CdjStatus.TrackSourceSlot slot,
                                                      int sortOrder,
                                                      int playlistOrFolderId,
                                                      boolean folder)
                                               throws Exception
        Ask the specified player's dbserver 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.
        Parameters:
        player - the player number whose playlist entries are of interest
        slot - the slot in which the playlist can be found
        sortOrder - the order in which responses should be sorted, 0 for default, see Section 6.11.1 of the Packet Analysis document for details
        playlistOrFolderId - the database ID of the desired playlist or folder
        folder - indicates whether we are asking for the contents of a folder or playlist
        Returns:
        the items that are found in the specified playlist or folder; they will be tracks if we are asking for a playlist, or playlists and folders if we are asking for a folder
        Throws:
        Exception - if there is a problem obtaining the playlist information
      • isRunning

        public boolean isRunning()
        Check whether we are currently running. Unless we are in passive mode, we will also automatically request metadata from the appropriate player when a new track is loaded that is not found in the hot cache or an attached metadata cache file.
        Specified by:
        isRunning in class LifecycleParticipant
        Returns:
        true if track metadata is being kept track of for all active players
        See Also:
        isPassive()
      • isPassive

        public boolean isPassive()
        Check whether we are configured to use metadata only from caches, never actively requesting it from a player. Note that this will implicitly mean all of the metadata-related finders (ArtFinder, BeatGridFinder, and WaveformFinder) are in passive mode as well, because their activity is triggered by the availability of new track metadata.
        Returns:
        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 assigned
      • setPassive

        public void setPassive​(boolean passive)
        Set whether we are configured to use metadata only from caches, never actively requesting it from a player. Note that this will implicitly put all of the metadata-related finders (ArtFinder, BeatGridFinder, and WaveformFinder) into a passive mode as well, because their activity is triggered by the availability of new track metadata.
        Parameters:
        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 assigned
      • getLoadedTracks

        public 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.
        Returns:
        the track information reported by all current players, including any tracks loaded in their hot cue slots
        Throws:
        IllegalStateException - if the MetadataFinder is not running
      • getLatestMetadataFor

        public TrackMetadata getLatestMetadataFor​(int player)
        Look up the track metadata we have for the track loaded in the main deck of a given player number.
        Parameters:
        player - the device number whose track metadata for the playing track is desired
        Returns:
        information about the track loaded on that player, if available
        Throws:
        IllegalStateException - if the MetadataFinder is not running
      • getLatestMetadataFor

        public TrackMetadata getLatestMetadataFor​(DeviceUpdate update)
        Look up the track metadata we have for a given player, identified by a status update received from that player.
        Parameters:
        update - a status update from the player for which track metadata is desired
        Returns:
        information about the track loaded on that player, if available
        Throws:
        IllegalStateException - if the MetadataFinder is not running
      • attachMetadataCache

        public void attachMetadataCache​(SlotReference slot,
                                        File file)
                                 throws IOException
        Attach a metadata cache file to a particular player media slot, so the cache will be used instead of querying the player for metadata. This supports operation with metadata during shows where DJs are using all four player numbers and heavily cross-linking between them. If the media is ejected from that player slot, the cache will be detached.
        Parameters:
        slot - the media slot to which a meta data cache is to be attached
        file - the metadata cache to be attached
        Throws:
        IOException - if there is a problem reading the cache file
        IllegalArgumentException - if an invalid player number or slot is supplied
        IllegalStateException - if the metadata finder is not running
      • detachMetadataCache

        public 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.
        Parameters:
        slot - the media slot to which a meta data cache is to be attached
      • addAutoAttachCacheFile

        public void addAutoAttachCacheFile​(File metadataCacheFile)
                                    throws IOException
        Add a metadata cache file to the set being automatically attached when matching media is inserted. Will try to auto-attach the new file to any already-mounted media. Adding a file that is already present in the set will have no effect, and if the file being added was created from the same media as any existing file in the set, the new file will replace the existing one, since only one file can match the media when it mounts. (Tracking of source media was only added in version 0.4.1.)
        Parameters:
        metadataCacheFile - the file to be auto-attached when matching media is seen on the network
        Throws:
        IOException - if the specified file cannot be read or is not a valid metadata cache
      • removeAutoAttacheCacheFile

        public void removeAutoAttacheCacheFile​(File metadataCacheFile)
        Remove a metadata cache file from the set being automatically attached when matching media is inserted. This will not detach it from a slot if it has already been attached; for that you need to use detachMetadataCache(SlotReference).
        Parameters:
        metadataCacheFile - the file that should no longer be auto-attached when matching media is seen
      • getAutoAttachCacheFiles

        public 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.
        Returns:
        the current auto-attache cache files, sorted by name
      • setAutoAttachProbeCount

        public void setAutoAttachProbeCount​(int numTracks)
        Set the number of tracks examined when considering auto-attaching a metadata cache file to a newly-mounted media database. The more examined, the more confident we can be in the cache matching the media, but the longer it will take and the more metadata queries will be required. The smallest legal value is 1. This value is only used for metadata caches created by versions older than 0.4.1, because they lacked the ability to match by the details of the media database itself.
        Parameters:
        numTracks - the number of tracks that will be compared between the cache files and the media in the player
      • getAutoAttachProbeCount

        public int getAutoAttachProbeCount()
        Get the number of tracks examined when considering auto-attaching a metadata cache file to a newly-mounted media database. The more examined, the more confident we can be in the cache matching the media, but the longer it will take and the more metadata queries will be required. This value is only used for metadata caches created by versions older than 0.4.1, because they lacked the ability to match by the details of the media database itself.
        Returns:
        the number of tracks that will be compared between the cache files and the media in the player
      • getMetadataCache

        public MetadataCache getMetadataCache​(SlotReference slot)
        Finds the metadata cache file assigned to a particular player media slot, if any.
        Parameters:
        slot - the media slot to which a meta data cache is to be attached
        Returns:
        the metadata cache for that player and slot, or null if no cache has been attached
      • getMountedMediaSlots

        public Set<SlotReference> getMountedMediaSlots()
        Returns the set of media slots on the network that currently have media mounted in them. Note that computers running rekordbox are included; their collections are valid media databases to explore with the MenuLoader, and they are valid as SlotReference arguments to tell players to load tracks from.
        Returns:
        the slots with media currently available on the network, including rekordbox instances
      • getMountedMediaDetails

        public Collection<MediaDetails> getMountedMediaDetails()
        Get the details we know about all mounted media.
        Returns:
        the media details the Virtual CDJ has been able to find for us about the mounted slots.
      • getMediaDetailsFor

        public MediaDetails getMediaDetailsFor​(SlotReference slot)
        Look up the details we know about the media mounted in a particular slot
        Parameters:
        slot - the slot whose media is of interest
        Returns:
        the details, or null if we don't have any
      • addMountListener

        public void addMountListener​(MountListener listener)
        Adds the specified mount update listener to receive updates when media is mounted or unmounted by any player. If listener is null or already present in the set of registered listeners, no exception is thrown and no action is performed.

        Note that at the time a mount is detected, we will not yet know any details about the mounted media. If listener also implements MediaDetailsListener, then as soon as the media details have been reported by the mounting player, MediaDetailsListener.detailsAvailable(MediaDetails) will be called with them.

        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.

        Parameters:
        listener - the mount update listener to add
      • removeMountListener

        public 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. If listener is null or not present in the set of registered listeners, no exception is thrown and no action is performed.
        Parameters:
        listener - the mount update listener to remove
      • getMountListeners

        public Set<MountListener> getMountListeners()
        Get the set of currently-registered mount update listeners.
        Returns:
        the listeners that are currently registered for mount updates
      • addCacheListener

        public void addCacheListener​(MetadataCacheListener listener)
        Adds the specified cache update listener to receive updates when a metadata cache is attached or detached. If 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.

        Parameters:
        listener - the cache update listener to add
      • removeCacheListener

        public 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. If listener is null or not present in the set of registered listeners, no exception is thrown and no action is performed.
        Parameters:
        listener - the cache update listener to remove
      • getCacheListeners

        public Set<MetadataCacheListener> getCacheListeners()
        Get the set of currently-registered metadata cache update listeners.
        Returns:
        the listeners that are currently registered for metadata cache updates
      • addTrackMetadataListener

        public void addTrackMetadataListener​(TrackMetadataListener listener)
        Adds the specified track metadata listener to receive updates when the track metadata for a player changes. If 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.

        Parameters:
        listener - the track metadata update listener to add
      • removeTrackMetadataListener

        public 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. If listener is null or not present in the set of registered listeners, no exception is thrown and no action is performed.
        Parameters:
        listener - the track metadata update listener to remove
      • getTrackMetadataListeners

        public Set<TrackMetadataListener> getTrackMetadataListeners()
        Get the set of currently-registered track metadata update listeners.
        Returns:
        the listeners that are currently registered for track metadata updates
      • addMetadataProvider

        public void addMetadataProvider​(MetadataProvider provider)
        Adds a metadata provider that will be consulted to see if it can provide metadata for newly-loaded tracks before we try to retrieve it from the players or our cache files. This function will immediately call MetadataProvider.supportedMedia() and will only consult the provider for tracks loaded from the media mentioned in the response. The function is only called once, when initially adding the provider, so if the set of supported media changes, you will need to remove the provider and re-add it. Providers that can provide metadata for all media can simply return an empty list of supported media, and they will always be consulted. Only do this if they truly can always provide metadata, or you will slow down the lookup process by having them frequently called in vain.
        Parameters:
        provider - the object that can supply metadata about tracks
        Throws:
        IllegalArgumentException - if you pass in a MetadataCache.
      • removeMetadataProvider

        public void removeMetadataProvider​(MetadataProvider provider)
        Removes a metadata provider so it will no longer be consulted to provide metadata for tracks loaded from any media.
        Parameters:
        provider - the metadata provider to remove.
      • getMetadataProviders

        public Set<MetadataProvider> getMetadataProviders​(MediaDetails sourceMedia)
        Get the set of metadata providers that can offer metadata for tracks loaded from the specified media.
        Parameters:
        sourceMedia - the media whose metadata providers are desired, or null to get the set of metadata providers that can offer metadata for all media.
        Returns:
        any registered metadata providers that reported themselves as supporting tracks from that media
      • start

        public void start()
                   throws Exception
        Start finding track metadata for all active players. Starts the 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.
        Throws:
        Exception - if there is a problem starting the required components
      • stop

        public void stop()
        Stop finding track metadata for all active players.
      • getInstance

        public static MetadataFinder getInstance()
        Get the singleton instance of this class.
        Returns:
        the only instance of this class which exists.