f@0: /* f@0: CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool f@0: f@0: Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) f@0: f@0: This program is free software: you can redistribute it and/or modify f@0: it under the terms of the GNU General Public License as published by f@0: the Free Software Foundation, either version 3 of the License, or f@0: (at your option) any later version. f@0: f@0: This program is distributed in the hope that it will be useful, f@0: but WITHOUT ANY WARRANTY; without even the implied warranty of f@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the f@0: GNU General Public License for more details. f@0: f@0: You should have received a copy of the GNU General Public License f@0: along with this program. If not, see . f@0: */ f@0: f@0: package uk.ac.qmul.eecs.ccmi.network; f@0: f@0: import java.io.IOException; f@0: import java.net.SocketException; f@0: import java.nio.ByteBuffer; f@0: import java.nio.channels.SocketChannel; f@0: import java.util.ResourceBundle; f@0: f@0: import uk.ac.qmul.eecs.ccmi.gui.DiagramEventSource; f@0: f@0: import de.sciss.net.OSCBundle; f@0: import de.sciss.net.OSCMessage; f@0: f@0: /* f@0: * An implementation of the Protocol interface which uses OSC messages f@0: * streamed on a TCP connection. f@0: * f@0: */ f@0: class OscProtocol implements Protocol { f@0: f@0: OscProtocol(){ f@0: buffer = ByteBuffer.allocate(DEFAULT_CAPACITY); f@0: codec = new CCmIOSCPacketCodec(); f@0: } f@0: f@0: @Override f@0: public void send(SocketChannel channel, Command cmd) throws IOException { f@0: /* OSC message args = [diagram, cmd.arg1, cmd.arg2, amd.arg2, ... , cmd.argN ] */ f@0: bundle = new CCmIOSCBundle(cmd.getTimestamp()); f@0: Object[] args = new Object[2+cmd.getArgNum()]; f@0: args[0] = cmd.getDiagram(); f@0: args[1] = cmd.getSource().toString(); f@0: for(int i=0; i 0 ); f@0: ByteBuffer b = buffer; f@0: /* if the packet is very big we must allocate an ad hoc temporary big big buffer */ f@0: if(packetSize <= DEFAULT_CAPACITY) f@0: b.rewind().limit(packetSize); f@0: else f@0: b = ByteBuffer.allocate(packetSize); f@0: /* read the packet, it must be a bundle containing only one message */ f@0: while( b.hasRemaining() ) f@0: if( channel.read( b ) == -1 ) f@0: throw new SocketException(ResourceBundle.getBundle(Server.class.getName()).getString("error.connection_close")); f@0: b.rewind(); f@0: return (OSCBundle)codec.decode(b); f@0: } f@0: f@0: private void writeBundle(SocketChannel channel) throws IOException{ f@0: ByteBuffer b = buffer; f@0: buffer.clear(); f@0: if(bundle.getSize() + 4 > DEFAULT_CAPACITY){ f@0: b = ByteBuffer.allocate(bundle.getSize() + 4); f@0: } f@0: b.position(4); f@0: bundle.encode(codec,b); f@0: int len = b.position() - 4; f@0: b.putInt(0, len); f@0: b.flip(); f@0: channel.write(b); f@0: } f@0: f@0: ByteBuffer buffer; f@0: CCmIOSCBundle bundle; f@0: CCmIOSCPacketCodec codec; f@0: f@0: private static final int DEFAULT_CAPACITY = 1024; f@0: private static final char OSC_NAME_PREFIX = '/'; f@0: f@0: f@0: private static final int REPLY_LEN_INDEX = 0; f@0: /* position of the diagram Name in the OSC message */ f@0: private static final int REPLY_DIAGRAM_INDEX = 1; f@0: private static final int REPLY_SOURCE_INDEX = 3; f@0: private static final int CMD_DIAGRAM_INDEX = 0; f@0: private static final int CMD_SOURCE_INDEX = 1; f@0: private static final int CMD_OFFSET = 2; f@0: private static final int LOCK_DIAGRAM_INDEX = 0; f@0: private static final int LOCK_SOURCE_INDEX = 1; f@0: private static final int LOCK_OFFSET = 2; f@0: private static final int AWAR_DIAGRAM_INDEX = 0; f@0: private static final int AWAR_SOURCE_INDEX = 1; f@0: /* ------------------------------------------------*/ f@0: private static final int REPLY_MESSAGE_INDEX = 2; f@0: }