/** * @param source * @param oldScalarMap The previous ScalarMap of the ScalarMapAdapter. May be <code>null</code>. * @return The controlling ScalarMapAdapter of the display. * @throws RemoteException * @throws VisADException */ protected final synchronized ScalarMapAdapter accept( ScalarMapAdapter source, ScalarMap oldScalarMap) throws VisADException, RemoteException { ScalarMapAdapter adapter; if (oldScalarMap != null) { adapter = (ScalarMapAdapter) map.get(oldScalarMap); if ((adapter != null) && (adapter == source)) { map.remove(oldScalarMap); changed = true; } } ScalarMap newScalarMap = source.getScalarMap(); adapter = (ScalarMapAdapter) map.get(newScalarMap); if (adapter != null) { source.duplicate(adapter); } else { adapter = source; map.put(newScalarMap, source); changed = true; } if (changed) { updater.update(); } return adapter; }
/** * Remove an adapter * * @param adapter adapter to remove */ public final synchronized void remove(ScalarMapAdapter adapter) { adapter.removePropertyChangeListener(adapter.SCALAR_MAP, listener); ScalarMap scalarMap = adapter.getScalarMap(); ScalarMapAdapter source = (ScalarMapAdapter) map.get(scalarMap); if ((source != null) && (source == adapter)) { map.remove(scalarMap); changed = true; updater.update(); } }
/** * 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<Boolean></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; }
/** {@inheritDoc} */ @Override public void setProperty(String propertyName, Object value) { if (value == null) properties.remove(propertyName); else properties.put(propertyName, value); }