Commit dfdc3b8f authored by Valérie Maquil's avatar Valérie Maquil

sounds can be loaded as base64

parent 29066317
/**
* Copyright Luxembourg Institute of Science and Technology, 2016.
*
* This file is part of TULIP.
*
* TULIP is licensed under a dual-licensing scheme. For non-commercial purposes, the LGPL version 3,
* as stated below, is applicable. For all commercial purposes TULIP is licensed under a LIST
* proprietary license. Please contact LIST at tto@list.lu to obtain a commercial license.
*
* For all non-commercial purposes, TULIP is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, version 3 of the License.
*
* TULIP 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 Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.scenario;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.tui.TangibleApplication;
import lu.list.itis.dkd.tui.TangibleContentManager;
import lu.list.itis.dkd.tui.content.Content;
import lu.list.itis.dkd.tui.cps.system.Equation;
import lu.list.itis.dkd.tui.cps.system.Mapping;
import lu.list.itis.dkd.tui.cps.variable.BooleanVariable;
import lu.list.itis.dkd.tui.cps.variable.Variable;
import lu.list.itis.dkd.tui.exception.BuildException;
import lu.list.itis.dkd.tui.utility.Externalization;
import com.google.common.base.Splitter;
import org.jdom2.Element;
import java.awt.Graphics2D;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Base64;
import java.util.LinkedHashSet;
import javax.imageio.ImageIO;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.ImageIcon;
/**
* Class holding all the necessary bits to play a scene in response to a particular trigger
* condition. The class extends {@link Content} and can, thus, easily be managed by a
* {@link TangibleApplication}, respectively its {@link TangibleContentManager}.
*
* @author Eric Tobias [eric.tobias@list.lu]
* @since 1.0
* @version 1.0.2
*/
@NonNullByDefault
public class Scene extends Content {
/** The equation that will evaluate the trigger condition. */
private Equation trigger;
/** All variables that will be needed to evaluate the trigger condition. */
private LinkedHashSet<Variable> variables = new LinkedHashSet<>();
/** Variable used to easily gather the output from the trigger equation. */
private BooleanVariable triggerVariable = new BooleanVariable("Trigger", false); //$NON-NLS-1$
/** The image to show when painting. */
private ImageIcon scenery;
/** The sound to play when painting. */
private Clip audioClip;
private boolean triggered = false;
/**
* Constructor initializing all fields.
*
* @param element
* @throws BuildException
*/
public Scene(Element element) throws BuildException {
super(element.getChildText(Externalization.NAME_NODE));
try {
drawPriority = Integer.parseInt(element.getChildText(Externalization.DRAW_PRIORITY_NODE));
} catch (final NumberFormatException e) {
}
final String triggerCondition = element.getChildText(Externalization.TRIGGER_CONDITION_NODE);
for (final String _name : Splitter.on(Externalization.SPACE).trimResults().omitEmptyStrings().split(triggerCondition)) {
final Variable variable = Scenario.retrieveVariableByName(_name);
if (null != variable) {
variables.add(variable);
}
}
// TODO This needs to be solved more elegantly.
if (variables.isEmpty()) {
variables.add(triggerVariable);
}
trigger = new Equation(new Mapping(variables, triggerVariable), triggerCondition);
try {
final Element imageNode = element.getChild(Externalization.IMAGE_ELEMENT);
if (null != imageNode) {
scenery = new ImageIcon(ImageIO.read(new File(imageNode.getText())));
}
} catch (final NullPointerException npe) {
throw new BuildException("The provided image path may not be empty!", npe); //$NON-NLS-1$
} catch (final IllegalArgumentException iae) {
throw new BuildException("The image could not be read from the provided location. The location should be given as absolute path, i.e.: \"C:\\My Image\\image.jpeg\"!", iae); //$NON-NLS-1$
} catch (final IOException ioe) {
// throw new BuildException("The image could not be read!", ioe); //$NON-NLS-1$
}
try {
final Element imageBase64Node = element.getChild(Externalization.IMAGE_BASE64_ELEMENT);
if ((null != imageBase64Node) && (imageBase64Node.getText() != "")) {
final String[] tokens = (imageBase64Node.getText()).split(",");
System.out.println(tokens[1]);
byte[] imageByte;
imageByte = Base64.getDecoder().decode(tokens[1]);
final ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
scenery = new ImageIcon(ImageIO.read(bis));
}
} catch (final IOException e1) {
throw new BuildException("The Base64 image could not be read!", e1); //$NON-NLS-1$
}
// open the sound file as a Java input stream
try {
final Element soundNode = element.getChild(Externalization.SOUND_NODE);
if ((null != soundNode) && (soundNode.getText() != "")) {
final File audioFile = new File(soundNode.getText());
final AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
final AudioFormat format = audioStream.getFormat();
final DataLine.Info info = new DataLine.Info(Clip.class, format);
audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
}
}
catch (final FileNotFoundException e) {
throw new BuildException("The file could not be found!", e); //$NON-NLS-1$
} catch (final IOException e) {
throw new BuildException("The sound could not be read!", e); //$NON-NLS-1$
} catch (final UnsupportedAudioFileException e) {
throw new BuildException("The sound format is not supported!", e); //$NON-NLS-1$
} catch (final LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Simple getter to retrieve the trigger.
*
* @return The equation that servers as a trigger for this scene.
*/
public Equation getTrigger() {
return trigger;
}
/**
* Method called to evaluate the stored trigger. Returns the result as a boolean.
*
* @return <code>true</code> if value held by the result variable of the stored trigger
* evaluates to true, <code>false</code> otherwise.
* @see Equation#evaluate()
*/
public boolean evaluateTrigger() {
trigger.evaluate();
if (!triggerVariable.getValue() && triggered) {
triggered = false;
}
return triggerVariable.getValue();
}
/** {@inheritDoc} */
@Override
public void paint(Graphics2D canvas) {
// canvas.drawImage(scenery, 0, 0, null);
if (scenery != null) {
scenery.paintIcon(null, canvas, 0, 0);
}
if ((!triggered) && (audioClip != null)) {
audioClip.setFramePosition(0);
audioClip.start();
triggered = true;
}
}
/** {@inheritDoc} */
@Override
public void initialise() {
// Nothing to do here!
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2016.
*
* This file is part of TULIP.
*
* TULIP is licensed under a dual-licensing scheme. For non-commercial purposes, the LGPL version 3,
* as stated below, is applicable. For all commercial purposes TULIP is licensed under a LIST
* proprietary license. Please contact LIST at tto@list.lu to obtain a commercial license.
*
* For all non-commercial purposes, TULIP is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, version 3 of the License.
*
* TULIP 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 Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.scenario;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.tui.TangibleApplication;
import lu.list.itis.dkd.tui.TangibleContentManager;
import lu.list.itis.dkd.tui.content.Content;
import lu.list.itis.dkd.tui.cps.system.Equation;
import lu.list.itis.dkd.tui.cps.system.Mapping;
import lu.list.itis.dkd.tui.cps.variable.BooleanVariable;
import lu.list.itis.dkd.tui.cps.variable.Variable;
import lu.list.itis.dkd.tui.exception.BuildException;
import lu.list.itis.dkd.tui.utility.Externalization;
import com.google.common.base.Splitter;
import org.jdom2.Element;
import java.awt.Graphics2D;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Base64;
import java.util.LinkedHashSet;
import javax.imageio.ImageIO;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.ImageIcon;
/**
* Class holding all the necessary bits to play a scene in response to a particular trigger
* condition. The class extends {@link Content} and can, thus, easily be managed by a
* {@link TangibleApplication}, respectively its {@link TangibleContentManager}.
*
* @author Eric Tobias [eric.tobias@list.lu]
* @since 1.0
* @version 1.0.2
*/
@NonNullByDefault
public class Scene extends Content {
/** The equation that will evaluate the trigger condition. */
private Equation trigger;
/** All variables that will be needed to evaluate the trigger condition. */
private LinkedHashSet<Variable> variables = new LinkedHashSet<>();
/** Variable used to easily gather the output from the trigger equation. */
private BooleanVariable triggerVariable = new BooleanVariable("Trigger", false); //$NON-NLS-1$
/** The image to show when painting. */
private ImageIcon scenery;
/** The sound to play when painting. */
private Clip audioClip;
private boolean triggered = false;
private AudioInputStream audioIn;
private AudioInputStream audioStream;
/**
* Constructor initializing all fields.
*
* @param element
* @throws BuildException
*/
public Scene(Element element) throws BuildException {
super(element.getChildText(Externalization.NAME_NODE));
try {
drawPriority = Integer.parseInt(element.getChildText(Externalization.DRAW_PRIORITY_NODE));
} catch (final NumberFormatException e) {
}
final String triggerCondition = element.getChildText(Externalization.TRIGGER_CONDITION_NODE);
for (final String _name : Splitter.on(Externalization.SPACE).trimResults().omitEmptyStrings().split(triggerCondition)) {
final Variable variable = Scenario.retrieveVariableByName(_name);
if (null != variable) {
variables.add(variable);
}
}
// TODO This needs to be solved more elegantly.
if (variables.isEmpty()) {
variables.add(triggerVariable);
}
trigger = new Equation(new Mapping(variables, triggerVariable), triggerCondition);
try {
final Element imageNode = element.getChild(Externalization.IMAGE_ELEMENT);
if (null != imageNode) {
scenery = new ImageIcon(ImageIO.read(new File(imageNode.getText())));
}
} catch (final NullPointerException npe) {
throw new BuildException("The provided image path may not be empty!", npe); //$NON-NLS-1$
} catch (final IllegalArgumentException iae) {
throw new BuildException("The image could not be read from the provided location. The location should be given as absolute path, i.e.: \"C:\\My Image\\image.jpeg\"!", iae); //$NON-NLS-1$
} catch (final IOException ioe) {
// throw new BuildException("The image could not be read!", ioe); //$NON-NLS-1$
}
try {
final Element imageBase64Node = element.getChild(Externalization.IMAGE_BASE64_ELEMENT);
if ((null != imageBase64Node) && (imageBase64Node.getText() != "")) { //$NON-NLS-1$
final String[] tokens = (imageBase64Node.getText()).split(","); //$NON-NLS-1$
// System.out.println(tokens[1]);
byte[] imageByte;
imageByte = Base64.getDecoder().decode(tokens[1]);
final ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
scenery = new ImageIcon(ImageIO.read(bis));
}
} catch (final IOException e1) {
throw new BuildException("The Base64 image could not be read!", e1); //$NON-NLS-1$
}
// open the sound file as a Java input stream
try {
final Element soundNode = element.getChild(Externalization.SOUND_NODE);
if ((null != soundNode) && (soundNode.getText() != "")) { //$NON-NLS-1$
final File audioFile = new File(soundNode.getText());
audioStream = AudioSystem.getAudioInputStream(audioFile);
final AudioFormat format = audioStream.getFormat();
final DataLine.Info info = new DataLine.Info(Clip.class, format);
audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
}
}
catch (final FileNotFoundException e) {
// throw new BuildException("The file could not be found!", e); //$NON-NLS-1$
} catch (final IOException e) {
throw new BuildException("The sound could not be read!", e); //$NON-NLS-1$
} catch (final UnsupportedAudioFileException e) {
throw new BuildException("The sound format is not supported!", e); //$NON-NLS-1$
} catch (final LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
final Element soundBase64Node = element.getChild(Externalization.SOUND_BASE64_NODE);
if ((null != soundBase64Node) && (soundBase64Node.getText() != "")) { //$NON-NLS-1$
final String[] tokens = (soundBase64Node.getText()).split(","); //$NON-NLS-1$
// System.out.println(tokens[1]);
final byte[] soundByte = Base64.getDecoder().decode(tokens[1]);
audioIn = AudioSystem.getAudioInputStream(new ByteArrayInputStream(soundByte));
audioClip = AudioSystem.getClip();
audioClip.open(audioIn);
}
} catch (final UnsupportedAudioFileException e) {
throw new BuildException("The sound format is not supported!", e); //$NON-NLS-1$
} catch (final IOException e) {
throw new BuildException("The sound could not be read!", e); //$NON-NLS-1$
} catch (final LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Simple getter to retrieve the trigger.
*
* @return The equation that servers as a trigger for this scene.
*/
public Equation getTrigger() {
return trigger;
}
/**
* Method called to evaluate the stored trigger. Returns the result as a boolean.
*
* @return <code>true</code> if value held by the result variable of the stored trigger
* evaluates to true, <code>false</code> otherwise.
* @see Equation#evaluate()
*/
public boolean evaluateTrigger() {
trigger.evaluate();
if (!triggerVariable.getValue() && triggered) {
triggered = false;
}
return triggerVariable.getValue();
}
/** {@inheritDoc} */
@Override
public void paint(Graphics2D canvas) {
// canvas.drawImage(scenery, 0, 0, null);
if (scenery != null) {
scenery.paintIcon(null, canvas, 0, 0);
}
if ((!triggered) && (audioClip != null)) {
audioClip.setFramePosition(0);
audioClip.start();
triggered = true;
}
}
/** {@inheritDoc} */
@Override
public void initialise() {
// Nothing to do here!
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment