//////////////////////////////////////////////////////////////////////////////// // Copyright 2011 Michael Schmalle - Teoti Graphix, LLC // // 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 // // Author: Michael Schmalle, Principal Architect // mschmalle at teotigraphix dot com //////////////////////////////////////////////////////////////////////////////// package com.teotigraphix.caustk.controller.command; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; /** * The OSCMessage contains the data used to contact the Caustic Core with device * messaging. * <p> * [controller]/[device]/[control] [...params] * * @author Michael Schmalle * @copyright Teoti Graphix, LLC * @since 1.0 */ public class OSCMessage { private static final String SPACE = " "; //-------------------------------------------------------------------------- // // Public :: Variables // //-------------------------------------------------------------------------- //---------------------------------- // exception //---------------------------------- private Exception mException; public final Exception getException() { return mException; } public final void setException(Exception e) { mException = e; } public final boolean hasException() { return mException != null; } //---------------------------------- // instance //---------------------------------- Object instance; /** * The actual IDevice|IDeviceComponent that is sending the message. * (Optional) */ public final Object getInstance() { return instance; } public final void setInstance(Object value) { instance = value; } //---------------------------------- // controller //---------------------------------- String mController; /** * The controller name. */ public String getController() { return mController; } public void setController(String value) { mController = value; } //---------------------------------- // device //---------------------------------- String device; /** * The String IDevice name. */ public final String getDevice() { return device; } //---------------------------------- // control //---------------------------------- String control; /** * The IDevice control name. */ public final String getControl() { return control; } //---------------------------------- // data //---------------------------------- Object data; /** * The arbitrary data based on the specific device, component and control * involved in the message. */ public final Object getData() { return data; } //---------------------------------- // result //---------------------------------- public float result; private Object mResult; /** * The result of the message call if any. * <p> * Once the event is dispatched, if the data variable of the event is not * undefined, the core will update the result after the message returns. * </p> */ public final Object getResult() { return mResult; } public final void setResult(Object value) { mResult = value; } //---------------------------------- // parameters //---------------------------------- List<String> parameters; /** * The parameter list if any. */ public final List<String> getParameters() { // lazy init // if (mParameters == null && data != null) { // StrTokenizer st = new StrTokenizer(data.toString(), ' ', '"'); // mParameters = st.getTokenList(); // } return parameters; } /** * Returns a String parameter if exists, <code>null</code> if the index is * out of bounds. * * @param index The parameter index. */ public String getParameter(int index) { if (!hasParameter(index)) return null; return parameters.get(index); } public boolean hasParameter(int index) { return index < parameters.size(); } //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Creates a new OSCMessage message event. * * @param device A String IDevice name. * @param control An IDevice control name. * @param data The arbitrary data based on the specific device and control * involved in the message. */ public OSCMessage(String device, String control, Object data) { this.device = device; this.control = control; this.data = data; } //-------------------------------------------------------------------------- // // Public :: Methods // //-------------------------------------------------------------------------- /** * Adds a parameter to the parameters collection. * * @param value The value to add. * @return */ public final OSCMessage add(Object value) { if (parameters == null) { parameters = new ArrayList<String>(); data = null; } parameters.add(value.toString()); if (data != null) { StringBuffer sb = new StringBuffer(); sb.append(data); sb.append(SPACE); sb.append(value.toString()); data = sb.toString(); } else { data = value.toString(); } return this; } /** * Creates and returns the constructed OSC message for the core. */ @Override public String toString() { StringBuffer result = new StringBuffer(); result.append("/"); result.append(mController != null ? mController : "caustic"); result.append("/"); result.append(device); result.append("/"); result.append(control); if (data != null) { result.append(" "); result.append(data); } return result.toString(); } public String toCommandString() { StringBuffer result = new StringBuffer(); result.append("/"); result.append(getController()); result.append("/"); result.append(getDevice()); result.append("/"); result.append(getControl()); // no data, just raw command return result.toString(); } /** * Initializes a string message and returns a new {@link OSCMessage} with * populated values from the OSC string. * * @param message The String OSC message to digest. * @return A new {@link OSCMessage} based on the digested String message. */ public static OSCMessage initialize(String message) { StringTokenizer t = new StringTokenizer(message + "\n"); String command = t.nextToken(); String data = null; try { data = t.nextToken("\n").trim(); } catch (Exception e) { // TODO: handle exception } t = new StringTokenizer(command); String base = t.nextToken("/"); String device = t.nextToken("/"); String control = t.nextToken("/"); ArrayList<String> datas = new ArrayList<String>(); if (data != null) { t = new StringTokenizer(data); while (t.hasMoreTokens()) { String token = t.nextToken(); datas.add(token); } } OSCMessage result = OSCMessage.create(device, control, data); result.mController = base; result.parameters = datas; return result; } //-------------------------------------------------------------------------- // // Public Class :: Methods // //-------------------------------------------------------------------------- /** * Creates a new OSCMessage message event. * * @param device A String IDevice name. * @param control An IDevice control name. * @param data The arbitrary data based on the specific device and control * involved in the message. * @return A new OSCMessage. */ public final static OSCMessage create(String device, String control, Object data) { return new OSCMessage(device, control, data); } public final static OSCMessage create(String device, String control) { return new OSCMessage(device, control, null); } }