///////////////////////////////////////////////////////////////////////////////
// Improviser.java //
// //
// Copyright (c) 2008 Strange Loop. All rights reserved. //
// //
// //
// This program 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 3 of the License, or //
// (at your option) any later version. //
// //
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
import de.sciss.net.*;
import java.net.InetSocketAddress;
import java.io.IOException;
import java.net.SocketAddress;
import java.util.HashMap;
import java.util.Set;
import java.util.Iterator;
/**
* Represents an improvising agent.
* Allows messages to be sent to improvising agents.
* Created when an agent sends a hello message to the server
*
* @author <a href="mailto:matthew@hyde">Matthew Yee-King</a>
* @version 1.0
*/
public class Improviser{
private Conductor conductor;
private OSCClient client;
private String address;
private int port;
private long signInTime;
private boolean dead;
private HashMap<String,Integer> messageCounts;
/**
* create a representation for a remote improviser sitting on the sent address and port
*
* @param address a <code>String</code> value
* @param port an <code>int</code> value
* @param conductor a <code>Conductor</code> value
*/
public Improviser(String address, int port, Conductor conductor){
System.out.println("Improviser:construct address:"+address+" port:"+port);
this.conductor = conductor;
this.address = address;
this.port = port;
this.resetMessageCounts();
client = null;
try {
client = OSCClient.newUsing( OSCClient.UDP ); // create UDP client with any free port number
client.setTarget( new InetSocketAddress( address, port )); // talk to scsynth on the same machine
client.start(); // open channel and (in the case of TCP) connect, then start listening for replies
}
catch( IOException e1 ) {
e1.printStackTrace();
return;
}
dead = false;
}
/**
* This method is used to decide if messages from this improviser
* should be processed by the conductor.
*
*/
public boolean canSendMessages(){
// algorithm for this TBC....
// for now, look for a count over 100..
for (Integer i : messageCounts.values()) {
if (i.intValue() > 100) {
System.out.println("Improviser: not allowing message as count > 100");
return false;
}
}
return true;
}
/**
* Tests if this improviser has sent too many of the sent type of
* message in this cycle according to the thresholds defined in the
* config file.
*
* @param message a <code>String</code> value
* @return a <code>boolean</code> value
*/
public boolean canSendMessage(String message){
int count, allowed;
Integer countI;
countI = messageCounts.get(message);
if (countI == null) {
return true;
}
else {
count = countI.intValue();
allowed = (conductor.getThresholds().get(message)).intValue();
//System.out.println("Improviser: "+message+" count is "+count+" of allowed "+allowed);
if (count > allowed) {
return false;
}
}
return true;
}
/**
* When a message is received by the conductor from this improviser,
* this method is called to keep a count of the messages being sent
* by this improviser, with an aim to ignoring really 'message
* noisy' improvisers.
*
* @param message a <code>String</code> which is the name of the message, e.g. /clock
*/
public synchronized void addToMessageCounts(String message, int length){
Integer count, c;
count = messageCounts.get(message);
if (count == null) {
count = new Integer(length);
}
else {
c = count.intValue();
count = new Integer(c+length);
}
//System.out.println("Improviser: message "+message+" has count "+count.intValue());
messageCounts.put(message, count);
}
public synchronized void resetMessageCounts(){
messageCounts = new HashMap<String,Integer>();
}
public int getPort(){
return port;
}
public String getAddress(){
return address;
}
public void setDead(){
this.dead = true;
}
public boolean isDead(){
return this.dead;
}
public boolean sendPacket(OSCPacket packet){
try {
client.send(packet);
return true;
}
catch( IOException e11 ) {
e11.printStackTrace();
return false;
}
}
public String toString(){
String status = "Improviser: address: "+address+" port: "+port;
return status;
}
}