code: public synchronized void start() throws Exception {
          if (!isRunning()) {
              ConnectionManager.getInstance().addLifecycleListener(lifecycleListener);
              ConnectionManager.getInstance().start();
              DeviceFinder.getInstance().addDeviceAnnouncementListener(announcementListener);
              MetadataFinder.getInstance().addLifecycleListener(lifecycleListener);
              MetadataFinder.getInstance().start();
              MetadataFinder.getInstance().addTrackMetadataListener(metadataListener);
              MetadataFinder.getInstance().addMountListener(mountListener);
              queueHandler = new Thread(new Runnable() {
                  @Override
                  public void run() {
                      while (isRunning()) {
                          try {
                              handleUpdate(pendingUpdates.take());
                          } catch (InterruptedException e) {
                              // Interrupted due to MetadataFinder shutdown, presumably
                          } catch (Throwable t) {
                              logger.error("Problem processing metadata update", t);
                          }
                      }
                  }
              });
              running.set(true);
              queueHandler.start();
              deliverLifecycleAnnouncement(logger, true);
              primeCache();
          }
      }
docs: <p>Start finding waveforms for all active players. Starts the {@link MetadataFinder} if it is not already
  running, because we need it to send us metadata updates to notice when new tracks are loaded. This in turn
  starts the {@link DeviceFinder}, so we can keep track of the comings and goings of players themselves.
  We also start the {@link ConnectionManager} in order to make queries to obtain waveforms.</p>
  
  @throws Exception if there is a problem starting the required components