/**
* Copyright 2010-2011 Voxeo Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License.
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package com.voxeo.moho.media.output;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.media.mscontrol.Parameter;
import javax.media.mscontrol.Parameters;
import javax.media.mscontrol.Value;
import javax.media.mscontrol.mediagroup.CodecConstants;
import javax.media.mscontrol.mediagroup.FileFormatConstants;
import javax.media.mscontrol.resource.RTC;
import javax.media.mscontrol.resource.Resource;
import org.apache.log4j.Logger;
/**
* <p>Media command to play an array of {@link AudibleResource AudibleResource}.</p>
*
* <p>When an array of {@link AudibleSpeechResource AudibleResource}
* are given to this command, these {@link AudibleSpeechResource AudibleResource} form
* a play list. You can jump forwards or backwards within the list.</p>
*
* <p> When applicable, the properties of this command apply to all the
* {@link AudibleSpeechResource AudibleResource}
* in the array. If different properties are required for different
* {@link AudibleSpeechResource AudibleResource},
* you have to use separate {@link OutputCommand OutputCommand} for each
* {@link AudibleSpeechResource AudibleResource}.</p>
*
* @author wchen
*
*/
public class OutputCommand implements Parameters, Cloneable {
private static final Logger LOG = Logger.getLogger(OutputCommand.class);
/**
* How media server should behave when it receives an {@link OutputCommand OutputCommand}
* while it is busy rendering other {@link OutputCommand OutputCommand}s.
*
*/
public enum BehaviorIfBusy {
/**
* This command should be queued up and be played later based on FIFO.
*/
QUEUE,
/**
* This command interrupts other {@link OutputCommand OutputCommand} and should be rendered right away.
*/
STOP,
/**
* Error will be returned.
*/
ERROR
}
/**
* When kind of input should interrupt this command.
*
*/
public enum BargeinType {
/**
* DTMF input should interrupt this command.
*/
DTMF,
/**
* Speech input should interrupt this command.
*/
SPEECH,
/**
* Any input should interrupt this command.
*/
ANY,
/**
* This command should not be interrupted by this command.
*/
NONE
}
protected AudibleResource[] _resources;
protected BehaviorIfBusy _behavior = BehaviorIfBusy.QUEUE;
protected BargeinType _bargein = BargeinType.NONE;
protected String _voiceName;
protected String _language;
protected long _maxtime = Resource.FOREVER;
protected long _offset = 0;
protected int _volumeUnit = 3;
protected Value _codec = CodecConstants.INFERRED;
protected Value _format = FileFormatConstants.INFERRED;
protected long _repeatInterval = 0;
protected int _repeatTimes = 1;
protected int _jumpPlaylistIncrement = 1;
protected long _jumpTime = 5000;
protected boolean _startInPausedMode = false;
protected Parameters _parameters;
protected RTC[] _rtcs;
protected Map<Parameter, Object> _parametersExt = new HashMap<Parameter, Object>();
protected Set<RTC> _rtcsExt = new HashSet<RTC>();
/**
* Construct OutputCommand with simple URL for media content or text for text-to-speech.
*
* @param textOrURL either an URL or text
*/
public OutputCommand(String textOrURL) {
if (textOrURL == null || textOrURL.length() == 0) {
throw new IllegalArgumentException();
}
URL url = null;
try {
url = new URL(textOrURL);
}
catch (IllegalArgumentException ex) {
// IGNORE
LOG.debug("" + ex.getMessage());
}
catch (MalformedURLException e) {
// IGNORE
LOG.debug("" + e.getMessage());
}
if (url != null) {
_resources = new AudibleResource[] {new AudioURIResource(URI.create(textOrURL))};
}
else {
_resources = new AudibleResource[] {new TextToSpeechResource(textOrURL)};
}
}
/**
* Construct OutputCommand with an {@link AudibleResource AudibleResource}.
*
* @param resource the {@link AudibleResource AudibleResource}
*/
public OutputCommand(final AudibleResource resource) {
if (resource != null) {
_resources = new AudibleResource[] {resource};
}
}
/**
* Construct OutputCommand with an array of {@link AudibleResource AudibleResource}.
* This array forms a play list.
*
* @param resources {@link AudibleResource AudibleResource}s
*/
public OutputCommand(final AudibleResource[] resources) {
_resources = resources;
}
public void setAudibleResource(final AudibleResource[] resources) {
_resources = resources;
}
/**
* @return What this command should do when the server is busy.
* The default value is {@link OutputCommand.BehaviorIfBusy.QUEUE QUEUE}.
*/
public BehaviorIfBusy getBehavior() {
return _behavior;
}
/**
* Set What this command should do when the server is busy.
* @param behavior
*/
public void setBahavior(final BehaviorIfBusy behavior) {
_behavior = behavior;
}
/**
* @return The array of {@link AudibleResource AudibleResource} to be played within this command.
* This array of {@link AudibleResource AudibleResource} sometimes is referred as play list.
*/
public AudibleResource[] getAudibleResources() {
return _resources;
}
// public void setAudibleResources(final AudibleResource[] resources) {
// _resources = resources;
// }
/**
* @return Whether this command should be stopped when the other end speaks
*/
public BargeinType getBargeinType() {
return _bargein;
}
/**
* @param bargein true if this command should be stopped when the other end speaks
*/
public void setBargeinType(final BargeinType bargein) {
_bargein = bargein;
}
/**
* The max time of each {@link AudibleResource AudibleResource} in this command can be played.
* When the time is reached, the current {@link AudibleResource AudibleResource} will be stopped
* and next {@link AudibleResource AudibleResource} will start to play.
*
* @return the max timeout in milliseconds.
*/
public long getMaxtime() {
return _maxtime;
}
/**
* set the max timeout of each {@link AudibleResource AudibleResource} in this command.
* @param maxtime the max timeout in milliseconds.
*/
public void setMaxtime(final long maxtime) {
if (maxtime <= 0) {
throw new IllegalArgumentException("Timeout must be a positive integer.");
}
_maxtime = maxtime;
}
/**
* @return The starting offset, in milliseconds, of each {@link AudibleResource AudibleResource} in this command.
*/
public long getStartingOffset() {
return _offset;
}
/**
* Set the starting offset of each {@link AudibleResource AudibleResource} in this command.
* @param offset the starting offset in millisecond.
*/
public void setStartingOffset(final long offset) {
if (offset < 0) {
throw new IllegalArgumentException("Offset can not be a negative integer.");
}
_offset = offset;
}
/**
* @return The unit of the volume, in dB, to be increased or decreased
* when the {@link com.voxeo.moho.media.Output#volume(boolean) Output.volume()} is invoked.
* The default value is 3db.
*
* @see com.voxeo.moho.media.Output#volume(boolean)
*/
public int getVolumeUnit() {
return _volumeUnit;
}
/**
* Set the unit of volume to increased or decreased when the
* {@link com.voxeo.moho.media.Output.volume(boolean) Output.volume(boolean)} is invoked.
*
* @param unit The unit of volume in dB.
*/
public void setVolumeUnit(final int unit) {
_volumeUnit = unit;
}
/**
* @return The default codec value of the each {@link AudibleResource AudibleResource},
* if applicable, in this command.
* By default, the codec is inferred from the file extension and format.
*/
public Value getCodec() {
return _codec;
}
/**
* Set the default codec value for this command.
* @param codec One of the <a href="http://micromethod.com/api/msctrl-1.0/javax/media/mscontrol/mediagroup/CodecConstants.html">codec constants</a>.
*/
public void setCodec(final Value codec) {
_codec = codec;
}
/**
* @return The file format of the each {@link AudibleResource AudibleResource},
* if applicable, in this command.
* By default, the format is inferred from the file extension.
*/
public Value getFormat() {
return _format;
}
/**
* Set the default file format for this command.
* @param format One of the <a href="http://micromethod.com/api/msctrl-1.0/javax/media/mscontrol/mediagroup/FileFormatConstants.html">file format constants</a>.
*/
public void setFormat(final Value format) {
_format = format;
}
/**
* @return How long, in milliseconds, the wait time is between each repetition of this command.
* Only applicable when {link {@link #getRepeatTimes() getRepeatTimes()} is greater than 1.
* The default value is 0.
*/
public long getRepeatInterval() {
return _repeatInterval;
}
/**
* set the interval between each repetition of this command.
* @param interval in milliseconds.
*/
public void setRepeatInterval(final long interval) {
if (interval < 0) {
throw new IllegalArgumentException("Repeat Interval can not be a negative integer.");
}
_repeatInterval = interval;
}
/**
* @return The unit of jump size when {@link com.voxeo.moho.media.Output#jump(int) Output.jump(number)} is invoked.
* The default value is 1.
*
* @see com.voxeo.moho.media.Output#jump(int)
*/
public int getJumpPlaylistIncrement() {
return _jumpPlaylistIncrement;
}
/**
* Set the unit of jump size.
* @param jumpPlaylistIncrement unit as a positive integer.
*/
public void setJumpPlaylistIncrement(int jumpPlaylistIncrement) {
if (jumpPlaylistIncrement <=0) {
throw new IllegalArgumentException("Jump Playlist Increment must be a positive integer.");
}
_jumpPlaylistIncrement = jumpPlaylistIncrement;
}
/**
* @return The unit of the move time, in milliseconds,
* when {@link com.voxeo.moho.media.Output#move(boolean, long) Output.move(direction, time)} is invoked.
*
* @see com.voxeo.moho.media.Output#move(boolean, long)
*/
public long getMoveTime() {
return _jumpTime;
}
/**
* Set the unit of move time in milliseconds.
* @param jumpTime
*/
public void setMoveTime(long jumpTime) {
if (jumpTime < 0) {
throw new IllegalArgumentException("Time can not be a negative integer.");
}
_jumpTime = jumpTime;
}
/**
* @return Whether this command should be started in pause
* so it can be com.voxeo.moho.media.Output#resume() resumed) later.
*/
public boolean isStartInPausedMode() {
return _startInPausedMode;
}
/**
* Set whether this command should be started in pause mode.
* @param startInPausedMode true if this command should be started in pause mode.
*/
public void setStartInPausedMode(boolean startInPausedMode) {
_startInPausedMode = startInPausedMode;
}
@Deprecated
public Parameters getParameters() {
return _parameters;
}
@Deprecated
public void setParameters(Parameters parameters) {
_parameters = parameters;
}
@Deprecated
public RTC[] getRtcs() {
return _rtcs;
}
@Deprecated
public void setRtcs(RTC[] rtcs) {
_rtcs = rtcs;
}
/**
* Add <a href="http://micromethod.com/api/msctrl-1.0/javax/media/mscontrol/resource/RTC.html">RTC</a> to this command.
* @param rtc the <a href="http://micromethod.com/api/msctrl-1.0/javax/media/mscontrol/resource/RTC.html">RTC</a> to be added.
* @return true if rtc is added.
*/
public boolean addRTC(RTC rtc) {
return _rtcsExt.add(rtc);
}
/**
* Add a collection of <a href="http://micromethod.com/api/msctrl-1.0/javax/media/mscontrol/resource/RTC.html">RTC</a> to this command.
* @param c the collection of <a href="http://micromethod.com/api/msctrl-1.0/javax/media/mscontrol/resource/RTC.html">RTC</a>.
* @return true if the collection is successfully added.
*/
public boolean addAllRTC(Collection<? extends RTC> c) {
return _rtcsExt.addAll(c);
}
/**
* Remove all the <a href="http://micromethod.com/api/msctrl-1.0/javax/media/mscontrol/resource/RTC.html">RTC</a>s.
*/
public void removeAllRTC() {
_rtcsExt.clear();
}
/**
* Remove a <a href="http://micromethod.com/api/msctrl-1.0/javax/media/mscontrol/resource/RTC.html">RTC</a>.
* @param o the <a href="http://micromethod.com/api/msctrl-1.0/javax/media/mscontrol/resource/RTC.html">RTC</a> to be removed.
* @return true if removed.
*/
public boolean removeRTC(Object o) {
return _rtcsExt.remove(o);
}
/**
* @return all the <a href="http://micromethod.com/api/msctrl-1.0/javax/media/mscontrol/resource/RTC.html">RTC</a> within this command.
*/
public Set<RTC> getAllRTC() {
return _rtcsExt;
}
// method for Parameters
@Override
public void clear() {
_parametersExt.clear();
}
@Override
public boolean containsKey(Object key) {
return _parametersExt.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return _parametersExt.containsValue(value);
}
@Override
public Set<java.util.Map.Entry<Parameter, Object>> entrySet() {
return _parametersExt.entrySet();
}
@Override
public Object get(Object key) {
return _parametersExt.get(key);
}
@Override
public boolean isEmpty() {
return _parametersExt.isEmpty();
}
@Override
public Set<Parameter> keySet() {
return _parametersExt.keySet();
}
@Override
public Object put(Parameter key, Object value) {
return _parametersExt.put(key, value);
}
@Override
public void putAll(Map<? extends Parameter, ? extends Object> t) {
_parametersExt.putAll(t);
}
@Override
public Object remove(Object key) {
return _parametersExt.remove(key);
}
@Override
public int size() {
return _parametersExt.size();
}
@Override
public Collection<Object> values() {
return _parametersExt.values();
}
/**
* @return How many times this command should be repeated.
*/
public int getRepeatTimes() {
return _repeatTimes;
}
/**
* Set how many times this command should be repeated.
* @param repeatTimes
* The play request will be repeated repeatTimes times. Default value = 1.
*/
public void setRepeatTimes(int repeatTimes) {
_repeatTimes = repeatTimes;
}
/**
* @return The voice name for each {@link TextToSpeechResource TextToSpeechResource} in this command.
*/
public String getVoiceName() {
return _voiceName;
}
/**
* Set the voice name for this command.
* The interpretation of voice name is
* {@link com.voxeo.moho.media.dialect.MediaDialect MediaDialect} specific.
* @param voiceName the voice name to be set.
*/
public void setVoiceName(String voiceName) {
_voiceName = voiceName;
}
public String getLanguage() {
return _language;
}
public void setLanguage(String language) {
this._language = language;
}
@Override
public Object clone() {
try {
return super.clone();
}
catch (CloneNotSupportedException e) {
return null;
}
}
}