docs: @SuppressWarnings("WeakerAccess")
      public synchronized void stop() {
          if (isRunning()) {
              MetadataFinder.getInstance().removeTrackMetadataListener(metadataListener);
              running.set(false);
              pendingUpdates.clear();
              queueHandler.interrupt();
              queueHandler = null;
  
              // Report the loss of our waveforms, on the proper thread, outside our lock
              final Set<DeckReference> dyingPreviewCache = new HashSet<DeckReference>(previewHotCache.keySet());
              previewHotCache.clear();
              final Set<DeckReference> dyingDetailCache = new HashSet<DeckReference>(detailHotCache.keySet());
              detailHotCache.clear();
              SwingUtilities.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                      for (DeckReference deck : dyingPreviewCache) {  // Report the loss of our previews.
                          if (deck.hotCue == 0) {
                              deliverWaveformPreviewUpdate(deck.player, null);
                          }
                      }
                      for (DeckReference deck : dyingDetailCache) {  // Report the loss of our details.
                          if (deck.hotCue == 0) {
                              deliverWaveformDetailUpdate(deck.player, null);
                          }
                      }
                  }
              });
              deliverLifecycleAnnouncement(logger, false);
          }
      }