/* * Copyright 2007 Sun Microsystems, Inc. * * This file is part of jVoiceBridge. * * jVoiceBridge is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation and distributed hereunder * to you. * * jVoiceBridge is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Sun designates this particular file as subject to the "Classpath" * exception as provided by Sun in the License file that accompanied this * code. */ package com.sun.voip.server; import com.sun.voip.Logger; import com.sun.voip.MixDataSource; /* * There is a MixDescriptor for each MixDataSource whose volume needs to be * adjusted. A MixDataSource's volume needs to be adjusted if the * MixDataSource is member in a whisper group or if a member has a * custom mix volume for another member. */ class MixDescriptor { private static final String ZERO_VOLUME_PROPERTY = "com.sun.voip.server.ZERO_VOLUME"; private static double zeroVolume = .0001; private MixDataSource mixDataSource; private double attenuation; /* * The spatial values consist of 4 doubles. * The first is frontBack with -1 being all the way back an +1 * all the way to the front. * The second double is leftRight with -1 all the way to the left * and +1 all the way to the right. * The third double is upDown with -1 all the way down and +1 * all the way to the top. * The fourth double is the non-negative volume level. */ private double[] spatialValues; private boolean isMuted; static { String s = System.getProperty(ZERO_VOLUME_PROPERTY); if (s != null) { try { zeroVolume = Double.parseDouble(s); if (zeroVolume < 0) { zeroVolume = 0; } } catch (NumberFormatException e) { Logger.println("Invalid zero volume: " + s); } } } public MixDescriptor(MixDataSource mixDataSource, double attenuation) { this(mixDataSource, attenuation, null); } public MixDescriptor(MixDataSource mixDataSource, double attenuation, double[] spatialValues) { this.mixDataSource = mixDataSource; this.attenuation = attenuation; if (spatialValues != null) { this.spatialValues = new double[4]; this.spatialValues[0] = spatialValues[0]; this.spatialValues[1] = spatialValues[1]; this.spatialValues[2] = spatialValues[2]; this.spatialValues[3] = spatialValues[3]; } else { this.spatialValues = null; } } public void setMixDataSource(MixDataSource mixDataSource) { this.mixDataSource = mixDataSource; } public MixDataSource getMixDataSource() { return mixDataSource; } public void setAttenuation(double attenuation) { this.attenuation = attenuation; } public double getAttenuation() { return attenuation; } //public void adjustSpatialVolume(double volume) { // spatialValues[3] += volume; //} public boolean isMuted() { return isMuted; } public double getEffectiveVolume() { if (isMuted()) { return 0; } if (spatialValues != null) { return spatialValues[3] * attenuation; } return attenuation; } public void setMuted(boolean isMuted) { this.isMuted = isMuted; } public void setSpatialValues(double[] spatialValues) { this.spatialValues = spatialValues; } public boolean isPrivateMix() { return spatialValues != null; } public static boolean isZeroVolume(double volume) { return volume <= zeroVolume; } public boolean isNop() { return isNop(spatialValues, attenuation); } public static boolean isNop(double[] spatialValues, double attenuation) { if (spatialValues == null) { return attenuation == 1; } return isSpatiallyNeutral(spatialValues) && spatialValues[3] == 1 && attenuation == 1; } public boolean isSpatiallyNeutral() { return isSpatiallyNeutral(spatialValues); } public static boolean isSpatiallyNeutral(double[] spatialValues) { if (spatialValues == null) { return true; } return spatialValues[0] == 0 && spatialValues[1] == 0 && spatialValues[2] == 0; } public double[] getSpatialValues() { return spatialValues; } public boolean equals(MixDataSource mixDataSource, double[] spatialValues) { if (this.mixDataSource != mixDataSource) { return false; } if (this.spatialValues[3] == 0 && spatialValues[3] == 0) { return true; } return this.spatialValues[0] == spatialValues[0] && this.spatialValues[1] == spatialValues[1] && this.spatialValues[2] == spatialValues[2] && this.spatialValues[3] == spatialValues[3]; } public Object clone() { MixDescriptor mixDescriptor = new MixDescriptor( mixDataSource, attenuation, spatialValues); mixDescriptor.setMuted(isMuted); return mixDescriptor; } public String toString() { String s = ""; if (mixDataSource != null) { s += mixDataSource; } s += values(); return s; } public String toAbbreviatedString() { String s = ""; if (mixDataSource != null) { s += mixDataSource.toAbbreviatedString(); } s += values(); return s; } private String values() { double frontBack = 1; double leftRight = 0; double upDown = 0; double volume = 1; if (spatialValues != null) { frontBack = spatialValues[0]; leftRight = spatialValues[1]; upDown = spatialValues[2]; volume = spatialValues[3]; } String s = " attenuation = " + attenuation; s += ", frontBack = " + (Math.round(frontBack * 1000) / 1000.); s += ", leftRight = " + (Math.round(leftRight * 10000) / 10000.); s += ", upDown = " + (Math.round(upDown * 10000) / 10000.); s += ", volume = " + (Math.round(volume * 1000) / 1000.); s += ", effectiveVolume = " + (Math.round(attenuation * volume * 1000) / 1000.); if (isMuted) { s += ", MUTED"; } return s; } }