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

sounds can be loaded as base64

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