docs: public synchronized void stop () {
          if (isRunning()) {
              MetadataFinder.getInstance().removeTrackMetadataListener(metadataListener);
              WaveformFinder.getInstance().removeWaveformListener(waveformListener);
              BeatGridFinder.getInstance().removeBeatGridListener(beatGridListener);
              running.set(false);
              pendingUpdates.clear();
              queueHandler.interrupt();
              queueHandler = null;
  
              // Report the loss of our signatures, on the proper thread, outside our lock
              final Set<Integer> dyingSignatures = new HashSet<Integer>(signatures.keySet());
              signatures.clear();
              SwingUtilities.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                      for (Integer player : dyingSignatures) {
                          deliverSignatureUpdate(player, null);
                      }
                  }
              });
          }
          deliverLifecycleAnnouncement(logger, false);
      }