/**
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
*/
package org.puredata.core.utils;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.puredata.core.PdBase;
import org.puredata.core.PdListener;
import org.puredata.core.PdReceiver;
/**
*
* PdDispatcher is an implementation of {@link PdReceiver} that dispatches messages from Pd to instances of
* {@link PdListener} based on the Pd symbol they originate from. Instances of this class automatically
* handle subscriptions to Pd symbols.
*
* @author Peter Brinkmann (peter.brinkmann@gmail.com)
*
*/
public abstract class PdDispatcher implements PdReceiver {
private final Map<String, Set<PdListener>> listeners = new HashMap<String, Set<PdListener>>();
/**
* Register a listener for Pd messages to the given symbol; subscribe to the symbol if this is
* the first listener for this symbol
*
* @param symbol receiver symbol in Pd
* @param listener
*/
public synchronized void addListener(String symbol, PdListener listener) {
Set<PdListener> selected = listeners.get(symbol);
if (selected == null) {
int err = PdBase.subscribe(symbol);
if (err != 0) {
throw new IllegalArgumentException("bad symbol: " + symbol);
}
selected = new HashSet<PdListener>();
listeners.put(symbol, selected);
}
selected.add(listener);
}
/**
* Remove a listener associated with a symbol; unsubscribe from Pd messages to symbol
* if no listeners are left
*
* @param symbol receiver symbol in Pd
* @param listener
*/
public synchronized void removeListener(String symbol, PdListener listener) {
Set<PdListener> selected = listeners.get(symbol);
if (selected != null) {
selected.remove(listener);
if (selected.isEmpty()) {
PdBase.unsubscribe(symbol);
listeners.remove(symbol);
}
}
}
/**
* Unsubscribe from Pd messages and release all resources
*/
public synchronized void release() {
for (String symbol: listeners.keySet()) {
PdBase.unsubscribe(symbol);
}
listeners.clear();
}
@Override
protected void finalize() throws Throwable {
release();
super.finalize();
}
/**
* Handle print messages from Pd
*/
@Override
public abstract void print(String s);
@Override
public synchronized void receiveBang(String source) {
Set<PdListener> selected = listeners.get(source);
if (selected != null) {
for (PdListener listener: selected) {
listener.receiveBang(source);
}
}
}
@Override
public synchronized void receiveFloat(String source, float x) {
Set<PdListener> selected = listeners.get(source);
if (selected != null) {
for (PdListener listener: selected) {
listener.receiveFloat(source, x);
}
}
}
@Override
public synchronized void receiveSymbol(String source, String symbol) {
Set<PdListener> selected = listeners.get(source);
if (selected != null) {
for (PdListener listener: selected) {
listener.receiveSymbol(source, symbol);
}
}
}
@Override
public synchronized void receiveList(String source, Object... args) {
Set<PdListener> selected = listeners.get(source);
if (selected != null) {
for (PdListener listener: selected) {
listener.receiveList(source, args);
}
}
}
@Override
public synchronized void receiveMessage(String source, String symbol, Object... args) {
Set<PdListener> selected = listeners.get(source);
if (selected != null) {
for (PdListener listener: selected) {
listener.receiveMessage(source, symbol, args);
}
}
}
}