org.monome.pages.ExternalApplicationPage.java Source code

Java tutorial

Introduction

Here is the source code for org.monome.pages.ExternalApplicationPage.java

Source

/*
 *  ExternalApplicationPage.java
 * 
 *  Copyright (c) 2008, Tom Dinchak
 * 
 *  This file is part of Pages.
 *
 *  Pages is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Pages 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 Pages; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

package org.monome.pages;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;

import javax.sound.midi.MidiMessage;
import javax.sound.midi.Receiver;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.apache.commons.lang.StringEscapeUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.illposed.osc.OSCListener;
import com.illposed.osc.OSCMessage;
import com.illposed.osc.OSCPortIn;
import com.illposed.osc.OSCPortOut;

/**
 * The External Application page.  Usage information is available at:
 * 
 * http://code.google.com/p/monome-pages/wiki/ExternalApplicationPage
 * 
 * @author Tom Dinchak, Stephen McLeod
 *
 */
public class ExternalApplicationPage implements Page, ActionListener, OSCListener {

    /**
     * The MonomeConfiguration this page belongs to
     */
    private MonomeConfiguration monome;

    /**
     * This page's index (page number) 
     */
    private int index;

    /**
     * The OSC prefix the external application uses
     */
    private String prefix = "/mlr";

    /**
     * The hostname that the external application is bound to 
     */
    private String hostname = "localhost";

    /**
     * The OSC input port number to receive messages from the external application 
     */
    private int inPort = 8080;

    /**
     * The OSCPortIn object for communication with the external application
     */
    private OSCPortIn oscIn;

    /**
     * The OSC output port number to send messages to the external application
     */
    private int outPort = 8000;

    /**
     * The OSCPortOut object for communication with the external application 
     */
    private OSCPortOut oscOut;

    /**
     * The page's GUI
     */
    private JPanel panel;

    /**
     * The Disable LED Cache checkbox 
     */
    private JCheckBox disableCache;

    /**
     * The OSC Prefix label
     */
    private JLabel prefixLabel;

    /**
     * The OSC Prefix text field 
     */
    private JTextField prefixTF;

    /**
     * The OSC Output Port label
     */
    private JLabel oscOutLabel;

    /**
     * The OSC Output Port text field
     */
    private JTextField oscOutTF;

    /**
     * The OSC Input Port text field
     */
    private JLabel oscInLabel;

    /**
     * The OSC Input Port text field
     */
    private JTextField oscInTF;

    /**
     * The OSC hostname label
     */
    private JLabel hostnameLabel;

    /**
     * The OSC hostname text field
     */
    private JTextField hostnameTF;

    /**
     * The update preferences button
     */
    private JButton updatePrefsButton;

    private Receiver recv;

    // tilt stuff 
    private ADCOptions pageADCOptions = new ADCOptions();

    /**
     * The name of the page 
     */
    private String pageName = "External Application";
    private JLabel pageNameLBL;

    //private Receiver recv;
    /**
     * @param monome The MonomeConfiguration object this page belongs to
     * @param index The index of this page (page number)
     */
    public ExternalApplicationPage(MonomeConfiguration monome, int index) {
        this.monome = monome;
        this.index = index;
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
        // update the external application OSC configuration
        if (e.getActionCommand().equals("Update Preferences")) {
            this.prefix = this.prefixTF.getText();
            this.hostname = this.hostnameTF.getText();
            this.inPort = Integer.parseInt(this.oscInTF.getText());
            this.outPort = Integer.parseInt(this.oscOutTF.getText());
            this.initOSC();
        }
        return;
    }

    /**
     * Stops OSC communication with the external application
     */
    public void stopOSC() {

        if (this.oscIn != null) {
            this.oscIn.removeListener(this.prefix + "/led");
            this.oscIn.removeListener(this.prefix + "/led_col");
            this.oscIn.removeListener(this.prefix + "/led_row");
            this.oscIn.removeListener(this.prefix + "/clear");
            this.oscIn.removeListener(this.prefix + "/frame");
        }

    }

