Example #1
0
  /**
   * Create preview component.
   *
   * @param type type
   * @param comboBox the options.
   * @param prefSize the preferred size
   * @return the component.
   */
  private static Component createPreview(int type, final JComboBox comboBox, Dimension prefSize) {
    JComponent preview = null;

    if (type == DeviceConfigurationComboBoxModel.AUDIO) {
      Object selectedItem = comboBox.getSelectedItem();

      if (selectedItem instanceof AudioSystem) {
        AudioSystem audioSystem = (AudioSystem) selectedItem;

        if (!NoneAudioSystem.LOCATOR_PROTOCOL.equalsIgnoreCase(audioSystem.getLocatorProtocol())) {
          preview = new TransparentPanel(new GridBagLayout());
          createAudioSystemControls(audioSystem, preview);
        }
      }
    } else if (type == DeviceConfigurationComboBoxModel.VIDEO) {
      JLabel noPreview =
          new JLabel(
              NeomediaActivator.getResources().getI18NString("impl.media.configform.NO_PREVIEW"));

      noPreview.setHorizontalAlignment(SwingConstants.CENTER);
      noPreview.setVerticalAlignment(SwingConstants.CENTER);

      preview = createVideoContainer(noPreview);
      preview.setPreferredSize(prefSize);

      Object selectedItem = comboBox.getSelectedItem();
      CaptureDeviceInfo device = null;
      if (selectedItem instanceof DeviceConfigurationComboBoxModel.CaptureDevice)
        device = ((DeviceConfigurationComboBoxModel.CaptureDevice) selectedItem).info;

      Exception exception;
      try {
        createVideoPreview(device, preview);
        exception = null;
      } catch (IOException ex) {
        exception = ex;
      } catch (MediaException ex) {
        exception = ex;
      }
      if (exception != null) {
        logger.error("Failed to create preview for device " + device, exception);
        device = null;
      }
    }

    return preview;
  }
  /**
   * Creates an SCAudioClip from the given URI and adds it to the list of available audio-s.
   *
   * @param uri the path where the audio file could be found
   * @param playback use or not the playback device.
   * @return a newly created <tt>SCAudioClip</tt> from <tt>uri</tt>
   */
  public SCAudioClip createAudio(String uri, boolean playback) {
    SCAudioClip audio;

    synchronized (audiosSyncRoot) {
      final AudioKey key = new AudioKey(uri, playback);

      /*
       * While we want to reuse the SCAudioClip instances, they may be
       * used by a single user at a time. That's why we'll forget about
       * them while they are in use and we'll reclaim them when they are
       * no longer in use.
       */
      audio = (audios == null) ? null : audios.remove(key);

      if (audio == null) {
        try {
          AudioSystem audioSystem = getDeviceConfiguration().getAudioSystem();

          if (audioSystem == null) {
            audio = new JavaSoundClipImpl(uri, this);
          } else if (NoneAudioSystem.LOCATOR_PROTOCOL.equalsIgnoreCase(
              audioSystem.getLocatorProtocol())) {
            audio = null;
          } else {
            audio = new AudioSystemClipImpl(uri, this, audioSystem, playback);
          }
        } catch (Throwable t) {
          if (t instanceof ThreadDeath) throw (ThreadDeath) t;
          else {
            /*
             * Could not initialize a new SCAudioClip instance to be
             * played.
             */
            return null;
          }
        }
      }

      /*
       * Make sure that the SCAudioClip will be reclaimed for reuse when
       * it is no longer in use.
       */
      if (audio != null) {
        if (audios == null) audios = new HashMap<AudioKey, SCAudioClip>();

        /*
         * We have to return in the Map which was active at the time the
         * SCAudioClip was initialized because it may have become
         * invalid if the playback or notify audio device changed.
         */
        final Map<AudioKey, SCAudioClip> finalAudios = audios;
        final SCAudioClip finalAudio = audio;

        audio =
            new SCAudioClip() {
              /**
               * Evaluates a specific <tt>loopCondition</tt> as defined by {@link
               * SCAudioClip#play(int,Callable)}.
               *
               * @param loopCondition the <tt>Callable&lt;Boolean&gt;</tt> which represents the
               *     <tt>loopCondition</tt> to be evaluated
               * @return {@link Boolean#FALSE} if <tt>loopCondition</tt> is <tt>null</tt>;
               *     otherwise, the value returned by invoking {@link Callable#call()} on the
               *     specified <tt>loopCondition</tt>
               * @throws Exception if the specified <tt>loopCondition</tt> throws an
               *     <tt>Exception</tt>
               */
              private Boolean evaluateLoopCondition(Callable<Boolean> loopCondition)
                  throws Exception {
                /*
                 * SCAudioClip.play(int,Callable<Boolean>) is
                 * documented to play the SCAudioClip once only if
                 * the loopCondition is null. The same will be
                 * accomplished by returning Boolean.FALSE.
                 */
                return (loopCondition == null) ? Boolean.FALSE : loopCondition.call();
              }

              /**
               * {@inheritDoc}
               *
               * <p>Returns the wrapped <tt>SCAudioClip</tt> into the cache from it has earlier been
               * retrieved in order to allow its reuse.
               */
              @Override
              protected void finalize() throws Throwable {
                try {
                  synchronized (audios) {
                    finalAudios.put(key, finalAudio);
                  }
                } finally {
                  super.finalize();
                }
              }

              public void play() {
                /*
                 * SCAudioClip.play() is documented to behave as if
                 * loopInterval is negative and/or loopCondition is
                 * null. We have to take care that this instance
                 * does not get garbage collected until the
                 * finalAudio finishes playing so we will delegate
                 * to this instance's implementation of
                 * SCAudioClip.play(int,Callable<Boolean>) instead
                 * of to the finalAudio's.
                 */
                play(-1, null);
              }

              public void play(int loopInterval, final Callable<Boolean> finalLoopCondition) {
                /*
                 * We have to make sure that this instance does not
                 * get garbage collected before the finalAudio
                 * finishes playing. The argument loopCondition of
                 * the method
                 * SCAudioClip.play(int,Callable<Boolean>) will
                 * live/be referenced during that time so we will
                 * use it to hold on to this instance.
                 */
                Callable<Boolean> loopCondition =
                    new Callable<Boolean>() {
                      public Boolean call() throws Exception {
                        return evaluateLoopCondition(finalLoopCondition);
                      }
                    };

                finalAudio.play(loopInterval, loopCondition);
              }

              public void stop() {
                finalAudio.stop();
              }

              /**
               * Determines whether this audio is started i.e. a <tt>play</tt> method was invoked
               * and no subsequent <tt>stop</tt> has been invoked yet.
               *
               * @return <tt>true</tt> if this audio is started; otherwise, <tt>false</tt>
               */
              public boolean isStarted() {
                return finalAudio.isStarted();
              }
            };
      }
    }

    return audio;
  }