/** * * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. * */ package org.puredata.processing; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.puredata.core.PdBase; import org.puredata.core.PdReceiver; /** * Abstract base class for using libpd with Processing. It provides a * wrapper for libpd that is in line with the general look and feel of * Processing libraries. Subclasses will provide the connection between * libpd and the audio platform, such as JACK. * * @author Peter Brinkmann (peter.brinkmann@gmail.com) */ public abstract class PureDataP5Base implements PdReceiver { private final Object parent; private final Method pdPrintCallback; private final Method receiveBangCallback; private final Method receiveFloatCallback; private final Method receiveSymbolCallback; private final Method receiveListCallback; private final Method receiveMessageCallback; /** * Constructor. The parent object will always be an instance of PApplet, * but we don't use PApplet here because we don't want any Processing * dependency in libpd itself. * * @param parent owner, instance of PApplet */ public PureDataP5Base(Object parent) { this.parent = parent; Map<String, Method> methods = extractMethods(parent.getClass()); try { methods.get("registerDispose").invoke(parent, this); } catch (Exception e) { // Not an instance of PApplet, perhaps? throw new RuntimeException(e); } pdPrintCallback = methods.get("pdPrint"); receiveBangCallback = methods.get("receiveBang"); receiveFloatCallback = methods.get("receiveFloat"); receiveSymbolCallback = methods.get("receiveSymbol"); receiveListCallback = methods.get("receiveList"); receiveMessageCallback = methods.get("receiveMessage"); PdBase.setReceiver(this); PdBase.computeAudio(true); } private Map<String, Method> extractMethods(Class<?> clazz) { Map<String, Method> result = new HashMap<String, Method>(); Method[] methods = clazz.getMethods(); for (Method method: methods) { result.put(method.getName(), method); } return result; } /** * Processing dispose callback, automatically registered in the constructor. */ public void dispose() { stop(); PdBase.release(); } /** * Start audio. */ public abstract void start(); /** * Stop audio. */ public abstract void stop(); /** * Delegates to the corresponding method in {@link PdBase}. */ public int subscribe(String sym) { return PdBase.subscribe(sym); } /** * Delegates to the corresponding method in {@link PdBase}. */ public void unsubscribe(String sym) { PdBase.unsubscribe(sym); } /** * Delegates to the corresponding method in {@link PdBase}. */ public int openPatch(File file) { try { return PdBase.openPatch(file); } catch (IOException e) { throw new RuntimeException(e); } } /** * Delegates to the corresponding method in {@link PdBase}. */ public void closePatch(int handle) { PdBase.closePatch(handle); } /** * Delegates to the corresponding method in {@link PdBase}. */ public int arraySize(String name) { return PdBase.arraySize(name); } /** * Delegates to the corresponding method in {@link PdBase}. */ public int readArray(float[] to, int toOffset, String fromArray, int fromOffset, int n) { return PdBase.readArray(to, toOffset, fromArray, fromOffset, n); } /** * Delegates to the corresponding method in {@link PdBase}. */ public int writeArray(String toArray, int toOffset, float[] fromArray, int fromOffset, int n) { return PdBase.writeArray(toArray, toOffset, fromArray, fromOffset, n); } /** * Delegates to the corresponding method in {@link PdBase}. */ public void sendBang(String recv) { PdBase.sendBang(recv); } /** * Delegates to the corresponding method in {@link PdBase}. */ public void sendFloat(String recv, float x) { PdBase.sendFloat(recv, x); } /** * Delegates to the corresponding method in {@link PdBase}. */ public void sendSymbol(String recv, String sym) { PdBase.sendSymbol(recv, sym); } /** * Delegates to the corresponding method in {@link PdBase}. */ public void sendList(String recv, Object... args) { PdBase.sendList(recv, args); } /** * Delegates to the corresponding method in {@link PdBase}. */ public void sendMessage(String recv, String mesg, Object... args) { PdBase.sendMessage(recv, mesg, args); } /** * Delegates to parent's pdPrint method, if it exists; no-op otherwise. */ @Override public void print(String s) { if (pdPrintCallback != null) { try { pdPrintCallback.invoke(parent, s); } catch (Exception e) { // Do nothing. } } } /** * Delegates to parent's receiveBang method, if it exists; no-op otherwise. */ @Override public void receiveBang(String source) { if (receiveBangCallback != null) { try { receiveBangCallback.invoke(parent, source); } catch (Exception e) { // Do nothing. } } } /** * Delegates to parent's receiveFloat method, if it exists; no-op otherwise. */ @Override public void receiveFloat(String source, float x) { if (receiveFloatCallback != null) { try { receiveFloatCallback.invoke(parent, source, x); } catch (Exception e) { // Do nothing. } } } /** * Delegates to parent's receiveSymbol method, if it exists; no-op otherwise. */ @Override public void receiveSymbol(String source, String symbol) { if (receiveSymbolCallback != null) { try { receiveSymbolCallback.invoke(parent, source, symbol); } catch (Exception e) { // Do nothing. } } } /** * Delegates to parent's receiveList method, if it exists; no-op otherwise. */ @Override public void receiveList(String source, Object... args) { if (receiveListCallback != null) { try { receiveListCallback.invoke(parent, source, args); } catch (Exception e) { // Do nothing. } } } /** * Delegates to parent's receiveMessage method, if it exists; no-op otherwise. */ @Override public void receiveMessage(String source, String symbol, Object... args) { if (receiveMessageCallback != null) { try { receiveMessageCallback.invoke(parent, source, symbol, args); } catch (Exception e) { // Do nothing. } } } }