    /**
     * Initializes OSC communication with the external application
     */
    public void initOSC() {
        this.stopOSC();
        this.oscOut = OSCPortFactory.getInstance().getOSCPortOut(this.hostname, String.valueOf(this.outPort));
        this.oscIn = OSCPortFactory.getInstance().getOSCPortIn(String.valueOf(this.inPort));
        this.oscIn.addListener(this.prefix + "/led", this);
        this.oscIn.addListener(this.prefix + "/led_col", this);
        this.oscIn.addListener(this.prefix + "/led_row", this);
        this.oscIn.addListener(this.prefix + "/clear", this);
        this.oscIn.addListener(this.prefix + "/frame", this);
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#addMidiOutDevice(java.lang.String)
     */
    public void addMidiOutDevice(String deviceName) {
        this.recv = this.monome.getMidiReceiver(deviceName);
        this.updatePrefsButton.removeActionListener(this);
        this.panel.removeAll();
        this.panel = null;
        this.monome.redrawPanel();
        this.initOSC();
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#getName()
     */

    public String getName() {
        return pageName;
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#setName()
     */
    public void setName(String name) {
        this.pageName = name;
        this.pageNameLBL.setText("Page " + (this.index + 1) + ": " + pageName);
        this.monome.setJMenuBar(this.monome.createMenuBar());
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#getPanel()
     */
    public JPanel getPanel() {
        if (this.panel != null) {
            return this.panel;
        }

        // builds the page GUI
        JPanel panel = new JPanel();
        panel.setLayout(null);
        panel.setPreferredSize(new java.awt.Dimension(220, 180));

        pageNameLBL = new JLabel("Page " + (this.index + 1) + ": " + this.getName());
        prefixLabel = new JLabel();
        prefixLabel.setText("OSC Prefix");
        hostnameLabel = new JLabel();
        hostnameLabel.setText("OSC Hostname");
        oscInLabel = new JLabel();
        oscInLabel.setText("OSC In Port");
        oscOutLabel = new JLabel();
        oscOutLabel.setText("OSC Out Port");
        oscInTF = new JTextField();
        oscInTF.setText(String.valueOf(this.inPort));
        oscOutTF = new JTextField();
        panel.add(oscOutTF);
        panel.add(oscOutLabel);
        panel.add(oscInTF);
        panel.add(oscInLabel);
        oscInLabel.setBounds(12, 65, 85, 14);
        oscInTF.setBounds(97, 62, 100, 21);
        oscOutLabel.setBounds(12, 86, 85, 14);
        oscOutTF.setText(String.valueOf(this.outPort));
        oscOutTF.setBounds(97, 83, 100, 21);
        updatePrefsButton = new JButton();
        updatePrefsButton.setText("Update Preferences");
        updatePrefsButton.addActionListener(this);
        prefixTF = new JTextField();
        prefixTF.setText(this.prefix);
        hostnameTF = new JTextField();
        panel.add(hostnameTF);
        panel.add(hostnameLabel);
        panel.add(prefixTF);
        panel.add(prefixLabel);
        panel.add(pageNameLBL);
        panel.add(updatePrefsButton);
        panel.add(getDisableCache());
        updatePrefsButton.setBounds(12, 140, 169, 21);
        pageNameLBL.setBounds(0, 0, 250, 14);
        prefixLabel.setBounds(12, 23, 85, 14);
        prefixTF.setBounds(97, 20, 100, 21);
        hostnameLabel.setBounds(12, 44, 85, 14);
        hostnameTF.setText(this.hostname);
        hostnameTF.setBounds(97, 41, 100, 21);

        this.panel = panel;
        return panel;
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#handlePress(int, int, int)
     */
    public void handlePress(int x, int y, int value) {
        // pass all press messages along to the external application
        if (this.oscOut == null) {
            return;
        }
        Object args[] = new Object[3];
        args[0] = new Integer(x);
        args[1] = new Integer(y);
        args[2] = new Integer(value);
        OSCMessage msg = new OSCMessage(this.prefix + "/press", args);
        try {
            this.oscOut.send(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean isTiltPage() {
        return true;
    }

    public ADCOptions getAdcOptions() {
        return this.pageADCOptions;
    }

    public void setAdcOptions(ADCOptions options) {
        this.pageADCOptions = options;
    }

    public void handleADC(int adcNum, float value) {
        if (this.oscOut == null) {
            return;
        }

        switch (adcNum) {
        case 0:
            if (this.pageADCOptions.isSwapADC())
                adcNum = 2;
            break;
        case 1:
            if (this.pageADCOptions.isSwapADC())
                adcNum = 3;
            break;
        case 2:
            if (this.pageADCOptions.isSwapADC())
                adcNum = 0;
            break;
        case 3:
            if (this.pageADCOptions.isSwapADC())
                adcNum = 1;
            break;
        default:
            break;
        }

        Object args[] = new Object[2];
        OSCMessage msg;

        args[0] = new Integer(adcNum);
        args[1] = new Float(value);
        msg = new OSCMessage(this.prefix + "/adc", args);

        try {
            this.oscOut.send(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (this.pageADCOptions.isSendADC() && this.monome.adcObj.isEnabled()) {
            this.monome.adcObj.sendCC(this.recv, this.pageADCOptions.getMidiChannel(),
                    this.pageADCOptions.getCcADC(), monome, adcNum, value);
        }
    }

    public void handleADC(float x, float y) {
        if (this.oscOut == null) {
            return;
        }

        Object args[] = new Object[2];
        OSCMessage msg;

        args[0] = x;
        args[1] = y;
        msg = new OSCMessage(this.prefix + "/tilt", args);

        try {
            this.oscOut.send(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (this.pageADCOptions.isSendADC() && this.monome.adcObj.isEnabled())
            this.monome.adcObj.sendCC(this.recv, this.pageADCOptions.getMidiChannel(),
                    this.pageADCOptions.getCcADC(), monome, x, y);
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#handleReset()
     */
    public void handleReset() {
        return;
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#handleTick()
     */
    public void handleTick() {
        return;
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#redrawMonome()
     */
    public void redrawMonome() {
        // redraw the monome from the pageState, this is updated when the page isn't selected
        for (int x = 0; x < this.monome.sizeX; x++) {
            for (int y = 0; y < this.monome.sizeY; y++) {
                this.monome.led(x, y, this.monome.pageState[this.index][x][y], this.index);
            }
        }

    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#send(javax.sound.midi.MidiMessage, long)
     */
    public void send(MidiMessage message, long timeStamp) {
        return;
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#toXml()
     */
    public String toXml() {

        String disableCache = "false";

        if (this.getDisableCache().isSelected()) {
            disableCache = "true";
        }

        String xml = "";
        xml += "      <name>External Application</name>\n";
        xml += "      <pageName>" + this.pageName + "</pageName>\n";
        xml += "      <prefix>" + this.prefix + "</prefix>\n";
        xml += "      <oscinport>" + this.inPort + "</oscinport>\n";
        xml += "      <oscoutport>" + this.outPort + "</oscoutport>\n";
        xml += "      <hostname>" + this.hostname + "</hostname>\n";
        xml += "      <disablecache>" + disableCache + "</disablecache>\n";

        xml += "      <swapADC>" + this.pageADCOptions.isSwapADC() + "</swapADC>\n";
        xml += "      <ccoffset>" + this.pageADCOptions.getCcOffset() + "</ccoffset>\n";
        xml += "      <sendADC>" + this.pageADCOptions.isSendADC() + "</sendADC>\n";
        xml += "      <midiChannelADC>" + this.pageADCOptions.getMidiChannel() + "</midiChannelADC>\n";
        xml += "      <adcTranspose>" + this.pageADCOptions.getAdcTranspose() + "</adcTranspose>\n";
        xml += "      <recv>" + this.pageADCOptions.getRecv() + "</recv>\n";
        return xml;
    }

    /* (non-Javadoc)
     * @see com.illposed.osc.OSCListener#acceptMessage(java.util.Date, com.illposed.osc.OSCMessage)
     */
    public void acceptMessage(Date arg0, OSCMessage msg) {
        // only process messages from the external application
        if (!msg.getAddress().contains(this.prefix)) {
            return;
        }
        // handle a monome clear request from the external application
        if (msg.getAddress().contains("clear")) {
            Object[] args = msg.getArguments();
            int int_arg = 0;
            if (args.length > 0) {
                if (!(args[0] instanceof Integer)) {
                    return;
                }
                int_arg = ((Integer) args[0]).intValue();
            }
            this.monome.clear(int_arg, this.index);
        }

        // handle a monome led_col request from the external application
        if (msg.getAddress().contains("led_col")) {
            Object[] args = msg.getArguments();
            ArrayList<Integer> intArgs = new ArrayList<Integer>();
            for (int i = 0; i < args.length; i++) {
                if (!(args[i] instanceof Integer)) {
                    continue;
                }
                intArgs.add((Integer) args[i]);
            }
            this.monome.led_col(intArgs, this.index);
        }

        // handle a monome led_row request from the external application
        if (msg.getAddress().contains("led_row")) {
            Object[] args = msg.getArguments();
            int[] int_args = { 0, 0, 0 };
            ArrayList<Integer> intArgs = new ArrayList<Integer>();
            for (int i = 0; i < args.length; i++) {
                if (!(args[i] instanceof Integer)) {
                    continue;
                }
                intArgs.add((Integer) args[i]);
            }
            this.monome.led_row(intArgs, this.index);
        }

        // handle a monome led request from the external application
        else if (msg.getAddress().contains("led")) {
            Object[] args = msg.getArguments();
            int[] int_args = { 0, 0, 0 };
            for (int i = 0; i < args.length; i++) {
                if (!(args[i] instanceof Integer)) {
                    return;
                }
                int_args[i] = ((Integer) args[i]).intValue();
            }
            this.monome.led(int_args[0], int_args[1], int_args[2], this.index);
        }

        else if (msg.getAddress().contains("clear")) {
            Object[] args = msg.getArguments();
            int[] int_args = { 0 };
            for (int i = 0; i < args.length; i++) {
                if (!(args[i] instanceof Integer)) {
                    return;
                }
                int_args[i] = ((Integer) args[i]).intValue();
            }
            this.monome.clear(int_args[0], this.index);
        }
    }

    /**
     * @param extPrefix The OSC prefix of the external application
     */
    public void setPrefix(String extPrefix) {
        this.prefix = extPrefix;
        this.prefixTF.setText(extPrefix);
    }

    /**
     * @param extInPort The OSC input port number to receive messages from the external application
     */
    public void setInPort(String extInPort) {
        this.inPort = Integer.parseInt(extInPort);
        this.oscInTF.setText(extInPort);
    }

    /**
     * @param extOutPort The OSC output port number to send messages to the external application
     */
    public void setOutPort(String extOutPort) {
        this.outPort = Integer.parseInt(extOutPort);
        this.oscOutTF.setText(extOutPort);
    }

    /**
     * @param extHostname The hostname that the external application is bound to
     */
    public void setHostname(String extHostname) {
        this.hostname = extHostname;
        this.hostnameTF.setText(extHostname);
    }

    /**
     * @return The Disable LED Cache checkbox
     */
    public JCheckBox getDisableCache() {
        if (disableCache == null) {
            disableCache = new JCheckBox();
            disableCache.setText("Disable LED Cache");
            disableCache.setBounds(12, 110, 200, 20);
        }
        return disableCache;
    }

    /**
     * @param cacheDisabled "true" if the cache should be disabled
     */
    public void setCacheDisabled(String cacheDisabled) {
        if (cacheDisabled.equals("true")) {
            this.getDisableCache().setSelected(true);
        } else {
            this.getDisableCache().setSelected(false);
        }
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#getCacheDisabled()
     */
    public boolean getCacheDisabled() {
        if (this.getDisableCache().isSelected()) {
            return true;
        } else {
            return false;
        }
    }

    /* (non-Javadoc)
     * @see org.monome.pages.Page#destroyPage()
     */
    public void destroyPage() {
        this.stopOSC();
    }

    public void clearPanel() {
        this.panel = null;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public void configure(Element pageElement) {
        NodeList nl = pageElement.getElementsByTagName("pageName");
        Element el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String name = ((Node) nl.item(0)).getNodeValue();
            this.setName(name);

        }

        nl = pageElement.getElementsByTagName("prefix");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String extPrefix = ((Node) nl.item(0)).getNodeValue();
            this.setPrefix(extPrefix);
        }

        nl = pageElement.getElementsByTagName("oscinport");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String extInPort = ((Node) nl.item(0)).getNodeValue();
            this.setInPort(extInPort);
        }

        nl = pageElement.getElementsByTagName("oscoutport");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String extOutPort = ((Node) nl.item(0)).getNodeValue();
            this.setOutPort(extOutPort);
        }

        nl = pageElement.getElementsByTagName("hostname");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String extHostname = ((Node) nl.item(0)).getNodeValue();
            this.setHostname(extHostname);
        }

        nl = pageElement.getElementsByTagName("disablecache");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String cacheDisabled = ((Node) nl.item(0)).getNodeValue();
            this.setCacheDisabled(cacheDisabled);
        }

        nl = pageElement.getElementsByTagName("swapADC");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String swapADC = ((Node) nl.item(0)).getNodeValue();
            this.pageADCOptions.setSwapADC(Boolean.parseBoolean(swapADC));
        }

        nl = pageElement.getElementsByTagName("ccoffset");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String ccOffset = ((Node) nl.item(0)).getNodeValue();
            this.pageADCOptions.setCcOffset(Integer.parseInt(ccOffset));
        }

        nl = pageElement.getElementsByTagName("sendADC");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String sendADC = ((Node) nl.item(0)).getNodeValue();
            this.pageADCOptions.setSendADC(Boolean.parseBoolean(sendADC));
        }

        nl = pageElement.getElementsByTagName("adcTranspose");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String adcTranspose = ((Node) nl.item(0)).getNodeValue();
            this.pageADCOptions.setAdcTranspose(Integer.parseInt(adcTranspose));
        }

        nl = pageElement.getElementsByTagName("midiChannelADC");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String midiChannelADC = ((Node) nl.item(0)).getNodeValue();
            this.pageADCOptions.setMidiChannel(Integer.parseInt(midiChannelADC));
        }

        nl = pageElement.getElementsByTagName("recv");
        el = (Element) nl.item(0);
        if (el != null) {
            nl = el.getChildNodes();
            String recv = ((Node) nl.item(0)).getNodeValue();
            this.pageADCOptions.setRecv(recv);
            this.addMidiOutDevice(this.pageADCOptions.getRecv());
        }

        this.initOSC();
    }
}