Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.media;
027
028import java.util.List;
029import javafx.beans.property.BooleanProperty;
030import javafx.beans.property.BooleanPropertyBase;
031
032import javafx.collections.ObservableList;
033import javafx.collections.FXCollections;
034
035import com.sun.javafx.collections.VetoableListDecorator;
036import com.sun.media.jfxmedia.logging.Logger;
037
038/**
039 * The <code>AudioEqualizer</code> class provides audio equalization control for
040 * a media player. It contains an {@link ObservableList} of {@link EqualizerBand}
041 * elements. Each <code> AudioEqualizer</code> instance is connected to a
042 * {@link MediaPlayer} and may be obtained using the
043 * {@link MediaPlayer#getAudioEqualizer MediaPlayer.getAudioEqualizer} method.
044 *
045 * @see MediaPlayer
046 * @see EqualizerBand
047 */
048public final class AudioEqualizer {
049
050    /**
051     * Maximum number of bands an <code>AudioEqualizer</code> may contain.
052     * In the current implementation this value is <code>64</code>.
053     */
054    public static final int MAX_NUM_BANDS = com.sun.media.jfxmedia.effects.AudioEqualizer.MAX_NUM_BANDS;
055    private com.sun.media.jfxmedia.effects.AudioEqualizer jfxEqualizer = null;
056    private final ObservableList<EqualizerBand> bands;
057    private final Object disposeLock = new Object();
058
059    /**
060     * ObservableList containing {@link EqualizerBand} elements. The content of
061     * the sequence may be changed by adding or removing {@link EqualizerBand}
062     * elements. When adding elements, the user must be prepared to catch
063     * {@link IllegalArgumentException}s because the internal list is a
064     * {@link VetoableObservableList} and any change to the list can be vetoed
065     * if a newly added instance is not valid.
066     *
067     * <p>The constraints for a valid {@link EqualizerBand} instance are:
068     * <ul>
069     * <li>{@link EqualizerBand#centerFrequencyProperty EqualizerBand.centerFrequency} &gt; 0</li>
070     * <li>{@link EqualizerBand#bandwidthProperty EqualizerBand.bandwidth} &gt; 0</li>
071     * <li>{@link EqualizerBand#MIN_GAIN EqualizerBand.MIN_GAIN} &le;
072     * {@link EqualizerBand#gainProperty EqualizerBand.gain} &le;
073     * {@link EqualizerBand#MAX_GAIN EqualizerBand.MAX_GAIN}</li>
074     * </ul>
075     * </p>
076     *
077     * <p>The default set of bands is as in the following table; all bands have
078     * unity gain (0 dB).
079     * <table border="1">
080     * <tr><th>Band Index</th><th>Center Frequency (Hz)</th><th>Bandwidth (Hz)</th></tr>
081     * <tr><td>0</td><td>32</td><td>19</td></tr>
082     * <tr><td>1</td><td>64</td><td>39</td></tr>
083     * <tr><td>2</td><td>125</td><td>78</td></tr>
084     * <tr><td>3</td><td>250</td><td>156</td></tr>
085     * <tr><td>4</td><td>500</td><td>312</td></tr>
086     * <tr><td>5</td><td>1000</td><td>625</td></tr>
087     * <tr><td>6</td><td>2000</td><td>1250</td></tr>
088     * <tr><td>7</td><td>4000</td><td>2500</td></tr>
089     * <tr><td>8</td><td>8000</td><td>5000</td></tr>
090     * <tr><td>9</td><td>16000</td><td>10000</td></tr>
091     * </table>
092     *
093     * @throws IllegalArgumentException
094     * @return ObservableList containing {@link EqualizerBand} elements.
095     */
096    public final ObservableList<EqualizerBand> getBands() {
097        return bands;
098    }
099
100    AudioEqualizer() {        
101        bands = new Bands();
102
103        // Add reasonable bands
104        bands.addAll(new EqualizerBand(32, 19, 0),
105                new EqualizerBand(64, 39, 0),
106                new EqualizerBand(125, 78, 0),
107                new EqualizerBand(250, 156, 0),
108                new EqualizerBand(500, 312, 0),
109                new EqualizerBand(1000, 625, 0),
110                new EqualizerBand(2000, 1250, 0),
111                new EqualizerBand(4000, 2500, 0),
112                new EqualizerBand(8000, 5000, 0),
113                new EqualizerBand(16000, 10000, 0));
114    }
115
116    /**
117     * Called by NativePlayer when native part is ready
118     *
119     * @param jfxEqualizer - Instance of native equalizer
120     */
121    void setAudioEqualizer(com.sun.media.jfxmedia.effects.AudioEqualizer jfxEqualizer) {
122        synchronized (disposeLock) {
123            if (this.jfxEqualizer == jfxEqualizer) {
124                return;
125            }
126            
127            if (this.jfxEqualizer != null && jfxEqualizer == null) {
128                this.jfxEqualizer.setEnabled(false);
129                for (EqualizerBand band : bands) {
130                    band.setJfxBand(null);
131                }
132                this.jfxEqualizer = null;
133                return;
134            }
135
136            this.jfxEqualizer = jfxEqualizer;
137            
138            // Propogate enabled
139            jfxEqualizer.setEnabled(isEnabled());
140            // Propogate bands
141            for (EqualizerBand band : bands) {
142                if (band.getCenterFrequency() > 0 && band.getBandwidth() > 0) {
143                    com.sun.media.jfxmedia.effects.EqualizerBand jfxBand =
144                            jfxEqualizer.addBand(band.getCenterFrequency(),
145                            band.getBandwidth(),
146                            band.getGain());
147                    // setJfxBand will throw an NPE if jfxBand is null which
148                    // should never happen.
149                    band.setJfxBand(jfxBand);
150                } else {
151                    Logger.logMsg(Logger.ERROR, "Center frequency [" + band.getCenterFrequency()
152                            + "] and bandwidth [" + band.getBandwidth() + "] must be greater than 0.");
153                }
154            }
155        }
156    }
157
158    /**
159     * Whether the <code>AudioEqualizer</code> is enabled. The default value is
160     * <code>true</code>.
161     */
162    private BooleanProperty enabled;
163
164    /**
165     * Enables or disables <code>AudioEqualizer</code>. If the enabled property
166     * is set to <tt>false</tt>, {@link AudioEqualizer} settings are preserved but
167     * not taken into account during playback, which is equivalent to setting all
168     * {@link EqualizerBand#gainProperty EqualizerBand.gain} properties to zero.
169     */
170    public final void setEnabled(boolean value) {
171        enabledProperty().set(value);
172    }
173
174    /**
175     * Return enabled state of the AudioEqualizer.
176     * @return <tt>true</tt> if AudioEqulizer is enabled, <tt>false</tt> otherwise.
177     */
178    public final boolean isEnabled() {
179        return enabled == null ? false : enabled.get();
180    }
181
182    public BooleanProperty enabledProperty() {
183        if (enabled == null) {
184            enabled = new BooleanPropertyBase() {
185
186                @Override
187                protected void invalidated() {
188                    synchronized (disposeLock) {
189                        if (jfxEqualizer != null) {
190                            jfxEqualizer.setEnabled(enabled.get());
191                        }
192                    }
193                }
194
195                @Override
196                public Object getBean() {
197                    return AudioEqualizer.this;
198                }
199
200                @Override
201                public String getName() {
202                    return "enabled";
203                }
204            };
205        }
206        return enabled;
207    }
208
209    private class Bands extends VetoableListDecorator<EqualizerBand> {
210
211        public Bands() {
212            super(FXCollections.<EqualizerBand>observableArrayList());
213        }
214
215        @Override
216        protected void onProposedChange(List<EqualizerBand> toBeAdded, int[] toBeRemoved) {
217            synchronized (disposeLock) {
218                if (jfxEqualizer != null) {
219                    for (int i = 0; i < toBeRemoved.length; i += 2) {
220                        for (EqualizerBand band : subList(toBeRemoved[i], toBeRemoved[i + 1])) {
221                            jfxEqualizer.removeBand(band.getCenterFrequency());
222                        }
223                    }
224
225                    for (EqualizerBand band : toBeAdded) {
226                        if (band.getCenterFrequency() > 0 && band.getBandwidth() > 0) {
227                            com.sun.media.jfxmedia.effects.EqualizerBand jfxBand =
228                                    jfxEqualizer.addBand(band.getCenterFrequency(),
229                                    band.getBandwidth(),
230                                    band.getGain());
231                            band.setJfxBand(jfxBand);
232                        } else {
233                            Logger.logMsg(Logger.ERROR, "Center frequency [" + band.getCenterFrequency()
234                                    + "] and bandwidth [" + band.getBandwidth() + "] must be greater than 0.");
235                        }
236                    }
237                }
238            }
239        }
240    }
241}