/**
   * Checks whether media recording is currently enabled for this <tt>Conference</tt>.
   *
   * @return <tt>true</tt> if media recording is currently enabled for this <tt>Conference</tt>,
   *     false otherwise.
   */
  public boolean isRecording() {
    boolean recording = this.recording;

    // if one of the contents is not recording, stop all recording
    if (recording) {
      synchronized (contents) {
        for (Content content : contents) {
          MediaType mediaType = content.getMediaType();

          if (!MediaType.VIDEO.equals(mediaType) && !MediaType.AUDIO.equals(mediaType)) continue;
          if (!content.isRecording()) recording = false;
        }
      }
    }
    if (this.recording != recording) setRecording(recording);

    return this.recording;
  }
  /**
   * Attempts to enable or disable media recording for this <tt>Conference</tt>.
   *
   * @param recording whether to enable or disable recording.
   * @return the state of the media recording for this <tt>Conference</tt> after the attempt to
   *     enable (or disable).
   */
  public boolean setRecording(boolean recording) {
    if (recording != this.recording) {
      if (recording) {
        // try enable recording
        if (logger.isDebugEnabled()) {
          logger.debug("Starting recording for conference with id=" + getID());
        }

        String path = getRecordingPath();
        boolean failedToStart = !checkRecordingDirectory(path);

        if (!failedToStart) {
          RecorderEventHandler handler = getRecorderEventHandler();

          if (handler == null) failedToStart = true;
        }
        if (!failedToStart) {
          EndpointRecorder endpointRecorder = getEndpointRecorder();

          if (endpointRecorder == null) {
            failedToStart = true;
          } else {
            for (Endpoint endpoint : getEndpoints()) endpointRecorder.updateEndpoint(endpoint);
          }
        }

        /*
         * The Recorders of the Contents need to share a single
         * Synchronizer, we take it from the first Recorder.
         */
        boolean first = true;
        Synchronizer synchronizer = null;

        for (Content content : contents) {
          MediaType mediaType = content.getMediaType();

          if (!MediaType.VIDEO.equals(mediaType) && !MediaType.AUDIO.equals(mediaType)) {
            continue;
          }

          if (!failedToStart) failedToStart = !content.setRecording(true, path);
          if (failedToStart) break;

          if (first) {
            first = false;
            synchronizer = content.getRecorder().getSynchronizer();
          } else {
            Recorder recorder = content.getRecorder();

            if (recorder != null) recorder.setSynchronizer(synchronizer);
          }

          content.feedKnownSsrcsToSynchronizer();
        }

        if (failedToStart) {
          recording = false;
          logger.warn("Failed to start media recording for conference " + getID());
        }
      }

      // either we were asked to disable recording, or we failed to
      // enable it
      if (!recording) {
        if (logger.isDebugEnabled()) {
          logger.debug("Stopping recording for conference with id=" + getID());
        }

        for (Content content : contents) {
          MediaType mediaType = content.getMediaType();

          if (MediaType.AUDIO.equals(mediaType) || MediaType.VIDEO.equals(mediaType)) {
            content.setRecording(false, null);
          }
        }

        if (recorderEventHandler != null) recorderEventHandler.close();
        recorderEventHandler = null;
        recordingPath = null;
        recordingDirectory = null;

        if (endpointRecorder != null) endpointRecorder.close();
        endpointRecorder = null;
      }

      this.recording = recording;
    }

    return this.recording;
  }