diff --git a/praxiscore-api/src/main/java/org/praxislive/core/RootHub.java b/praxiscore-api/src/main/java/org/praxislive/core/RootHub.java index c7065d27..45384f0b 100644 --- a/praxiscore-api/src/main/java/org/praxislive/core/RootHub.java +++ b/praxiscore-api/src/main/java/org/praxislive/core/RootHub.java @@ -44,7 +44,7 @@ public interface RootHub extends Lookup.Provider { /** * Dispatch a message to another Root. - * + *

* See {@link Root.Controller#submitPacket(org.praxislive.core.Packet) * * @param packet message to dispatch @@ -78,9 +78,8 @@ public static interface ExtensionProvider { /** * An interface for RootHub extensions (see {@link ExtensionProvider}) to - * advertise the services they provide. Use of {@link Component#getInfo()} - * for this purpose should be considered deprecated. - * + * advertise the services they provide. + *

* The Root itself must provide the advertised services. Support for root * containers to provide services via child components is not yet supported. * @@ -88,8 +87,6 @@ public static interface ExtensionProvider { */ public static interface ServiceProvider extends Root { - // ideally this would be part of the ExtensionProvider itself, but breaks - // too many assumptions in the API /** * A list of the services this extension provides. This method will be * called as the extension Root is installed in the RootHub. diff --git a/praxiscore-api/src/main/java/org/praxislive/core/services/ComponentFactory.java b/praxiscore-api/src/main/java/org/praxislive/core/services/ComponentFactory.java index ae961fdf..8be338a2 100644 --- a/praxiscore-api/src/main/java/org/praxislive/core/services/ComponentFactory.java +++ b/praxiscore-api/src/main/java/org/praxislive/core/services/ComponentFactory.java @@ -23,7 +23,6 @@ import java.util.Objects; import java.util.Optional; -import java.util.function.Supplier; import java.util.stream.Stream; import org.praxislive.core.Component; import org.praxislive.core.ComponentType; @@ -65,20 +64,6 @@ public interface ComponentFactory { */ public Stream rootTypes(); - @Deprecated - public default MetaData getMetaData(ComponentType type) { - Supplier redirect = () -> componentData(type); - return new MetaData(redirect) { - }; - } - - @Deprecated - public default MetaData getRootMetaData(ComponentType type) { - Supplier redirect = () -> rootData(type); - return new MetaData(redirect) { - }; - } - /** * Query the data associated with this component type. * @@ -86,14 +71,7 @@ public default MetaData getRootMetaData(ComponentType type) { * @return lookup of data */ public default Lookup componentData(ComponentType type) { - var metadata = getMetaData(type); - if (metadata == null) { - return null; - } else if (metadata.redirect != null) { - return Lookup.EMPTY; - } else { - return metadata.getLookup(); - } + return Lookup.EMPTY; } /** @@ -103,14 +81,7 @@ public default Lookup componentData(ComponentType type) { * @return lookup of data */ public default Lookup rootData(ComponentType type) { - var metadata = getRootMetaData(type); - if (metadata == null) { - return null; - } else if (metadata.redirect != null) { - return Lookup.EMPTY; - } else { - return metadata.getLookup(); - } + return Lookup.EMPTY; } /** @@ -139,21 +110,6 @@ public default Root createRoot(ComponentType type) throws ComponentInstantiation throw new ComponentInstantiationException(); } - @Deprecated - public default Root createRootComponent(ComponentType type) throws ComponentInstantiationException { - return createRoot(type); - } - - @Deprecated - public default Class getFactoryService() { - return ComponentFactoryService.class; - } - - @Deprecated - public default Class getRootFactoryService() { - return RootFactoryService.class; - } - /** * Optional service to redirect to for component instantiation. The control * on the service should follow the same shape as the default @@ -164,12 +120,7 @@ public default Class getRootFactoryService() { * @return optional service redirect */ public default Optional componentRedirect() { - var service = getFactoryService(); - if (service == null || ComponentFactoryService.class.equals(service)) { - return Optional.empty(); - } else { - return Optional.of(new Redirect(service, ComponentFactoryService.NEW_INSTANCE)); - } + return Optional.empty(); } /** @@ -182,104 +133,40 @@ public default Optional componentRedirect() { * @return optional service redirect */ public default Optional rootRedirect() { - var service = getRootFactoryService(); - if (service == null || RootFactoryService.class.equals(service)) { - return Optional.empty(); - } else { - return Optional.of(new Redirect(service, RootFactoryService.NEW_ROOT_INSTANCE)); - } - } - - @Deprecated - public static abstract class MetaData { - - private final Supplier redirect; - - public MetaData() { - this.redirect = null; - } - - private MetaData(Supplier redirect) { - this.redirect = redirect; - } - - public boolean isDeprecated() { - return false; - } - - public Optional findReplacement() { - return Optional.empty(); - } - - public Lookup getLookup() { - return redirect != null ? redirect.get() : Lookup.EMPTY; - } - + return Optional.empty(); } /** * A factory service redirect. See {@link #componentRedirect()} and * {@link #rootRedirect()}. */ - public static final class Redirect { + public record Redirect(Class service, String control) { - private final Class service; - private final String control; + } - /** - * Construct a redirect to the provided service and control. - * - * @param service service type to redirect to - * @param control control on service to redirect to - */ - public Redirect(Class service, String control) { - this.service = Objects.requireNonNull(service); - this.control = Objects.requireNonNull(control); - } + /** + * Mark a component deprecated (with optional replacement type). An instance + * should be added to the metadata lookup associated with the component + * type. + */ + public record Deprecated(Optional replacement) { /** - * Query the service to redirect to. - * - * @return service + * Deprecated without replacement. */ - public Class service() { - return service; + public Deprecated() { + this(Optional.empty()); } /** - * Query the control on the service to redirect to. + * Deprecated with replacement type. * - * @return control id + * @param replacement replacement type */ - public String control() { - return control; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 97 * hash + Objects.hashCode(this.service); - hash = 97 * hash + Objects.hashCode(this.control); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Redirect other = (Redirect) obj; - if (!Objects.equals(this.control, other.control)) { - return false; - } - return Objects.equals(this.service, other.service); + public Deprecated(ComponentType replacement) { + this(Optional.of(replacement)); } } + } diff --git a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioBodyContext.java b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioBodyContext.java deleted file mode 100644 index 3ee44b28..00000000 --- a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioBodyContext.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2020 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - */ -package org.praxislive.audio.code; - -import org.praxislive.code.CodeUtils; -import org.praxislive.code.ClassBodyContext; - -/** - * - */ -public class AudioBodyContext extends ClassBodyContext { - - public final static String TEMPLATE = - CodeUtils.load(AudioBodyContext.class, "resources/audio_template.pxj"); - - private final static String[] IMPORTS = CodeUtils.join( - CodeUtils.defaultImports(), new String[]{ - "org.jaudiolibs.pipes.*", - "org.jaudiolibs.pipes.units.*", - "org.praxislive.audio.code.userapi.*", - "static org.praxislive.audio.code.userapi.AudioConstants.*" - }); - - public AudioBodyContext() { - super(AudioCodeDelegate.class); - } - - @Override - public String[] getDefaultImports() { - return IMPORTS.clone(); - } - -} diff --git a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCode.java b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCode.java new file mode 100644 index 00000000..5480c0f0 --- /dev/null +++ b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCode.java @@ -0,0 +1,59 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2023 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code 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 Lesser General Public License + * version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit https://www.praxislive.org if you need additional information or + * have any questions. + */ +package org.praxislive.audio.code; + +import java.util.List; +import java.util.stream.Stream; +import org.praxislive.code.CodeFactory; +import org.praxislive.code.CodeUtils; + +/** + * Audio code utility functions. + */ +public class AudioCode { + + private static final List DEFAULT_IMPORTS + = Stream.concat(CodeUtils.defaultImports().stream(), + Stream.of("org.jaudiolibs.pipes.*", + "org.jaudiolibs.pipes.units.*", + "org.praxislive.audio.code.userapi.*", + "static org.praxislive.audio.code.userapi.AudioConstants.*")) + .toList(); + + private static final CodeFactory.Base BASE + = CodeFactory.base(AudioCodeDelegate.class, + DEFAULT_IMPORTS, + (task, delegate) -> new AudioCodeContext(new AudioCodeConnector(task, delegate))); + + private AudioCode() { + + } + + /** + * Access {@link CodeFactory.Base} for {@link AudioCodeDelegate}. + * + * @return code factory base for AudioCodeDelegate. + */ + public static CodeFactory.Base base() { + return BASE; + } +} diff --git a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeConnector.java b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeConnector.java index 23ced416..3f6d7930 100644 --- a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeConnector.java +++ b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeConnector.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -40,15 +40,20 @@ /** * */ -public class AudioCodeConnector extends CodeConnector { +public class AudioCodeConnector extends CodeConnector { private final Class previousClass; private final List ins; private final List outs; private final List ugens; - - public AudioCodeConnector(CodeFactory.Task task, - D delegate, + + public AudioCodeConnector(CodeFactory.Task task, + AudioCodeDelegate delegate) { + this(task, delegate, task.getPrevious()); + } + + public AudioCodeConnector(CodeFactory.Task task, + AudioCodeDelegate delegate, Class previousClass) { super(task, delegate); this.previousClass = previousClass; @@ -60,12 +65,12 @@ public AudioCodeConnector(CodeFactory.Task task, @Override @SuppressWarnings("deprecation") protected void analyseField(Field field) { - + if (AudioIn.class.isAssignableFrom(field.getType())) { In in = field.getAnnotation(In.class); if (in != null) { - AudioInPort.Descriptor aid = - AudioInPort.createDescriptor(this, in, field); + AudioInPort.Descriptor aid + = AudioInPort.createDescriptor(this, in, field); if (aid != null) { addPort(aid); ins.add(aid); @@ -73,12 +78,12 @@ protected void analyseField(Field field) { } } } - + if (AudioOut.class.isAssignableFrom(field.getType())) { Out out = field.getAnnotation(Out.class); if (out != null) { - AudioOutPort.Descriptor aod = - AudioOutPort.createDescriptor(this, out, field); + AudioOutPort.Descriptor aod + = AudioOutPort.createDescriptor(this, out, field); if (aod != null) { addPort(aod); outs.add(aod); @@ -86,21 +91,21 @@ protected void analyseField(Field field) { } } } - - if (field.isAnnotationPresent(UGen.class) && - Pipe.class.isAssignableFrom(field.getType())) { + + if (field.isAnnotationPresent(UGen.class) + && Pipe.class.isAssignableFrom(field.getType())) { UGenDescriptor ugd = UGenDescriptor.create(this, field); if (ugd != null) { ugens.add(ugd); return; } } - + if (AudioTable.class.isAssignableFrom(field.getType())) { P p = field.getAnnotation(P.class); if (p != null) { - ResourceProperty.Descriptor ipd = - ResourceProperty.Descriptor.create(this, p, field, TableLoader.getDefault()); + ResourceProperty.Descriptor ipd + = ResourceProperty.Descriptor.create(this, p, field, TableLoader.getDefault()); if (ipd != null) { addControl(ipd); if (shouldAddPort(field)) { @@ -110,24 +115,24 @@ protected void analyseField(Field field) { } } } - + super.analyseField(field); } - + UGenDescriptor[] extractUGens() { return ugens.toArray(new UGenDescriptor[ugens.size()]); } - + AudioInPort.Descriptor[] extractIns() { return ins.toArray(new AudioInPort.Descriptor[ins.size()]); } - + AudioOutPort.Descriptor[] extractOuts() { return outs.toArray(new AudioOutPort.Descriptor[outs.size()]); } - + Class getPreviousClass() { return previousClass; } - + } diff --git a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeContext.java b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeContext.java index 5bdf4023..8a72d814 100644 --- a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeContext.java +++ b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeContext.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -32,7 +32,7 @@ /** * */ -public class AudioCodeContext extends CodeContext { +public class AudioCodeContext extends CodeContext { private final UGenDescriptor[] ugens; private final AudioInPort.Descriptor[] ins; @@ -40,7 +40,7 @@ public class AudioCodeContext extends CodeContext connector) { + public AudioCodeContext(AudioCodeConnector connector) { super(connector, true); ugens = connector.extractUGens(); ins = connector.extractIns(); @@ -48,7 +48,7 @@ public AudioCodeContext(AudioCodeConnector connector) { } @Override - protected void configure(CodeComponent cmp, CodeContext oldCtxt) { + protected void configure(CodeComponent cmp, CodeContext oldCtxt) { super.configure(cmp, oldCtxt); // audio ins and outs attached in super call because they're ports for (UGenDescriptor ugd : ugens) { @@ -62,12 +62,12 @@ protected void hierarchyChanged() { } @Override - protected void starting(ExecutionContext source) { + protected void onInit() { setupDelegate(); } @Override - protected void stopping(ExecutionContext source) { + protected void onReset() { resetPorts(); } @@ -101,7 +101,7 @@ private void updateDelegate() { getLog().log(LogLevel.ERROR, e, "Exception thrown during update()"); } } - + private void setupUGens() { for (UGenDescriptor ugd : ugens) { Pipe ug = ugd.getUGen(); @@ -109,21 +109,21 @@ private void setupUGens() { ug.reset(); } } - + private void setupPorts() { for (AudioInPort.Descriptor aipd : ins) { - Utils.disconnectSinks(aipd.getPort().getPipe()); + Utils.disconnectSinks(aipd.port().getPipe()); } for (AudioOutPort.Descriptor aopd : outs) { - AudioOutPort.AudioOutPipe pipe = aopd.getPort().getPipe(); + AudioOutPort.AudioOutPipe pipe = aopd.port().getPipe(); Utils.disconnectSources(pipe); pipe.triggerSwitch(); } } - + private void resetPorts() { for (AudioOutPort.Descriptor aopd : outs) { - AudioOutPort.AudioOutPipe pipe = aopd.getPort().getPipe(); + AudioOutPort.AudioOutPipe pipe = aopd.port().getPipe(); pipe.resetSwitch(); } } diff --git a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeFactory.java b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeFactory.java deleted file mode 100644 index 7677010e..00000000 --- a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioCodeFactory.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2018 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - * - */ -package org.praxislive.audio.code; - -import org.praxislive.code.CodeContext; -import org.praxislive.code.CodeFactory; -import org.praxislive.core.ComponentType; - -/** - * - * - */ -public class AudioCodeFactory extends CodeFactory { - - private final static AudioBodyContext ABC = new AudioBodyContext(); - - public AudioCodeFactory(ComponentType type, - Class baseClass, - String sourceTemplate) { - super(ABC, type, baseClass, sourceTemplate); - } - - @Override - public Task task() { - return new AudioContextCreator(); - } - - private class AudioContextCreator extends Task { - - private AudioContextCreator() { - super(AudioCodeFactory.this); - } - - @Override - protected CodeContext createCodeContext(AudioCodeDelegate delegate) { - return new AudioCodeContext( - new AudioCodeConnector(this, delegate, getPrevious())); - } - - - } - -} diff --git a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioInPort.java b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioInPort.java index f08deef3..10a000fc 100644 --- a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioInPort.java +++ b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioInPort.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -31,7 +31,6 @@ import org.praxislive.code.PortDescriptor; import org.praxislive.code.userapi.AuxIn; import org.praxislive.code.userapi.In; -import org.praxislive.core.Port; import org.praxislive.core.PortInfo; import org.praxislive.core.types.PMap; import org.jaudiolibs.pipes.Buffer; @@ -49,7 +48,7 @@ private AudioInPort(AudioInPipe in) { super(in); this.in = in; } - + AudioInPipe getPipe() { return in; } @@ -81,7 +80,7 @@ protected void process(List list) { } - static class Descriptor extends PortDescriptor { + static class Descriptor extends PortDescriptor { private final static PortInfo INFO = PortInfo.create(AudioPort.class, PortInfo.Direction.IN, PMap.EMPTY); @@ -92,19 +91,16 @@ private Descriptor(String id, PortDescriptor.Category category, int index, Field field) { - super(id, category, index); + super(Descriptor.class, id, category, index); field.setAccessible(true); this.field = field; } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof AudioInPort) { - port = (AudioInPort) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + port = previous.port; } else { - if (previous != null) { - previous.disconnectAll(); - } port = new AudioInPort(new AudioInPipe()); } try { @@ -115,12 +111,12 @@ public void attach(CodeContext context, Port previous) { } @Override - public AudioInPort getPort() { + public AudioInPort port() { return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return INFO; } diff --git a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioOutPort.java b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioOutPort.java index df49489e..a0f740b5 100644 --- a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioOutPort.java +++ b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/AudioOutPort.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -31,7 +31,6 @@ import org.praxislive.code.PortDescriptor; import org.praxislive.code.userapi.AuxOut; import org.praxislive.code.userapi.Out; -import org.praxislive.core.Port; import org.praxislive.core.PortInfo; import org.praxislive.core.types.PMap; import org.praxislive.core.services.LogLevel; @@ -126,7 +125,7 @@ void resetSwitch() { } - static class Descriptor extends PortDescriptor { + static class Descriptor extends PortDescriptor { private final static PortInfo INFO = PortInfo.create(AudioPort.class, PortInfo.Direction.OUT, PMap.EMPTY); @@ -137,19 +136,16 @@ private Descriptor(String id, PortDescriptor.Category category, int index, Field field) { - super(id, category, index); + super(Descriptor.class, id, category, index); field.setAccessible(true); this.field = field; } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof AudioOutPort) { - port = (AudioOutPort) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + port = previous.port; } else { - if (previous != null) { - previous.disconnectAll(); - } port = new AudioOutPort(new AudioOutPipe()); } port.out.context = context; @@ -161,12 +157,12 @@ public void attach(CodeContext context, Port previous) { } @Override - public AudioOutPort getPort() { + public AudioOutPort port() { return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return INFO; } diff --git a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/UGenDescriptor.java b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/UGenDescriptor.java index c4567579..03aa759c 100644 --- a/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/UGenDescriptor.java +++ b/praxiscore-audio-code/src/main/java/org/praxislive/audio/code/UGenDescriptor.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -43,7 +43,7 @@ private UGenDescriptor(Field field, Field previousField, Pipe ugen) { this.ugen = ugen; } - void attach(AudioCodeContext context, CodeContext previous) { + void attach(AudioCodeContext context, CodeContext previous) { if (ugen == null) { try { ugen = (Pipe) previousField.get(previous.getDelegate()); diff --git a/praxiscore-audio-components/src/main/java/org/praxislive/audio/components/AudioComponents.java b/praxiscore-audio-components/src/main/java/org/praxislive/audio/components/AudioComponents.java index bd173727..b620603d 100644 --- a/praxiscore-audio-components/src/main/java/org/praxislive/audio/components/AudioComponents.java +++ b/praxiscore-audio-components/src/main/java/org/praxislive/audio/components/AudioComponents.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -21,16 +21,15 @@ */ package org.praxislive.audio.components; +import org.praxislive.audio.code.AudioCode; import org.praxislive.audio.code.AudioCodeDelegate; -import org.praxislive.audio.code.AudioCodeFactory; import org.praxislive.code.AbstractComponentFactory; -import org.praxislive.core.ComponentType; import org.praxislive.core.services.ComponentFactory; import org.praxislive.core.services.ComponentFactoryProvider; /** * - * + * */ public class AudioComponents implements ComponentFactoryProvider { @@ -40,24 +39,24 @@ public class AudioComponents implements ComponentFactoryProvider { public ComponentFactory getFactory() { return instance; } - + private static class Factory extends AbstractComponentFactory { - + private Factory() { build(); } private void build() { - + // custom add("audio:custom", AudioCustom.class, AudioCustom.TEMPLATE_PATH); - + add("audio:clock", AudioClock.class, AudioClock.TEMPLATE_PATH); add("audio:gain", AudioGain.class, AudioGain.TEMPLATE_PATH); add("audio:osc", AudioOsc.class, AudioOsc.TEMPLATE_PATH); add("audio:player", AudioPlayer.class, AudioPlayer.TEMPLATE_PATH); add("audio:looper", AudioLooper.class, AudioLooper.TEMPLATE_PATH); - + add("audio:fx:chorus", AudioFXChorus.class, AudioFXChorus.TEMPLATE_PATH); add("audio:fx:comb-filter", AudioFXCombFilter.class, AudioFXCombFilter.TEMPLATE_PATH); add("audio:fx:delay", AudioFXDelay.class, AudioFXDelay.TEMPLATE_PATH); @@ -65,18 +64,15 @@ private void build() { add("audio:fx:lfo-delay", AudioFXLFODelay.class, AudioFXLFODelay.TEMPLATE_PATH); add("audio:fx:overdrive", AudioFXOverdrive.class, AudioFXOverdrive.TEMPLATE_PATH); add("audio:fx:reverb", AudioFXReverb.class, AudioFXReverb.TEMPLATE_PATH); - + add("audio:analysis:level", AudioLevel.class, AudioLevel.TEMPLATE_PATH); - + } - - + private void add(String type, Class cls, String path) { - add(data( - new AudioCodeFactory(ComponentType.of(type), cls, source(path)) - )); + add(AudioCode.base().create(type, cls, source(path))); } - + } - + } diff --git a/praxiscore-base/src/main/java/org/praxislive/base/AbstractComponentFactory.java b/praxiscore-base/src/main/java/org/praxislive/base/AbstractComponentFactory.java index f05f7f3c..3a8ad172 100644 --- a/praxiscore-base/src/main/java/org/praxislive/base/AbstractComponentFactory.java +++ b/praxiscore-base/src/main/java/org/praxislive/base/AbstractComponentFactory.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -25,7 +25,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.stream.Stream; import org.praxislive.core.Component; import org.praxislive.core.services.ComponentFactory; @@ -39,8 +38,8 @@ */ public class AbstractComponentFactory implements ComponentFactory { - private final Map> componentMap; - private final Map> rootMap; + private final Map componentMap; + private final Map rootMap; protected AbstractComponentFactory() { componentMap = new LinkedHashMap<>(); @@ -48,23 +47,27 @@ protected AbstractComponentFactory() { } @Override - public Stream componentTypes() { + public final Stream componentTypes() { return componentMap.keySet().stream(); } @Override - public Stream rootTypes() { + public final Stream rootTypes() { return rootMap.keySet().stream(); } @Override - public Component createComponent(ComponentType type) throws ComponentInstantiationException { - MetaDataEx data = componentMap.get(type); + public final Component createComponent(ComponentType type) throws ComponentInstantiationException { + Lookup data = componentMap.get(type); if (data == null) { throw new IllegalArgumentException(); } try { - Class cl = data.getComponentClass(); + Class cl = data.findAll(Class.class) + .filter(Component.class::isAssignableFrom) + .map(cls -> cls.asSubclass(Component.class)) + .findFirst() + .orElseThrow(); return cl.getDeclaredConstructor().newInstance(); } catch (Exception ex) { throw new ComponentInstantiationException(ex); @@ -72,26 +75,30 @@ public Component createComponent(ComponentType type) throws ComponentInstantiati } @Override - public Root createRootComponent(ComponentType type) throws ComponentInstantiationException { - MetaDataEx data = rootMap.get(type); + public final Root createRoot(ComponentType type) throws ComponentInstantiationException { + Lookup data = rootMap.get(type); if (data == null) { throw new IllegalArgumentException(); } try { - Class cl = data.getComponentClass(); - return (Root) cl.getDeclaredConstructor().newInstance(); + Class cl = data.findAll(Class.class) + .filter(Root.class::isAssignableFrom) + .map(cls -> cls.asSubclass(Root.class)) + .findFirst() + .orElseThrow(); + return cl.getDeclaredConstructor().newInstance(); } catch (Exception ex) { throw new ComponentInstantiationException(ex); } } @Override - public ComponentFactory.MetaData getMetaData(ComponentType type) { + public final Lookup componentData(ComponentType type) { return componentMap.get(type); } - + @Override - public ComponentFactory.MetaData getRootMetaData(ComponentType type) { + public final Lookup rootData(ComponentType type) { return rootMap.get(type); } @@ -100,7 +107,7 @@ protected void add(String type, Class cls) { } protected void add(String type, Data info) { - componentMap.put(ComponentType.of(type), info.toMetaData()); + componentMap.put(ComponentType.of(type), info.toLookup()); } protected void addRoot(String type, Class cls) { @@ -108,95 +115,39 @@ protected void addRoot(String type, Class cls) { } protected void addRoot(String type, Data info) { - rootMap.put(ComponentType.of(type), info.toMetaData()); + rootMap.put(ComponentType.of(type), info.toLookup()); } public static Data data(Class cls) { return new Data<>(cls); } - private static class MetaDataEx extends ComponentFactory.MetaData { - - private final Class cls; - private final boolean test; - private final boolean deprecated; - private final ComponentType replacement; - private final Lookup lookup; - - private MetaDataEx(Class cls, - boolean test, - boolean deprecated, - ComponentType replacement, - Lookup lookup) { - this.cls = cls; - this.test = test; - this.deprecated = deprecated; - this.replacement = replacement; - this.lookup = lookup; - } - - public Class getComponentClass() { - return cls; - } - - @Override - public boolean isDeprecated() { - return deprecated; - } - - @Override - public Optional findReplacement() { - return Optional.ofNullable(replacement); - } - - @Override - public Lookup getLookup() { - return lookup == null ? super.getLookup() : lookup; - } - - - - } - public static class Data { - private final Class cls; - private boolean test; - private boolean deprecated; - private ComponentType replacement; - private List lookupList; + private final List lookupList; private Data(Class cls) { - this.cls = cls; - } - - public Data test() { - test = true; - return this; + lookupList = new ArrayList<>(); + lookupList.add(cls); } public Data deprecated() { - deprecated = true; + lookupList.add(new ComponentFactory.Deprecated()); return this; } public Data replacement(String type) { - replacement = ComponentType.of(type); - deprecated = true; + lookupList.add(new ComponentFactory.Deprecated(ComponentType.of(type))); return this; } public Data add(Object obj) { - if (lookupList == null) { - lookupList = new ArrayList(); - } lookupList.add(obj); return this; } - private MetaDataEx toMetaData() { - return new MetaDataEx(cls, test, deprecated, replacement, - lookupList == null ? null : Lookup.of(lookupList.toArray())); + private Lookup toLookup() { + return Lookup.of(lookupList.toArray()); } } } diff --git a/praxiscore-code-services/src/main/java/org/praxislive/code/services/ClassCacheKey.java b/praxiscore-code-services/src/main/java/org/praxislive/code/services/ClassCacheKey.java deleted file mode 100644 index 65f75a1a..00000000 --- a/praxiscore-code-services/src/main/java/org/praxislive/code/services/ClassCacheKey.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2018 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - */ -package org.praxislive.code.services; - -import java.util.Objects; -import org.praxislive.code.ClassBodyContext; - -/** - * - * - */ -class ClassCacheKey { - - private final ClassBodyContext cbc; - private final String source; - - ClassCacheKey(ClassBodyContext cbc, String source) { - this.cbc = cbc; - this.source = source; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 37 * hash + Objects.hashCode(this.cbc); - hash = 37 * hash + Objects.hashCode(this.source); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final ClassCacheKey other = (ClassCacheKey) obj; - if (!Objects.equals(this.cbc, other.cbc)) { - return false; - } - if (!Objects.equals(this.source, other.source)) { - return false; - } - return true; - } - -} diff --git a/praxiscore-code-services/src/main/java/org/praxislive/code/services/ComponentRegistry.java b/praxiscore-code-services/src/main/java/org/praxislive/code/services/ComponentRegistry.java index 9d5c909a..5a453b03 100644 --- a/praxiscore-code-services/src/main/java/org/praxislive/code/services/ComponentRegistry.java +++ b/praxiscore-code-services/src/main/java/org/praxislive/code/services/ComponentRegistry.java @@ -51,8 +51,9 @@ static ComponentRegistry getInstance() { Lookup.SYSTEM.findAll(ComponentFactoryProvider.class) .map(ComponentFactoryProvider::getFactory) - .filter(factory - -> factory.getFactoryService() == CodeComponentFactoryService.class) + .filter(factory -> factory.componentRedirect() + .filter(r -> r.service() == CodeComponentFactoryService.class) + .isPresent()) .forEachOrdered(factory -> { factory.componentTypes().forEachOrdered(type -> { componentCache.put(type, factory); @@ -62,8 +63,9 @@ static ComponentRegistry getInstance() { Lookup.SYSTEM.findAll(ComponentFactoryProvider.class) .map(ComponentFactoryProvider::getFactory) - .filter(factory - -> factory.getRootFactoryService() == CodeRootFactoryService.class) + .filter(factory -> factory.rootRedirect() + .filter(r -> r.service() == CodeRootFactoryService.class) + .isPresent()) .forEachOrdered(factory -> { factory.rootTypes().forEachOrdered(type -> { componentCache.put(type, factory); diff --git a/praxiscore-code-services/src/main/java/org/praxislive/code/services/DefaultCodeFactoryService.java b/praxiscore-code-services/src/main/java/org/praxislive/code/services/DefaultCodeFactoryService.java index 81ca8987..4b42a36f 100644 --- a/praxiscore-code-services/src/main/java/org/praxislive/code/services/DefaultCodeFactoryService.java +++ b/praxiscore-code-services/src/main/java/org/praxislive/code/services/DefaultCodeFactoryService.java @@ -228,8 +228,7 @@ protected Call processResponse(Call call) throws Exception { private CodeFactory findCodeFactory() throws Exception { ComponentType type = ComponentType.from(getActiveCall().args().get(0)).orElseThrow(); ComponentFactory cmpFactory = registry.getComponentFactory(type); - return cmpFactory.getMetaData(type).getLookup() - .find(CodeFactory.class).orElse(null); + return cmpFactory.componentData(type).find(CodeFactory.class).orElse(null); } private CodeComponent createComponent( @@ -279,8 +278,7 @@ protected Call processResponse(Call call) throws Exception { private CodeFactory findCodeFactory() throws Exception { ComponentType type = ComponentType.from(getActiveCall().args().get(0)).orElseThrow(); ComponentFactory cmpFactory = registry.getComponentFactory(type); - return cmpFactory.getRootMetaData(type).getLookup() - .find(CodeFactory.class).orElse(null); + return cmpFactory.rootData(type).find(CodeFactory.class).orElse(null); } private CodeComponent createComponent( diff --git a/praxiscore-code-services/src/main/java/org/praxislive/code/services/DefaultCompilerService.java b/praxiscore-code-services/src/main/java/org/praxislive/code/services/DefaultCompilerService.java index 601c45cb..1ed1b5d0 100644 --- a/praxiscore-code-services/src/main/java/org/praxislive/code/services/DefaultCompilerService.java +++ b/praxiscore-code-services/src/main/java/org/praxislive/code/services/DefaultCompilerService.java @@ -39,8 +39,6 @@ import javax.tools.JavaCompiler; import javax.tools.ToolProvider; import org.praxislive.code.CodeCompilerService; -import org.praxislive.code.services.tools.ClassBodyCompiler; -import org.praxislive.code.ClassBodyContext; import org.praxislive.code.LibraryResolver; import org.praxislive.code.services.tools.CompilerTask; import org.praxislive.code.services.tools.MessageHandler; @@ -181,11 +179,7 @@ public void call(Call call, PacketRouter router) throws Exception { if (call.isRequest()) { PMap map = PMap.from(call.args().get(0)).orElseThrow(); PMap ret; - if (map.keys().contains(CodeCompilerService.KEY_SOURCES)) { - ret = process(map); - } else { - ret = processLegacy(map); - } + ret = process(map); router.route(call.reply(ret)); } else { throw new UnsupportedOperationException(); @@ -229,35 +223,6 @@ private PMap process(PMap map) throws Exception { return response; } - @SuppressWarnings("deprecation") - private PMap processLegacy(PMap map) throws Exception { - String code = map.getString(CodeCompilerService.KEY_CODE, ""); - ClassBodyContext cbc = getClassBodyContext(map); - LogBuilder log = new LogBuilder(LogLevel.WARNING); - Map classFiles - = ClassBodyCompiler.create(cbc) - .setCompiler(compiler) - .setRelease(release) - .addMessageHandler(new LogMessageHandler(log)) - .extendClasspath(libFiles.stream() - .map(Path::toFile) - .collect(Collectors.toList())) - .compile(code); - PMap classes = convertClasses(classFiles); - PMap response = PMap.of(CodeCompilerService.KEY_CLASSES, classes, - CodeCompilerService.KEY_LOG, PArray.of(log.toList()), - EXT_CLASSPATH, libPath); - return response; - } - - @SuppressWarnings("deprecation") - private ClassBodyContext getClassBodyContext(PMap map) throws Exception { - String cbcClass = map.getString(CodeCompilerService.KEY_CLASS_BODY_CONTEXT, null); - return (ClassBodyContext) Class.forName(cbcClass, true, Thread.currentThread().getContextClassLoader()) - .getDeclaredConstructor() - .newInstance(); - } - private LogLevel getLogLevel(PMap map) { String level = map.getString(CodeCompilerService.KEY_LOG_LEVEL, null); if (level != null) { diff --git a/praxiscore-code-services/src/main/java/org/praxislive/code/services/tools/ClassBodyCompiler.java b/praxiscore-code-services/src/main/java/org/praxislive/code/services/tools/ClassBodyCompiler.java deleted file mode 100644 index bc1f0393..00000000 --- a/praxiscore-code-services/src/main/java/org/praxislive/code/services/tools/ClassBodyCompiler.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2021 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - */ -package org.praxislive.code.services.tools; - -import java.io.File; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import javax.lang.model.SourceVersion; -import javax.tools.JavaCompiler; -import org.praxislive.code.ClassBodyContext; - -/** - * - * - */ -public class ClassBodyCompiler { - - public final static String DEFAULT_CLASS_NAME = "$"; - - private final ClassBodyContext classBodyContext; - private final Set extClasspath; - private final String defClasspath; - private final String defModulepath; - - private MessageHandler messageHandler; - private JavaCompiler compiler; - private SourceVersion release; - - private ClassBodyCompiler(ClassBodyContext classBodyContext) { - this.classBodyContext = classBodyContext; - this.release = SourceVersion.RELEASE_11; - this.extClasspath = new LinkedHashSet<>(); - this.defClasspath = System.getProperty("java.class.path", ""); - this.defModulepath = System.getProperty("jdk.module.path", ""); - } - - public ClassBodyCompiler addMessageHandler(MessageHandler messageHandler) { - this.messageHandler = messageHandler; - return this; - } - - @Deprecated - public ClassBodyCompiler extendClasspath(Set libs) { - extClasspath.addAll(libs); - return this; - } - - public ClassBodyCompiler extendClasspath(List libs) { - extClasspath.addAll(libs); - return this; - } - - public ClassBodyCompiler setCompiler(JavaCompiler compiler) { - this.compiler = compiler; - return this; - } - - public ClassBodyCompiler setRelease(SourceVersion release) { - this.release = release; - return this; - } - - public Map compile(String code) throws CompilationException { - try { - String source = ClassBodyWrapper.create() - .className(DEFAULT_CLASS_NAME) - .extendsType(classBodyContext.getExtendedClass()) - .implementsTypes(List.of(classBodyContext.getImplementedInterfaces())) - .defaultImports(List.of(classBodyContext.getDefaultImports())) - .wrap(code); - - CompilerTask task = CompilerTask.create(Map.of(DEFAULT_CLASS_NAME, source)); - - if (messageHandler != null) { - task.messageHandler(messageHandler); - } - - List opts = List.of("-Xlint:all", "-proc:none", - "--release", String.valueOf(release.ordinal()), - "--add-modules", "ALL-MODULE-PATH", - "--module-path", defModulepath, - "-classpath", buildClasspath()); - - task.options(opts); - return task.compile(); - - } catch (CompilationException ex) { - throw new CompilationException(ex); - } catch (Exception ex) { - throw new CompilationException(ex); - } - } - - private String buildClasspath() { - if (extClasspath.isEmpty()) { - return defClasspath; - } else { - return extClasspath.stream() - .map(f -> f.getAbsolutePath()) - .collect(Collectors.joining(File.pathSeparator, - "", File.pathSeparator + defClasspath)); - } - } - - public static ClassBodyCompiler create(ClassBodyContext classBodyContext) { - return new ClassBodyCompiler(classBodyContext); - } - -} diff --git a/praxiscore-code-services/src/main/java/org/praxislive/code/services/tools/ClassBodyWrapper.java b/praxiscore-code-services/src/main/java/org/praxislive/code/services/tools/ClassBodyWrapper.java index fc26c1db..389303c4 100644 --- a/praxiscore-code-services/src/main/java/org/praxislive/code/services/tools/ClassBodyWrapper.java +++ b/praxiscore-code-services/src/main/java/org/praxislive/code/services/tools/ClassBodyWrapper.java @@ -67,7 +67,7 @@ public class ClassBodyWrapper { private ClassBodyWrapper() { defaultImports = List.of(); - className = ClassBodyCompiler.DEFAULT_CLASS_NAME; + className = "$"; implementedTypes = List.of(); } diff --git a/praxiscore-code/src/main/java/module-info.java b/praxiscore-code/src/main/java/module-info.java index 19617a83..47fefaa9 100644 --- a/praxiscore-code/src/main/java/module-info.java +++ b/praxiscore-code/src/main/java/module-info.java @@ -19,6 +19,5 @@ org.praxislive.code.internal.CodeProtocolsProvider; uses org.praxislive.code.CodeConnector.Plugin; - uses org.praxislive.code.TypeConverter.Provider; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/AbstractBasicProperty.java b/praxiscore-code/src/main/java/org/praxislive/code/AbstractBasicProperty.java deleted file mode 100644 index abeda5a0..00000000 --- a/praxiscore-code/src/main/java/org/praxislive/code/AbstractBasicProperty.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2019 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - */ -package org.praxislive.code; - -import java.util.List; -import org.praxislive.core.Value; -import org.praxislive.core.Call; -import org.praxislive.core.Control; -import org.praxislive.core.PacketRouter; - -/** - * An abstract property control base class. - *

- * Deprecated in favour of org.praxislive.base.AbstractProperty. - */ -@Deprecated -public abstract class AbstractBasicProperty implements Control { - - private boolean latestSet; - private long latest; - - @Override - public void call(Call call, PacketRouter router) throws Exception { - if (call.isRequest()) { - List args = call.args(); - int argCount = args.size(); - long time = call.time(); - if (argCount > 0) { - if (isLatest(time)) { - set(time, args.get(0)); - setLatest(time); - } - if (call.isReplyRequired()) { - router.route(call.reply(args)); - } - } else { - // ignore quiet hint? - router.route(call.reply(get())); - } - } else { -// throw new IllegalArgumentException(); - } - } - - protected abstract void set(long time, Value arg) throws Exception; - - protected abstract Value get(); - - private void setLatest(long time) { - latestSet = true; - latest = time; - } - - private boolean isLatest(long time) { - if (latestSet) { - return (time - latest) >= 0; - } else { - return true; - } - - } - -} diff --git a/praxiscore-code/src/main/java/org/praxislive/code/AbstractComponentFactory.java b/praxiscore-code/src/main/java/org/praxislive/code/AbstractComponentFactory.java index dc1b7cd3..c25cba9c 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/AbstractComponentFactory.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/AbstractComponentFactory.java @@ -27,11 +27,9 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Stream; -import org.praxislive.core.Component; import org.praxislive.core.services.ComponentFactory; import org.praxislive.core.ComponentType; import org.praxislive.core.Lookup; -import org.praxislive.core.Root; import org.praxislive.core.services.ComponentFactoryService; import org.praxislive.core.services.RootFactoryService; @@ -40,8 +38,16 @@ */ public class AbstractComponentFactory implements ComponentFactory { - private final Map componentMap; - private final Map rootMap; + private static final ComponentFactory.Redirect COMPONENT_REDIRECT + = new ComponentFactory.Redirect(CodeComponentFactoryService.class, + ComponentFactoryService.NEW_INSTANCE); + + private static final ComponentFactory.Redirect ROOT_REDIRECT + = new ComponentFactory.Redirect(CodeRootFactoryService.class, + RootFactoryService.NEW_ROOT_INSTANCE); + + private final Map componentMap; + private final Map rootMap; protected AbstractComponentFactory() { componentMap = new LinkedHashMap<>(); @@ -49,45 +55,45 @@ protected AbstractComponentFactory() { } @Override - public Stream componentTypes() { + public final Stream componentTypes() { return componentMap.keySet().stream(); } @Override - public Stream rootTypes() { + public final Stream rootTypes() { return rootMap.keySet().stream(); } @Override - public ComponentFactory.MetaData getMetaData(ComponentType type) { + public final Lookup componentData(ComponentType type) { return componentMap.get(type); } @Override - public ComponentFactory.MetaData getRootMetaData(ComponentType type) { + public final Lookup rootData(ComponentType type) { return rootMap.get(type); } @Override - public Class getFactoryService() { - return CodeComponentFactoryService.class; + public final Optional componentRedirect() { + return Optional.of(COMPONENT_REDIRECT); } @Override - public Class getRootFactoryService() { - return CodeRootFactoryService.class; + public final Optional rootRedirect() { + return Optional.of(ROOT_REDIRECT); } - + protected void add(Data info) { - componentMap.put(info.factory.componentType(), info.toMetaData()); + componentMap.put(info.factory.componentType(), info.toLookup()); } - + protected void add(CodeFactory factory) { - componentMap.put(factory.componentType(), new MetaData(factory)); + componentMap.put(factory.componentType(), Lookup.of(factory)); } - + protected void addRoot(CodeFactory factory) { - rootMap.put(factory.componentType(), new RootMetaData(factory)); + rootMap.put(factory.componentType(), Lookup.of(factory)); } protected Data data(CodeFactory factory) { @@ -98,65 +104,10 @@ protected String source(String location) { return CodeUtils.load(getClass(), location); } - private static class MetaData extends ComponentFactory.MetaData { - - private final boolean deprecated; - private final ComponentType replacement; - private final Lookup lookup; - - private MetaData( - boolean deprecated, - ComponentType replacement, - Lookup lookup) { - this.deprecated = deprecated; - this.replacement = replacement; - this.lookup = lookup; - } - - private MetaData(CodeFactory codeFactory) { - this.lookup = Lookup.of(codeFactory); - this.replacement = null; - this.deprecated = false; - } - - @Override - public boolean isDeprecated() { - return deprecated; - } - - @Override - public Optional findReplacement() { - return Optional.ofNullable(replacement); - } - - @Override - public Lookup getLookup() { - return lookup; - } - - } - - private static class RootMetaData extends ComponentFactory.MetaData { - - private final Lookup lookup; - - private RootMetaData(CodeFactory codeFactory) { - this.lookup = Lookup.of(codeFactory); - } - - @Override - public Lookup getLookup() { - return lookup; - } - - } - public static class Data { private final CodeFactory factory; private final List lookupList; - private boolean deprecated; - private ComponentType replacement; private Data(CodeFactory factory) { this.factory = factory; @@ -165,13 +116,12 @@ private Data(CodeFactory factory) { } public Data deprecated() { - deprecated = true; + lookupList.add(new ComponentFactory.Deprecated()); return this; } public Data replacement(String type) { - replacement = ComponentType.of(type); - deprecated = true; + lookupList.add(new ComponentFactory.Deprecated(ComponentType.of(type))); return this; } @@ -180,9 +130,8 @@ public Data add(Object obj) { return this; } - private MetaData toMetaData() { - return new MetaData(deprecated, replacement, - Lookup.of(lookupList.toArray())); + private Lookup toLookup() { + return Lookup.of(lookupList.toArray()); } } } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/BytesBinding.java b/praxiscore-code/src/main/java/org/praxislive/code/BytesBinding.java deleted file mode 100644 index 790d5978..00000000 --- a/praxiscore-code/src/main/java/org/praxislive/code/BytesBinding.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2020 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - * - */ -package org.praxislive.code; - -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import org.praxislive.core.ArgumentInfo; -import org.praxislive.core.types.PBytes; -import org.praxislive.core.types.PMap; -import org.praxislive.core.Value; -import org.praxislive.core.services.LogLevel; - -/** - * - */ -@Deprecated(forRemoval = true) -abstract class BytesBinding extends PropertyControl.Binding { - - @Override - public void set(Value value) throws Exception { - Optional bytes = PBytes.from(value); - if (bytes.isPresent()) { - setImpl(bytes.get()); - } else { - throw new IllegalArgumentException(); - } - } - - @Override - public void set(double value) throws Exception { - throw new IllegalArgumentException(); - } - - abstract void setImpl(PBytes value) throws Exception; - - @Override - public ArgumentInfo getArgumentInfo() { - return ArgumentInfo.of(PBytes.class, PMap.EMPTY); - } - - @Override - public Value getDefaultValue() { - return PBytes.EMPTY; - } - - static boolean isBindableFieldType(Class type) { - return type == PBytes.class || type == List.class || Serializable.class.isAssignableFrom(type); - } - - static BytesBinding create(CodeConnector connector, Field field) { - if (field.getType() == PBytes.class) { - return new PBytesField(field); - } else if (isSerializableList(field.getGenericType())) { - connector.getLog().log(LogLevel.WARNING, "Property " + field.getName() + " is a serialized list. Support for serializable lists is deprecated for removal"); - return new ListField(field); - } else if (isSerializableType(field.getGenericType())) { - connector.getLog().log(LogLevel.WARNING, "Property " + field.getName() + " is a serialized field. Support for serializable fields is deprecated for removal"); - return new SerializableField(field); - } else { - return null; - } - } - - private static boolean isSerializableType(java.lang.reflect.Type type) { - if (type instanceof Class) { - return Serializable.class.isAssignableFrom((Class) type); - } else if (type instanceof ParameterizedType) { - ParameterizedType parType = (ParameterizedType) type; - if (isSerializableType(parType.getRawType())) { - for (java.lang.reflect.Type actualType : parType.getActualTypeArguments()) { - if (!isSerializableType(actualType)) { - return false; - } - return true; - } - } - } - return false; - } - - private static boolean isSerializableList(java.lang.reflect.Type type) { - if (type instanceof ParameterizedType) { - ParameterizedType parType = (ParameterizedType) type; - if (List.class.equals(parType.getRawType())) { - for (java.lang.reflect.Type actualType : parType.getActualTypeArguments()) { - if (!isSerializableType(actualType)) { - return false; - } - return true; - } - } - } - return false; - } - - private static class PBytesField extends BytesBinding { - - private final Field field; - private CodeDelegate delegate; - - private PBytesField(Field field) { - this.field = field; - } - - @Override - protected void attach(CodeContext context) { - this.delegate = context.getDelegate(); - try { - set(PBytes.EMPTY); - } catch (Exception ex) { - // ignore - } - } - - @Override - void setImpl(PBytes value) throws Exception { - field.set(delegate, value); - } - - @Override - public Value get() { - try { - return (PBytes) field.get(delegate); - } catch (Exception ex) { - return PBytes.EMPTY; - } - } - - } - - private static class SerializableField extends BytesBinding { - - private final Field field; - private CodeDelegate delegate; - - private SerializableField(Field field) { - this.field = field; - } - - @Override - protected void attach(CodeContext context) { - this.delegate = context.getDelegate(); - try { - set(PBytes.EMPTY); - } catch (Exception ex) { - context.getLog().log(LogLevel.ERROR, ex); - } - } - - @Override - void setImpl(PBytes value) throws Exception { - if (value.isEmpty()) { - if (field.getType().isArray()) { - field.set(delegate, Array.newInstance(field.getType().getComponentType(), 0)); - } else { - field.set(delegate, field.getType().getDeclaredConstructor().newInstance()); - } - } else { - field.set(delegate, new ObjectInputStream(value.asInputStream()).readObject()); - } - } - - @Override - public Value get() { - try { - PBytes.OutputStream bos = new PBytes.OutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeObject(field.get(delegate)); - oos.close(); - return bos.toBytes(); - } catch (Exception ex) { - return PBytes.EMPTY; - } - } - - } - - private static class ListField extends BytesBinding { - - private final Field field; - private CodeDelegate delegate; - - private ListField(Field field) { - this.field = field; - } - - @Override - protected void attach(CodeContext context) { - this.delegate = context.getDelegate(); - try { - set(PBytes.EMPTY); - } catch (Exception ex) { - // ignore - } - } - - @Override - void setImpl(PBytes value) throws Exception { - List list; - if (value.isEmpty()) { - list = new ArrayList<>(); - } else { - list = (List) new ObjectInputStream(value.asInputStream()).readObject(); - } - field.set(delegate, list); - } - - @Override - public Value get() { - try { - List list = (List) field.get(delegate); - if (list.isEmpty()) { - return PBytes.EMPTY; - } - if (!ArrayList.class.equals(list.getClass())) { - list = new ArrayList<>(list); - } - PBytes.OutputStream bos = new PBytes.OutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeObject(list); - oos.close(); - return bos.toBytes(); - } catch (Exception ex) { - return PBytes.EMPTY; - } - } - - } - -} diff --git a/praxiscore-code/src/main/java/org/praxislive/code/ClassBodyContext.java b/praxiscore-code/src/main/java/org/praxislive/code/ClassBodyContext.java deleted file mode 100644 index 418c3235..00000000 --- a/praxiscore-code/src/main/java/org/praxislive/code/ClassBodyContext.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2021 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - */ -package org.praxislive.code; - -/** - * - * - */ -@Deprecated -public abstract class ClassBodyContext { - - public final static String KEY = "class-body-context"; - - private final Class superClass; - - protected ClassBodyContext(Class cls) { - superClass = cls; - } - - public final Class getExtendedClass() { - return superClass; - } - - public Class[] getImplementedInterfaces() { - return new Class[0]; - } - - public String[] getDefaultImports() { - return new String[0]; - } - - @Override - public int hashCode() { - return getClass().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - return obj == null ? false : this.getClass().equals(obj.getClass()); - } - - @Deprecated - public static class Default extends ClassBodyContext { - - public Default() { - super(DefaultCodeDelegate.class); - } - - @Override - public String[] getDefaultImports() { - return CodeUtils.defaultImports(); - } - - } - - -} diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeCompilerService.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeCompilerService.java index 26aad1a0..a7931bb1 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeCompilerService.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeCompilerService.java @@ -46,13 +46,6 @@ public class CodeCompilerService implements Service { .control(COMPILE, COMPILE_INFO) ); - // parameter keys - @Deprecated - public static final String KEY_CLASS_BODY_CONTEXT = "class-body-context"; - - @Deprecated - public static final String KEY_CODE = "code"; - public static final String KEY_SOURCES = "sources"; public static final String KEY_SHARED_CLASSES = "shared-classes"; diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeComponent.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeComponent.java index 2667478d..920e691a 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeComponent.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeComponent.java @@ -81,9 +81,7 @@ public void parentNotify(Container parent) throws VetoException { } private void disconnectAll() { - for (String portID : codeCtxt.getPortIDs()) { - getPort(portID).disconnectAll(); - } + codeCtxt.portIDs().map(codeCtxt::getPort).forEach(Port::disconnectAll); } @Override diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeComponentFactoryService.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeComponentFactoryService.java index d48ebd56..f7f71f37 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeComponentFactoryService.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeComponentFactoryService.java @@ -22,8 +22,6 @@ package org.praxislive.code; -import java.util.stream.Stream; -import org.praxislive.core.Protocol; import org.praxislive.core.services.ComponentFactoryService; /** @@ -32,15 +30,5 @@ */ public class CodeComponentFactoryService extends ComponentFactoryService { - - @Deprecated - public static class Provider implements Protocol.TypeProvider { - - @Override - public Stream types() { - return Stream.of(new Protocol.Type<>(CodeComponentFactoryService.class)); - } - } - } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeConnector.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeConnector.java index 1c0175d2..a0ede15b 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeConnector.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeConnector.java @@ -91,14 +91,14 @@ public abstract class CodeConnector { private final CodeFactory factory; private final LogBuilder log; private final D delegate; - private final Map controls; - private final Map ports; - private final Map refs; + private final Map> controls; + private final Map> ports; + private final Map> refs; private List plugins; - private Map extControls; - private Map extPorts; - private Map extRefs; + private Map> extControls; + private Map> extPorts; + private Map> extRefs; private ComponentInfo info; private int syntheticIdx = Integer.MIN_VALUE; private int internalIdx = Integer.MIN_VALUE; @@ -158,7 +158,7 @@ public LogBuilder getLog() { * * @return map of control descriptors by ID */ - protected Map extractControls() { + protected Map> extractControls() { return extControls; } @@ -169,7 +169,7 @@ protected Map extractControls() { * * @return map of port descriptors by ID */ - protected Map extractPorts() { + protected Map> extractPorts() { return extPorts; } @@ -180,7 +180,7 @@ protected Map extractPorts() { * * @return map of reference descriptors by ID */ - protected Map extractRefs() { + protected Map> extractRefs() { return extRefs; } @@ -212,29 +212,33 @@ private void buildExternalData() { info = buildComponentInfo(extControls, extPorts); } - private Map buildExternalControlMap() { + private Map> buildExternalControlMap() { + Comparator> cmp + = Comparator.comparing((ControlDescriptor cd) -> cd.category()) + .thenComparingInt((ControlDescriptor cd) -> cd.index()) + .thenComparing((ControlDescriptor cd) -> cd.id(), String.CASE_INSENSITIVE_ORDER); return controls.values().stream() - .sorted(Comparator.comparing(ControlDescriptor::getCategory) - .thenComparingInt(ControlDescriptor::getIndex) - .thenComparing(ControlDescriptor::getID, String.CASE_INSENSITIVE_ORDER)) - .collect(Collectors.toMap(ControlDescriptor::getID, + .sorted(cmp) + .collect(Collectors.toMap((ControlDescriptor cd) -> cd.id(), Function.identity(), (cd1, cd2) -> cd2, LinkedHashMap::new)); } - private Map buildExternalPortMap() { + private Map> buildExternalPortMap() { + Comparator> cmp + = Comparator.comparing((PortDescriptor pd) -> pd.category()) + .thenComparingInt((PortDescriptor pd) -> pd.index()) + .thenComparing((PortDescriptor pd) -> pd.id(), String.CASE_INSENSITIVE_ORDER); return ports.values().stream() - .sorted(Comparator.comparing(PortDescriptor::getCategory) - .thenComparingInt(PortDescriptor::getIndex) - .thenComparing(PortDescriptor::getID, String.CASE_INSENSITIVE_ORDER)) - .collect(Collectors.toMap(PortDescriptor::getID, + .sorted(cmp) + .collect(Collectors.toMap((PortDescriptor pd) -> pd.id(), Function.identity(), (pd1, pd2) -> pd2, LinkedHashMap::new)); } - private Map buildExternalRefsMap() { + private Map> buildExternalRefsMap() { if (refs.isEmpty()) { return Collections.EMPTY_MAP; } else { @@ -253,8 +257,8 @@ private Map buildExternalRefsMap() { * @param ports map of port IDs and descriptors * @return component info */ - protected ComponentInfo buildComponentInfo(Map controls, - Map ports) { + protected ComponentInfo buildComponentInfo(Map> controls, + Map> ports) { var cmp = Info.component(); buildBaseComponentInfo(cmp); buildControlInfo(cmp, controls); @@ -271,7 +275,7 @@ protected ComponentInfo buildComponentInfo(Map contro protected void buildBaseComponentInfo(Info.ComponentInfoBuilder cmp) { cmp.merge(ComponentProtocol.API_INFO); cmp.property(ComponentInfo.KEY_DYNAMIC, true); - cmp.property(ComponentInfo.KEY_COMPONENT_TYPE, factory.getComponentType()); + cmp.property(ComponentInfo.KEY_COMPONENT_TYPE, factory.componentType()); } /** @@ -280,10 +284,10 @@ protected void buildBaseComponentInfo(Info.ComponentInfoBuilder cmp) { * @param cmp component info builder * @param controls map of control descriptors */ - protected void buildControlInfo(Info.ComponentInfoBuilder cmp, Map controls) { + protected void buildControlInfo(Info.ComponentInfoBuilder cmp, Map> controls) { for (var e : controls.entrySet()) { if (!excludeFromInfo(e.getKey(), e.getValue())) { - cmp.control(e.getKey(), e.getValue().getInfo()); + cmp.control(e.getKey(), e.getValue().controlInfo()); } } } @@ -294,19 +298,19 @@ protected void buildControlInfo(Info.ComponentInfoBuilder cmp, Map ports) { + protected void buildPortInfo(Info.ComponentInfoBuilder cmp, Map> ports) { for (var e : ports.entrySet()) { if (!excludeFromInfo(e.getKey(), e.getValue())) { - cmp.port(e.getKey(), e.getValue().getInfo()); + cmp.port(e.getKey(), e.getValue().portInfo()); } } } - private boolean excludeFromInfo(String id, ControlDescriptor desc) { - return desc.getInfo() == null || id.startsWith("_"); + private boolean excludeFromInfo(String id, ControlDescriptor desc) { + return desc.controlInfo() == null || id.startsWith("_"); } - private boolean excludeFromInfo(String id, PortDescriptor desc) { + private boolean excludeFromInfo(String id, PortDescriptor desc) { return id.startsWith("_"); } @@ -316,7 +320,7 @@ private boolean excludeFromInfo(String id, PortDescriptor desc) { * @param ctl control descriptor */ public void addControl(ControlDescriptor ctl) { - controls.put(ctl.getID(), ctl); + controls.put(ctl.id(), ctl); } /** @@ -325,7 +329,7 @@ public void addControl(ControlDescriptor ctl) { * @param port port descriptor */ public void addPort(PortDescriptor port) { - ports.put(port.getID(), port); + ports.put(port.id(), port); } /** @@ -334,7 +338,7 @@ public void addPort(PortDescriptor port) { * @param ref reference descriptor */ public void addReference(ReferenceDescriptor ref) { - refs.put(ref.getID(), ref); + refs.put(ref.id(), ref); } /** @@ -364,8 +368,8 @@ protected ControlDescriptor createInfoControl(int index) { * @param index position of control * @return code control descriptor */ - protected ControlDescriptor createCodeControl(int index) { - return new CodeProperty.Descriptor<>(factory, index); + protected ControlDescriptor createCodeControl(int index) { + return new CodeProperty.Descriptor(factory, index); } /** @@ -512,7 +516,7 @@ private boolean analyseInputField(In ann, Field field) { InputImpl.Descriptor odsc = InputImpl.createDescriptor(this, ann, field); if (odsc != null) { addPort(odsc); - addControl(InputPortControl.Descriptor.createInput(odsc.getID(), odsc.getIndex(), odsc)); + addControl(InputPortControl.Descriptor.createInput(odsc.id(), odsc.index(), odsc)); return true; } @@ -535,7 +539,7 @@ private boolean analyseAuxInputField(AuxIn ann, Field field) { InputImpl.Descriptor odsc = InputImpl.createDescriptor(this, ann, field); if (odsc != null) { addPort(odsc); - addControl(InputPortControl.Descriptor.createAuxInput(odsc.getID(), odsc.getIndex(), odsc)); + addControl(InputPortControl.Descriptor.createAuxInput(odsc.id(), odsc.index(), odsc)); return true; } @@ -619,7 +623,7 @@ private boolean analyseTriggerField(T ann, Field field) { private boolean analyseResourcePropertyField(P ann, Field field) { if (field.getAnnotation(Type.Resource.class) != null && String.class.equals(field.getType())) { - ResourceProperty.Descriptor rpd + ResourceProperty.Descriptor rpd = ResourceProperty.Descriptor.create(this, ann, field, ResourceProperty.getStringLoader()); if (rpd != null) { addControl(rpd); @@ -743,7 +747,7 @@ private boolean analyseInputMethod(In ann, Method method) { = MethodInput.createDescriptor(this, ann, method); if (desc != null) { addPort(desc); - addControl(InputPortControl.Descriptor.createInput(desc.getID(), desc.getIndex(), desc)); + addControl(InputPortControl.Descriptor.createInput(desc.id(), desc.index(), desc)); return true; } else { return false; @@ -755,7 +759,7 @@ private boolean analyseAuxInputMethod(AuxIn ann, Method method) { = MethodInput.createDescriptor(this, ann, method); if (desc != null) { addPort(desc); - addControl(InputPortControl.Descriptor.createAuxInput(desc.getID(), desc.getIndex(), desc)); + addControl(InputPortControl.Descriptor.createAuxInput(desc.id(), desc.index(), desc)); return true; } else { return false; diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeContainer.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeContainer.java index 6a4e155f..92884c3f 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeContainer.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeContainer.java @@ -406,58 +406,60 @@ protected void notifyChild(Component child) throws VetoException { } - private static class ContainerControlDescriptor extends ControlDescriptor { + private static class ContainerControlDescriptor + extends ControlDescriptor { private final ControlInfo info; private Control control; ContainerControlDescriptor(String id, ControlInfo info, int index) { - super(id, Category.Internal, index); + super(ContainerControlDescriptor.class, id, Category.Internal, index); this.info = info; } @Override - public void attach(CodeContext context, Control previous) { - control = ((CodeContainer) context.getComponent()).getContainerControl(getID()); + public void attach(CodeContext context, ContainerControlDescriptor previous) { + control = ((CodeContainer) context.getComponent()).getContainerControl(id()); } @Override - public Control getControl() { + public Control control() { return control; } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return info; } } - private static class PortProxiesControlDescriptor extends ControlDescriptor { + private static class PortProxiesControlDescriptor + extends ControlDescriptor { private final ControlInfo info; private Control control; PortProxiesControlDescriptor(String id, int index) { - super(id, Category.Internal, index); + super(PortProxiesControlDescriptor.class, id, Category.Internal, index); info = Info.control().property() .input(PMap.class).defaultValue(PMap.EMPTY).build(); } @Override - public void attach(CodeContext context, Control previous) { + public void attach(CodeContext context, PortProxiesControlDescriptor previous) { control = ((CodeContainer) context.getComponent()).proxyProperty; } @Override - public Control getControl() { + public Control control() { return control; } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return info; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeContext.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeContext.java index b0663e0d..d204a8d3 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeContext.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeContext.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2022 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -23,6 +23,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -31,6 +32,7 @@ import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Stream; import org.praxislive.code.userapi.Async; import org.praxislive.core.Call; import org.praxislive.core.Component; @@ -61,9 +63,10 @@ */ public abstract class CodeContext { - private final Map controls; - private final Map ports; - private final Map refs; + private final Map> controls; + private final Map> ports; + private final Map> refs; + private final List descriptors; private final ComponentInfo info; private final D delegate; @@ -112,6 +115,9 @@ protected CodeContext(CodeConnector connector, boolean requireClock) { log = new LogBuilder(LogLevel.ERROR); this.requireClock = requireClock || connector.requiresClock(); this.responseHandler = Objects.requireNonNull((ResponseHandler) controls.get(ResponseHandler.ID)); + descriptors = new ArrayList<>(controls.values()); + descriptors.addAll(ports.values()); + descriptors.addAll(refs.values()); } catch (Exception e) { // Logger.getLogger(CodeContext.class.getName()).log(Level.FINE, "", e); throw e; @@ -143,42 +149,25 @@ protected void configure(CodeComponent cmp, CodeContext oldCtxt) { } private void configureControls(CodeContext oldCtxt) { - Map oldControls = oldCtxt == null - ? Collections.emptyMap() : oldCtxt.controls; - for (Map.Entry entry : controls.entrySet()) { - ControlDescriptor oldCD = oldControls.remove(entry.getKey()); - if (oldCD != null) { - entry.getValue().attach(this, oldCD.getControl()); - } else { - entry.getValue().attach(this, null); - } - } - for (ControlDescriptor oldCD : oldControls.values()) { - oldCD.dispose(); - } + Map> oldControls = oldCtxt == null + ? Collections.EMPTY_MAP : oldCtxt.controls; + controls.forEach((id, cd) -> cd.handleAttach(this, oldControls.remove(id))); + oldControls.forEach((id, cd) -> cd.dispose()); } private void configurePorts(CodeContext oldCtxt) { - Map oldPorts = oldCtxt == null - ? Collections.emptyMap() : oldCtxt.ports; - for (Map.Entry entry : ports.entrySet()) { - PortDescriptor oldPD = oldPorts.remove(entry.getKey()); - if (oldPD != null) { - entry.getValue().attach(this, oldPD.getPort()); - } else { - entry.getValue().attach(this, null); - } - } - for (PortDescriptor oldPD : oldPorts.values()) { - oldPD.getPort().disconnectAll(); - oldPD.dispose(); - } + Map> oldPorts = oldCtxt == null + ? Collections.EMPTY_MAP : oldCtxt.ports; + ports.forEach((id, pd) -> pd.handleAttach(this, oldPorts.remove(id))); + oldPorts.forEach((id, pd) -> { + pd.dispose(); + }); } private void configureRefs(CodeContext oldCtxt) { - Map oldRefs = oldCtxt == null + Map> oldRefs = oldCtxt == null ? Collections.EMPTY_MAP : oldCtxt.refs; - refs.forEach((id, ref) -> ref.attach(this, oldRefs.remove(id))); + refs.forEach((id, ref) -> ref.handleAttach(this, oldRefs.remove(id))); oldRefs.forEach((id, ref) -> ref.dispose()); } @@ -224,68 +213,57 @@ final void handleStateChanged(ExecutionContext source, boolean full) { if (execState == source.getState()) { return; } - if (source.getState() == ExecutionContext.State.IDLE) { - stopping(source, full); + if (full && source.getState() == ExecutionContext.State.IDLE + && execState != ExecutionContext.State.NEW) { + onStop(); + descriptors.forEach(Descriptor::onStop); } - reset(full); + onReset(); + descriptors.forEach(Descriptor::onReset); update(source.getTime()); execState = source.getState(); if (execState == ExecutionContext.State.ACTIVE) { - starting(source, full); + descriptors.forEach(Descriptor::onInit); + if (full) { + descriptors.forEach(Descriptor::onStart); + } + onInit(); + if (full) { + onStart(); + } } flush(); } /** - * Hook called when the execution context is started (moves to state - * {@link ExecutionContext.State#ACTIVE}) or the context is added to a - * component within an active execution context. Full start will be true in - * the former case when the execution context itself is changing state. - *

- * This method may be overridden in subclasses. The default implementation - * delegates to {@link #starting(org.praxislive.core.ExecutionContext)}. - * - * @param source execution context - * @param fullStart whether the context itself is transitioning state + * Hook called when the code context becomes active, either as a result of + * the execution context becoming active or the code context being attached + * to a component within an active execution context. */ - protected void starting(ExecutionContext source, boolean fullStart) { - starting(source); + protected void onInit() { + } /** - * Hook called when the execution context is started (moves to state - * {@link ExecutionContext.State#ACTIVE}) or the context is added to a - * component within an active execution context. - * - * @param source execution context + * Hook called when the execution context becomes active. The + * {@link #onInit()} hook will always have been called before this hook. */ - protected void starting(ExecutionContext source) { + protected void onStart() { + } /** - * Hook called when the execution context is stopped (moves away from state - * {@link ExecutionContext.State#ACTIVE}) or the context is removed from a - * component within an active execution context. Full stop will be true in - * the former case when the execution context itself is changing state. - *

- * This method may be overridden in subclasses. The default implementation - * delegates to {@link #stopping(org.praxislive.core.ExecutionContext)}. - * - * @param source execution context - * @param fullStop whether the context itself is transitioning state + * Hook called when the execution context is stopping. */ - protected void stopping(ExecutionContext source, boolean fullStop) { - stopping(source); + protected void onStop() { + } /** - * Hook called when the execution context is stopped (moves away from state - * {@link ExecutionContext.State#ACTIVE}) or the context is removed from a - * component within an active execution context. - * - * @param source execution context + * Hook called when the context is being reset. */ - protected void stopping(ExecutionContext source) { + protected void onReset() { + } final void handleTick(ExecutionContext source) { @@ -304,17 +282,15 @@ protected void tick(ExecutionContext source) { } /** - * Reset all control, port and reference descriptors. A full reset generally - * happens on execution context state changes as opposed to code change - * transitions. Descriptors may handle this differently - eg. clear injected - * values or dispose references on full. - * - * @param full whether reset is full (eg. execution state change) + * Reset and (if active) reinitialize all control, port and reference + * descriptors. This does not call the {@link #onReset()} or + * {@link #onInit()} hooks. */ - protected final void reset(boolean full) { - controls.values().forEach(cd -> cd.reset(full)); - ports.values().forEach(pd -> pd.reset(full)); - refs.values().forEach(rd -> rd.reset(full)); + protected final void resetAndInitialize() { + descriptors.forEach(Descriptor::onReset); + if (execCtxt.getState() == ExecutionContext.State.ACTIVE) { + descriptors.forEach(Descriptor::onInit); + } } final void handleDispose() { @@ -362,7 +338,7 @@ public D getDelegate() { */ protected Control getControl(String id) { ControlDescriptor cd = controls.get(id); - return cd == null ? null : cd.getControl(); + return cd == null ? null : cd.control(); } /** @@ -381,10 +357,8 @@ protected ControlDescriptor getControlDescriptor(String id) { * * @return control IDs */ - @Deprecated - protected String[] getControlIDs() { - Set keySet = controls.keySet(); - return keySet.toArray(new String[keySet.size()]); + protected Stream controlIDs() { + return controls.keySet().stream(); } /** @@ -395,7 +369,7 @@ protected String[] getControlIDs() { */ protected Port getPort(String id) { PortDescriptor pd = ports.get(id); - return pd == null ? null : pd.getPort(); + return pd == null ? null : pd.port(); } /** @@ -413,10 +387,8 @@ protected PortDescriptor getPortDescriptor(String id) { * * @return port IDs */ - @Deprecated - protected String[] getPortIDs() { - Set keySet = ports.keySet(); - return keySet.toArray(new String[keySet.size()]); + protected Stream portIDs() { + return ports.keySet().stream(); } /** @@ -438,8 +410,8 @@ protected ComponentInfo getInfo() { protected ControlAddress getAddress(Control control) { ComponentAddress ad = cmp == null ? null : cmp.getAddress(); if (ad != null) { - for (Map.Entry ce : controls.entrySet()) { - if (ce.getValue().getControl() == control) { + for (Map.Entry> ce : controls.entrySet()) { + if (ce.getValue().control() == control) { return ControlAddress.of(ad, ce.getKey()); } } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeFactory.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeFactory.java index 277d18b1..287ec353 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeFactory.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeFactory.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Supplier; import org.praxislive.core.ComponentType; @@ -60,33 +59,6 @@ public class CodeFactory { private final Supplier> componentCreator; private final BiFunction, D, CodeContext> contextCreator; - /** - * Construct CodeFactory for a type extending the base code delegate type. - * This constructor allows for a precompiled default delegate class to be - * provided. This must correspond to the code compiled from wrapping the - * provided class body template in the provided class body context. - * - * @param cbc class body context that will wrap source code - * @param type the component type - * @param defaultCls precompiled default delegate - * @param template code template reflecting default delegate - */ - @Deprecated - protected CodeFactory( - ClassBodyContext cbc, - ComponentType type, - Class defaultCls, - String template) { - this.baseClass = cbc.getExtendedClass(); - this.baseImports = List.of(cbc.getDefaultImports()); - this.lookup = Lookup.of(cbc); - this.type = type; - this.defaultDelegateClass = defaultCls; - this.template = template; - this.componentCreator = CodeComponent::new; - this.contextCreator = null; - } - private CodeFactory(Base base, ComponentType type, Class defaultCls, String template) { this.baseClass = base.baseClass; this.baseImports = base.baseImports; @@ -98,33 +70,6 @@ private CodeFactory(Base base, ComponentType type, Class default this.template = Objects.requireNonNull(template); } - /** - * Construct CodeFactory for a type extending the base code delegate type. - * This constructor is used where the default delegate is compiled from the - * template at runtime. - * - * @param cbc class body context that will wrap source code - * @param type the component type - * @param template code template reflecting default delegate - */ - @Deprecated - protected CodeFactory( - ClassBodyContext cbc, - ComponentType type, - String template) { - this(cbc, type, null, template); - } - - /** - * Get the component type. - * - * @return component type - */ - @Deprecated - public final ComponentType getComponentType() { - return type; - } - /** * Get the component type. * @@ -134,40 +79,6 @@ public final ComponentType componentType() { return type; } - /** - * Class body context used to create wrapping class for source code. - * - * @return class body context - */ - @SuppressWarnings("unchecked") - @Deprecated - public final ClassBodyContext getClassBodyContext() { - return (ClassBodyContext) lookup.find(ClassBodyContext.class) - .orElseGet(() -> new ClassBodyContext(baseClass) { - @Override - public String[] getDefaultImports() { - return baseImports.toArray(String[]::new); - } - - }); - } - - final String getClassBodyContextName() { - return lookup.find(ClassBodyContext.class) - .map(cbc -> cbc.getClass().getName()) - .orElse(ClassBodyContext.Default.class.getName()); - } - - /** - * The source template corresponding to the default delegate class. - * - * @return source template - */ - @Deprecated - public final String getSourceTemplate() { - return template; - } - /** * The source template corresponding to the default delegate class. * @@ -177,16 +88,6 @@ public final String sourceTemplate() { return template; } - /** - * Optional precompiled version of the default delegate class. - * - * @return optional precompiled default delegate - */ - @Deprecated - public final Optional> getDefaultDelegateClass() { - return Optional.ofNullable(defaultDelegateClass); - } - /** * Query the default delegate class. * @@ -389,7 +290,7 @@ public CodeContext createContext(D delegate) { * * @return log builder */ - protected LogBuilder getLog() { + public LogBuilder getLog() { return log; } @@ -399,7 +300,7 @@ protected LogBuilder getLog() { * * @return previous delegate class */ - protected Class getPrevious() { + public Class getPrevious() { return previous; } @@ -408,7 +309,7 @@ protected Class getPrevious() { * * @return code factory */ - protected CodeFactory getFactory() { + public CodeFactory getFactory() { return factory; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeProperty.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeProperty.java index 04c6ed14..14e978ed 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeProperty.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeProperty.java @@ -193,25 +193,23 @@ SharedCodeService.DependentTask createSharedCodeReloadTask() { sourceArgs.get(0).toString(), getDelegateClass()); } - static class Descriptor - extends ControlDescriptor { + static class Descriptor extends ControlDescriptor { - private final CodeFactory factory; + private final CodeFactory factory; private final ControlInfo info; private CodeProperty control; - public Descriptor(CodeFactory factory, int index) { - super("code", Category.Internal, index); + public Descriptor(CodeFactory factory, int index) { + super(Descriptor.class, "code", Category.Internal, index); this.factory = factory; this.info = createInfo(factory); } - private ControlInfo createInfo(CodeFactory factory) { + private ControlInfo createInfo(CodeFactory factory) { return ControlInfo.createPropertyInfo( ArgumentInfo.of(PString.class, PMap.of(PString.KEY_MIME_TYPE, MIME_TYPE, - ArgumentInfo.KEY_TEMPLATE, factory.getSourceTemplate(), - ClassBodyContext.KEY, factory.getClassBodyContextName(), + ArgumentInfo.KEY_TEMPLATE, factory.sourceTemplate(), CodeFactory.BASE_CLASS_KEY, factory.baseClass().getName(), CodeFactory.BASE_IMPORTS_KEY, factory.baseImports().stream().map(PString::of).collect(PArray.collector())) @@ -221,24 +219,25 @@ private ControlInfo createInfo(CodeFactory factory) { } @Override - @SuppressWarnings("unchecked") - public void attach(CodeContext context, Control previous) { - if (previous instanceof CodeProperty - && ((CodeProperty) previous).factory == factory) { - control = (CodeProperty) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null && previous.factory == factory) { + control = previous.control; } else { + if (previous != null) { + previous.dispose(); + } control = new CodeProperty<>(factory); } control.attach(context); } @Override - public Control getControl() { + public Control control() { return control; } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return info; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeRoot.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeRoot.java index b7a41f79..bf01c9d9 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeRoot.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeRoot.java @@ -54,7 +54,7 @@ * @param wrapped delegate type */ public class CodeRoot extends CodeComponent implements Root { - + private static final String SHARED_CODE = "shared-code"; private final RootImpl root; @@ -62,7 +62,7 @@ public class CodeRoot extends CodeComponent imple private final Control stopControl; private final Control isRunningControl; private final SharedCodeProperty sharedCode; - + private Lookup lookup; CodeRoot() { @@ -196,17 +196,15 @@ public CodeRoot getComponent() { } @Override - protected void starting(ExecutionContext source, boolean fullStart) { - if (fullStart && driverDesc != null) { + protected void onStart() { + if (driverDesc != null) { getComponent().root.installDelegate(driverDesc); } } @Override - protected void stopping(ExecutionContext source, boolean fullStop) { - if (fullStop) { - getComponent().root.uninstallDelegate(); - } + protected void onStop() { + getComponent().root.uninstallDelegate(); } } @@ -341,24 +339,25 @@ private void handleUpdate(long time) { } - private static class RootControlDescriptor extends ControlDescriptor { + private static class RootControlDescriptor + extends ControlDescriptor { private final String controlID; private CodeRoot root; private RootControlDescriptor(String controlID, int index) { - super(controlID, Category.Internal, index); + super(RootControlDescriptor.class, controlID, Category.Internal, index); this.controlID = controlID; } @Override - public void attach(CodeContext context, Control previous) { + public void attach(CodeContext context, RootControlDescriptor previous) { root = (CodeRoot) context.getComponent(); } @Override - public Control getControl() { + public Control control() { switch (controlID) { case StartableProtocol.START: return root.startControl; @@ -373,7 +372,7 @@ public Control getControl() { } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { switch (controlID) { case StartableProtocol.START: return StartableProtocol.START_INFO; @@ -389,7 +388,8 @@ public ControlInfo getInfo() { } - private static class DriverDescriptor extends ReferenceDescriptor implements ProxyContext.Handler { + private static class DriverDescriptor extends ReferenceDescriptor + implements ProxyContext.Handler { private final Field field; private final Object driver; @@ -398,22 +398,19 @@ private static class DriverDescriptor extends ReferenceDescriptor implements Pro private DriverDescriptor next; private DriverDescriptor(Field field, Object delegate) { - super(field.getName()); + super(DriverDescriptor.class, field.getName()); this.field = field; this.driver = delegate; } @Override - public void attach(CodeContext context, ReferenceDescriptor previous) { + public void attach(CodeContext context, DriverDescriptor previous) { this.context = (Context) context; - if (previous instanceof DriverDescriptor) { - var prev = (DriverDescriptor) previous; - if (!field.getType().equals(prev.field.getType())) { - prev.dispose(); + if (previous != null) { + if (!field.getType().equals(previous.field.getType())) { + previous.dispose(); } - prev.next = this; - } else if (previous != null) { - previous.dispose(); + previous.next = this; } try { var proxy = context.getComponent().getProxyContext() diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeRootContainer.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeRootContainer.java index 671cdb5c..8a2c0a1d 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeRootContainer.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeRootContainer.java @@ -218,30 +218,31 @@ protected void notifyChild(Component child) throws VetoException { } - private static class ContainerControlDescriptor extends ControlDescriptor { + private static class ContainerControlDescriptor + extends ControlDescriptor { private final ControlInfo info; private Control control; ContainerControlDescriptor(String id, ControlInfo info, int index) { - super(id, ControlDescriptor.Category.Internal, index); + super(ContainerControlDescriptor.class, id, ControlDescriptor.Category.Internal, index); this.info = info; } @Override - public void attach(CodeContext context, Control previous) { + public void attach(CodeContext context, ContainerControlDescriptor previous) { control = ((CodeRootContainer) context.getComponent()) - .getContainerControl(getID()); + .getContainerControl(id()); } @Override - public Control getControl() { + public Control control() { return control; } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return info; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/CodeUtils.java b/praxiscore-code/src/main/java/org/praxislive/code/CodeUtils.java index 1de61682..a118bacb 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/CodeUtils.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/CodeUtils.java @@ -23,7 +23,9 @@ import java.io.InputStream; import java.util.Arrays; +import java.util.List; import java.util.Scanner; +import java.util.stream.Stream; /** * @@ -50,8 +52,8 @@ public static T[] join(T[] a, T[] b) { return r; } - public static String[] defaultImports() { - return DefaultCodeDelegate.IMPORTS.clone(); + public static List defaultImports() { + return DefaultCodeDelegate.DEFAULT_IMPORTS; } } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/ControlDescriptor.java b/praxiscore-code/src/main/java/org/praxislive/code/ControlDescriptor.java index 854a2c8b..2b791589 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/ControlDescriptor.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/ControlDescriptor.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2021 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -30,7 +30,7 @@ * and reset. The underlying control may be configured from the previous * iteration or carried across. */ -public abstract class ControlDescriptor { +public non-sealed abstract class ControlDescriptor> extends Descriptor { /** * Categories of control, which also affects broad ordering of controls. @@ -69,39 +69,30 @@ public static enum Category { Function } - private final String id; private final Category category; private final int index; /** * Create a ControlDescriptor. * + * @param type type of the descriptor * @param id the ID (must be a valid control ID) * @param category the category * @param index the index within the category (used for ordering - must be * unique) */ - protected ControlDescriptor(String id, Category category, int index) { - this.id = id; + protected ControlDescriptor(Class type, String id, Category category, int index) { + super(type, id); this.category = category; this.index = index; } - /** - * Get the ID. - * - * @return id - */ - public final String getID() { - return id; - } - /** * Get the category. * * @return category */ - public Category getCategory() { + public Category category() { return category; } @@ -110,7 +101,7 @@ public Category getCategory() { * * @return index */ - public int getIndex() { + public int index() { return index; } @@ -119,21 +110,7 @@ public int getIndex() { * * @return info */ - public abstract ControlInfo getInfo(); - - /** - * Configure the control for the provided context during attachment. The - * previous control with the same ID is provided - it may be null or of a - * different type. - *

- * Note : any control passed in as previous will not be disposed - * - * @param context context being attached to - * @param previous previous control with same ID, may be null or different - * type - */ - // @TODO this method should take a ControlDescriptor in future versions - public abstract void attach(CodeContext context, Control previous); + public abstract ControlInfo controlInfo(); /** * Get the wrapped control. Should only be called when attached - behaviour @@ -141,31 +118,6 @@ public int getIndex() { * * @return control */ - public abstract Control getControl(); - - /** - * Hook called to reset during attachment / detachment, or execution context - * state changes. Full reset happens on execution context changes. - * - * @param full true if execution context state - */ - public void reset(boolean full) { - } - - /** - * Deprecated hook - no op! - * - * @deprecated - */ - @Deprecated - public void stopping() { - } - - /** - * Hook called on code context disposal for any control descriptors not - * carried over. - */ - public void dispose() { - } + public abstract Control control(); } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/DataPort.java b/praxiscore-code/src/main/java/org/praxislive/code/DataPort.java index 057515f1..c4b20f85 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/DataPort.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/DataPort.java @@ -44,29 +44,29 @@ * */ public abstract class DataPort implements Port { - + public final static class Input extends DataPort { - + private final InPipe in; private final List> connections; private final List listeners; - + private java.lang.reflect.Type type; - + private Input(InputDescriptor desc) { this.type = Objects.requireNonNull(desc.type); in = new InPipe<>(); connections = new ArrayList<>(); listeners = new CopyOnWriteArrayList<>(); } - + private void reconfigure(InputDescriptor desc) { if (!Objects.equals(type, desc.type)) { this.type = Objects.requireNonNull(desc.type); in.reset(true); } } - + @Override public void connect(Port port) throws PortConnectionException { if (port instanceof Output) { @@ -75,14 +75,14 @@ public void connect(Port port) throws PortConnectionException { throw new PortConnectionException(); } } - + @Override public void disconnect(Port port) { if (port instanceof Output) { port.disconnect(this); } } - + private void addDataOutputPort(Output port, Data.Pipe source) throws PortConnectionException { if (connections.contains(port)) { throw new PortConnectionException(); @@ -95,79 +95,78 @@ private void addDataOutputPort(Output port, Data.Pipe source) throws PortC throw new PortConnectionException(ex); } } - + private void removeDataOutputPort(Output port, Data.Pipe source) { if (connections.remove(port)) { in.removeSource(source); listeners.forEach(l -> l.connectionsChanged(this)); } } - + @Override public void disconnectAll() { for (Output connection : connections()) { disconnect(connection); } } - + @Override public List> connections() { return List.copyOf(connections); } - + @Override public void addListener(PortListener listener) { listeners.add(Objects.requireNonNull(listener)); } - + @Override public void removeListener(PortListener listener) { listeners.remove(listener); } } - + private static class InPipe extends Data.In { - + private void reset(boolean full) { disconnectSinks(); if (full) { clearCaches(); } } - + } - - static final class InputDescriptor extends PortDescriptor { - + + static final class InputDescriptor extends PortDescriptor { + private final Field field; private final java.lang.reflect.Type type; private final PortInfo info; - + private Input port; - + private InputDescriptor(String id, Category category, int index, Field field, java.lang.reflect.Type type) { - super(id, category, index); + super(InputDescriptor.class, id, category, index); this.field = field; this.type = type; this.info = PortInfo.create(DataPort.class, PortInfo.Direction.IN, PMap.of("category", TypeUtils.portCategory(type))); } - + @Override @SuppressWarnings("unchecked") - public void attach(CodeContext context, Port previous) { - if (previous instanceof Input - && TypeUtils.equivalent(type, ((Input) previous).type)) { - port = (Input) previous; + public void attach(CodeContext context, InputDescriptor previous) { + if (previous != null && TypeUtils.equivalent(type, previous.type)) { + port = previous.port; port.reconfigure(this); } else { if (previous != null) { - previous.disconnectAll(); + previous.dispose(); } port = new Input<>(this); } @@ -177,32 +176,39 @@ public void attach(CodeContext context, Port previous) { context.getLog().log(LogLevel.ERROR, ex); } } - + @Override - public Port getPort() { + public Port port() { return port; } - + @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return info; } - + @Override - public void reset(boolean full) { + public void onReset() { if (port != null) { - port.in.reset(full); + port.in.reset(false); } } - + + @Override + public void onStop() { + if (port != null) { + port.in.reset(true); + } + } + static InputDescriptor create(CodeConnector connector, In ann, Field field) { return create(connector, PortDescriptor.Category.In, ann.value(), field); } - + static InputDescriptor create(CodeConnector connector, AuxIn ann, Field field) { return create(connector, PortDescriptor.Category.AuxIn, ann.value(), field); } - + private static InputDescriptor create(CodeConnector connector, PortDescriptor.Category category, int index, Field field) { if (Data.In.class.equals(field.getType())) { @@ -216,31 +222,31 @@ private static InputDescriptor create(CodeConnector connector, return null; } } - + } - + public final static class Output extends DataPort { - + private final OutPipe out; private final List> connections; private final List listeners; - + private java.lang.reflect.Type type; - + private Output(OutputDescriptor desc) { this.type = Objects.requireNonNull(desc.type); out = new OutPipe<>(); connections = new ArrayList<>(); listeners = new CopyOnWriteArrayList<>(); } - + private void reconfigure(OutputDescriptor desc) { if (!Objects.equals(type, desc.type)) { type = Objects.requireNonNull(desc.type); out.reset(true); } } - + @Override @SuppressWarnings("unchecked") public void connect(Port port) throws PortConnectionException { @@ -259,7 +265,7 @@ public void connect(Port port) throws PortConnectionException { throw new PortConnectionException(); } } - + @Override @SuppressWarnings("unchecked") public void disconnect(Port port) { @@ -272,71 +278,70 @@ public void disconnect(Port port) { } } } - + @Override public void disconnectAll() { for (Input port : connections()) { disconnect(port); } } - + @Override public List> connections() { return List.copyOf(connections); } - + @Override public void addListener(PortListener listener) { listeners.add(Objects.requireNonNull(listener)); } - + @Override public void removeListener(PortListener listener) { listeners.remove(listener); } } - + private static class OutPipe extends Data.Out { - + private void reset(boolean full) { disconnectSources(); if (full) { clearCaches(); } } - + } - - static class OutputDescriptor extends PortDescriptor { - + + static class OutputDescriptor extends PortDescriptor { + private final Field field; private final java.lang.reflect.Type type; private final PortInfo info; - + private Output port; - + private OutputDescriptor(String id, Category category, int index, Field field, java.lang.reflect.Type type) { - super(id, category, index); + super(OutputDescriptor.class, id, category, index); this.field = field; this.type = type; this.info = PortInfo.create(DataPort.class, PortInfo.Direction.OUT, PMap.of("category", TypeUtils.portCategory(type))); } - + @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof Output - && TypeUtils.equivalent(type, ((Output) previous).type)) { - port = (Output) previous; + public void attach(CodeContext context, OutputDescriptor previous) { + if (previous != null && TypeUtils.equivalent(type, previous.type)) { + port = previous.port; port.reconfigure(this); } else { if (previous != null) { - previous.disconnectAll(); + previous.dispose(); } port = new Output<>(this); } @@ -346,32 +351,39 @@ public void attach(CodeContext context, Port previous) { context.getLog().log(LogLevel.ERROR, ex); } } - + @Override - public Port getPort() { + public Port port() { return port; } - + @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return info; } - + + @Override + public void onReset() { + if (port != null) { + port.out.reset(false); + } + } + @Override - public void reset(boolean full) { + public void onStop() { if (port != null) { - port.out.reset(full); + port.out.reset(true); } } - + static OutputDescriptor create(CodeConnector connector, Out ann, Field field) { return create(connector, PortDescriptor.Category.Out, ann.value(), field); } - + static OutputDescriptor create(CodeConnector connector, AuxOut ann, Field field) { return create(connector, PortDescriptor.Category.AuxOut, ann.value(), field); } - + private static OutputDescriptor create(CodeConnector connector, PortDescriptor.Category category, int index, Field field) { if (Data.Out.class.equals(field.getType())) { @@ -385,17 +397,7 @@ private static OutputDescriptor create(CodeConnector connector, return null; } } - - } - - @Deprecated - public static class Provider implements Port.TypeProvider { - - @Override - public Stream> types() { - return Stream.of(new Type<>(DataPort.class)); - } - + } - + } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/DataSink.java b/praxiscore-code/src/main/java/org/praxislive/code/DataSink.java index 15ffb772..9e72cddd 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/DataSink.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/DataSink.java @@ -29,7 +29,7 @@ /** * - * + * */ class DataSink extends Data.Sink { @@ -37,87 +37,82 @@ class DataSink extends Data.Sink { public Lookup getLookup() { return Lookup.EMPTY; } - - static class Descriptor extends ReferenceDescriptor { - + + static class Descriptor extends ReferenceDescriptor { + private final Field sinkField; private CodeContext context; private DataSink sink; - + public Descriptor(String id, Field sinkField) { - super(id); + super(Descriptor.class, id); this.sinkField = sinkField; } @Override - public void attach(CodeContext context, ReferenceDescriptor previous) { - + public void attach(CodeContext context, Descriptor previous) { + this.context = context; - - if (previous instanceof Descriptor) { - Descriptor pd = (Descriptor) previous; - if (isCompatible(pd)) { - sink = pd.sink; - pd.sink = null; + + if (previous != null) { + if (isCompatible(previous)) { + sink = previous.sink; + previous.sink = null; } else { - pd.dispose(); + previous.dispose(); } - } else if (previous != null) { - previous.dispose(); } - + if (sink == null) { sink = new DataSink<>(); } - + sink.attach(context); - + try { sinkField.set(context.getDelegate(), sink); } catch (Exception ex) { context.getLog().log(LogLevel.ERROR, ex); } - + } - + private boolean isCompatible(Descriptor other) { return sinkField.getGenericType().equals(other.sinkField.getGenericType()); } @Override - public void reset(boolean full) { - if (full) { - if (sink != null) { - // dispose? - } - sink = new DataSink<>(); - sink.attach(context); - try { - sinkField.set(context.getDelegate(), sink); - } catch (Exception ex) { - context.getLog().log(LogLevel.ERROR, ex); - } - } else { - if (sink != null) { - sink.reset(); - } + public void onInit() { +// if (sink != null) { +// // dispose? +// } + sink = new DataSink<>(); + sink.attach(context); + try { + sinkField.set(context.getDelegate(), sink); + } catch (Exception ex) { + context.getLog().log(LogLevel.ERROR, ex); } + } + @Override + public void onReset() { + if (sink != null) { + sink.reset(); + } } - + static Descriptor create(CodeConnector connector, Field field) { - if (Data.Sink.class.equals(field.getType()) && - field.getGenericType() instanceof ParameterizedType) { + if (Data.Sink.class.equals(field.getType()) + && field.getGenericType() instanceof ParameterizedType) { field.setAccessible(true); return new Descriptor(field.getName(), field); } else { return null; } } - + } - - - + } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/DefaultCodeDelegate.java b/praxiscore-code/src/main/java/org/praxislive/code/DefaultCodeDelegate.java index 82efade4..b2df42a7 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/DefaultCodeDelegate.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/DefaultCodeDelegate.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2022 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -21,16 +21,15 @@ */ package org.praxislive.code; -import java.lang.reflect.Array; +import java.util.List; import java.util.Random; -import org.praxislive.code.userapi.Constants; /** * Default base for code delegates providing a variety of functions. */ public class DefaultCodeDelegate extends CodeDelegate implements DefaultDelegateAPI { - final static String[] IMPORTS = { + final static List DEFAULT_IMPORTS = List.of( "java.util.*", "java.util.function.*", "java.util.stream.*", @@ -38,7 +37,7 @@ public class DefaultCodeDelegate extends CodeDelegate implements DefaultDelegate "org.praxislive.core.types.*", "org.praxislive.code.userapi.*", "static org.praxislive.code.userapi.Constants.*" - }; + ); protected final Random RND; @@ -105,235 +104,4 @@ public final String randomOf(String... values) { return values[RND.nextInt(values.length)]; } - // PERLIN NOISE - copied from Processing core. - // @TODO fully convert to double??? - private static final int PERLIN_YWRAPB = 4; - private static final int PERLIN_YWRAP = 1 << PERLIN_YWRAPB; - private static final int PERLIN_ZWRAPB = 8; - private static final int PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB; - private static final int PERLIN_SIZE = 4095; -// private static final float sinLUT[]; - private static final float cosLUT[]; - private static final float SINCOS_PRECISION = 0.5f; - private static final int SINCOS_LENGTH = (int) (360f / SINCOS_PRECISION); - - static { -// sinLUT = new float[SINCOS_LENGTH]; - cosLUT = new float[SINCOS_LENGTH]; - for (int i = 0; i < SINCOS_LENGTH; i++) { -// sinLUT[i] = (float) Math.sin(i * Constants.DEG_TO_RAD * SINCOS_PRECISION); - cosLUT[i] = (float) Math.cos(i * Constants.DEG_TO_RAD * SINCOS_PRECISION); - } - } - private int perlin_octaves = 4; // default to medium smooth - private float perlin_amp_falloff = 0.5f; // 50% reduction/octave - private int perlin_TWOPI, perlin_PI; - private float[] perlin_cosTable; - private float[] perlin; - private Random perlinRandom; - - /** - * Computes the Perlin noise function value at point x. - * - * @param x - * @return - */ - @Deprecated - public double noise(double x) { - return noise(x, 0f, 0f); - } - - /** - * Computes the Perlin noise function value at the point x, y. - * - * @param x - * @param y - * @return - */ - @Deprecated - public double noise(double x, double y) { - return noise(x, y, 0f); - } - - /** - * Computes the Perlin noise function value at x, y, z. - * - * @param x - * @param z - * @param y - * @return - */ - @Deprecated - public double noise(double x, double y, double z) { - if (perlin == null) { - if (perlinRandom == null) { - perlinRandom = new Random(); - } - perlin = new float[PERLIN_SIZE + 1]; - for (int i = 0; i < PERLIN_SIZE + 1; i++) { - perlin[i] = perlinRandom.nextFloat(); - } - perlin_cosTable = cosLUT; - perlin_TWOPI = perlin_PI = SINCOS_LENGTH; - perlin_PI >>= 1; - } - - if (x < 0) { - x = -x; - } - if (y < 0) { - y = -y; - } - if (z < 0) { - z = -z; - } - - int xi = (int) x, yi = (int) y, zi = (int) z; - float xf = (float) (x - xi); - float yf = (float) (y - yi); - float zf = (float) (z - zi); - float rxf, ryf; - - float r = 0; - float ampl = 0.5f; - - float n1, n2, n3; - - for (int i = 0; i < perlin_octaves; i++) { - int of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB); - - rxf = noise_fsc(xf); - ryf = noise_fsc(yf); - - n1 = perlin[of & PERLIN_SIZE]; - n1 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1); - n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; - n2 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2); - n1 += ryf * (n2 - n1); - - of += PERLIN_ZWRAP; - n2 = perlin[of & PERLIN_SIZE]; - n2 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2); - n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; - n3 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3); - n2 += ryf * (n3 - n2); - - n1 += noise_fsc(zf) * (n2 - n1); - - r += n1 * ampl; - ampl *= perlin_amp_falloff; - xi <<= 1; - xf *= 2; - yi <<= 1; - yf *= 2; - zi <<= 1; - zf *= 2; - - if (xf >= 1.0f) { - xi++; - xf--; - } - if (yf >= 1.0f) { - yi++; - yf--; - } - if (zf >= 1.0f) { - zi++; - zf--; - } - } - return r; - } - - private float noise_fsc(float i) { - return 0.5f * (1.0f - perlin_cosTable[(int) (i * perlin_PI) % perlin_TWOPI]); - } - - // make perlin noise quality user controlled to allow - // for different levels of detail. lower values will produce - // smoother results as higher octaves are surpressed - /** - * - * @param lod - */ - @Deprecated - public void noiseDetail(int lod) { - if (lod > 0) { - perlin_octaves = lod; - } - } - - /** - * - * @param lod - * @param falloff - */ - @Deprecated - public void noiseDetail(int lod, double falloff) { - if (lod > 0) { - perlin_octaves = lod; - } - if (falloff > 0) { - perlin_amp_falloff = (float) falloff; - } - } - - /** - * - * @param what - */ - @Deprecated - public void noiseSeed(long what) { - if (perlinRandom == null) { - perlinRandom = new Random(); - } - perlinRandom.setSeed(what); - perlin = null; - } - - // end of Perlin noise functions - // start of PApplet statics - /** - * Copies an array (or part of an array) to another array. The src array is - * copied to the dst array, beginning at the position specified by srcPos - * and into the position specified by dstPos. The number of elements to copy - * is determined by length. - * - * @param src - * @param srcPosition - * @param dst - * @param dstPosition - * @param length - */ - @Deprecated - public void arrayCopy(Object src, int srcPosition, Object dst, int dstPosition, int length) { - System.arraycopy(src, srcPosition, dst, dstPosition, length); - } - - /** - * Copies an array (or part of an array) to another array. The src array is - * copied to the dst array. The number of elements to copy is determined by - * length. - * - * @param src - * @param dst - * @param length - */ - @Deprecated - public void arrayCopy(Object src, Object dst, int length) { - System.arraycopy(src, 0, dst, 0, length); - } - - /** - * Copies an array to another array. The src array is copied to the dst - * array. - * - * @param src - * @param dst - */ - @Deprecated - public void arrayCopy(Object src, Object dst) { - System.arraycopy(src, 0, dst, 0, Array.getLength(src)); - } - } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/DefaultDelegateAPI.java b/praxiscore-code/src/main/java/org/praxislive/code/DefaultDelegateAPI.java index 6b3589e4..33e6f48b 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/DefaultDelegateAPI.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/DefaultDelegateAPI.java @@ -172,146 +172,6 @@ public default Value V(Object value) { } } - /** - * Extract a double from the Property's current Value, or zero if the value - * cannot be coerced. - * - * @param p - * @return - */ - @Deprecated - public default double d(Property p) { - return p.getDouble(); - } - - /** - * Convert the provided Value into a double, or zero if the Value cannot be - * coerced. - * - * @param v - * @return - */ - @Deprecated - public default double d(Value v) { - if (v instanceof PNumber) { - return ((PNumber) v).value(); - } else { - return PNumber.from(v).orElse(PNumber.ZERO).value(); - } - } - - /** - * Parse the provided String into a double, or zero if invalid. - * - * @param s - * @return - */ - @Deprecated - public default double d(String s) { - return d(PString.of(s)); - } - - /** - * Extract an int from the Property's current Value, or zero if the value - * cannot be coerced. - * - * @param p - * @return - */ - @Deprecated - public default int i(Property p) { - return p.getInt(); - } - - /** - * Convert the provided Value into an int, or zero if the Value cannot be - * coerced. - * - * @param v - * @return - */ - @Deprecated - public default int i(Value v) { - if (v instanceof PNumber) { - return ((PNumber) v).toIntValue(); - } else { - return PNumber.from(v).orElse(PNumber.ZERO).toIntValue(); - } - } - - /** - * Parse the provided String into an int, or zero if invalid. - * - * @param s - * @return - */ - @Deprecated - public default int i(String s) { - return i(PString.of(s)); - } - - /** - * Extract the Property's current value as a boolean. If the value cannot be - * coerced, returns false. - * - * @param p - * @return - */ - @Deprecated - public default boolean b(Property p) { - return p.getBoolean(); - } - - /** - * Convert the provided Value into a boolean according to the parsing rules - * of {@link PBoolean}. If the Value cannot be coerced, returns false. - * - * @param v - * @return - */ - @Deprecated - public default boolean b(Value v) { - if (v instanceof PBoolean) { - return ((PBoolean) v).value(); - } else { - return PBoolean.from(v).orElse(PBoolean.FALSE).value(); - } - } - - /** - * Parse the given String into a boolean according to the parsing rules of - * {@link PBoolean}. If the String is invalid, returns false. - * - * @param s - * @return - */ - @Deprecated - public default boolean b(String s) { - return b(PString.of(s)); - } - - /** - * Extract the Property's current value into a String representation. - * - * @param p - * @return - */ - @Deprecated - public default String s(Property p) { - return p.get().toString(); - } - - /** - * Convert the provided Value into a String representation. - * - * @param v - * @return - */ - @Deprecated - public default String s(Value v) { - return v.toString(); - } - /** * Attempt to extract a {@link PArray} from the given Property. An empty * PArray will be returned if the property's value is not a PArray and diff --git a/praxiscore-code/src/main/java/org/praxislive/code/Descriptor.java b/praxiscore-code/src/main/java/org/praxislive/code/Descriptor.java new file mode 100644 index 00000000..ae28ac40 --- /dev/null +++ b/praxiscore-code/src/main/java/org/praxislive/code/Descriptor.java @@ -0,0 +1,127 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2023 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code 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 Lesser General Public License + * version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit https://www.praxislive.org if you need additional information or + * have any questions. + */ +package org.praxislive.code; + +import java.util.Objects; + +/** + * Common interface of reference, port and control descriptors. + * + * @param direct subtype + */ +public sealed abstract class Descriptor> + permits ReferenceDescriptor, ControlDescriptor, PortDescriptor { + + private final Class type; + private final String id; + + protected Descriptor(Class type, String id) { + this.type = Objects.requireNonNull(type); + this.id = Objects.requireNonNull(id); + } + + /** + * Get the descriptor ID. + * + * @return id + */ + public final String id() { + return id; + } + + public final Class type() { + return type; + } + + /** + * Attach the descriptor to the provided context. The previous descriptor + * with the same ID and type is provided, if it exists. The implementation + * should handle disposal of the previous descriptor if required. + *

+ * The {@link #onInit()} hook will be called after attachment if the code + * context is active, or when the code context becomes active. + * + * @param context code context + * @param previous previous descriptor or null + */ + public abstract void attach(CodeContext context, T previous); + + /** + * Hook called when the descriptor becomes part of an active code context, + * or after anything triggers a reset while active. The default + * implementation does nothing. + */ + public void onInit() { + + } + + /** + * Hook called when the code context becomes active due to the execution + * context state changing. The {@link #onInit()} hook will have been called + * prior to this hook. The default implementation does nothing. + */ + public void onStart() { + + } + + /** + * Hook called when the code context becomes inactive due to the execution + * context state changing. This hook will be called before the + * {@link #onReset()} hook. The default implementation does nothing. + */ + public void onStop() { + + } + + /** + * Hook called when the code context becomes inactive, including on context + * swap, or if anything else triggers a reset while active. The default + * implementation does nothing. + */ + public void onReset() { + + } + + /** + * Hook called when the descriptor is disposed, when the code context is + * changing or the component is being removed. This hook is not called by + * default when a descriptor is passed in as the previous instance in + * {@link #attach(org.praxislive.code.CodeContext, org.praxislive.code.Descriptor)}. + * The default implementation does nothing. + */ + public void dispose() { + + } + + void handleAttach(CodeContext context, Descriptor previous) { + if (previous != null) { + if (type().isInstance(previous)) { + attach(context, type().cast(previous)); + } else { + previous.dispose(); + } + } else { + attach(context, null); + } + } + +} diff --git a/praxiscore-code/src/main/java/org/praxislive/code/FunctionDescriptor.java b/praxiscore-code/src/main/java/org/praxislive/code/FunctionDescriptor.java index 305a802f..7bb17afc 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/FunctionDescriptor.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/FunctionDescriptor.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2022 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -39,7 +39,7 @@ /** * */ -class FunctionDescriptor extends ControlDescriptor { +class FunctionDescriptor extends ControlDescriptor { private final ControlInfo info; private final FunctionControl control; @@ -50,26 +50,26 @@ private FunctionDescriptor(String id, ControlInfo info, List> parameterMappers, ValueMapper returnMapper) { - super(id, Category.Function, index); + super(FunctionDescriptor.class, id, Category.Function, index); this.info = info; this.control = new DirectFunctionControl(method, parameterMappers, returnMapper); } @Override - public void attach(CodeContext context, Control previous) { - if (previous instanceof FunctionControl) { - ((FunctionControl) previous).detach(); + public void attach(CodeContext context, FunctionDescriptor previous) { + if (previous != null) { + previous.control.detach(); } control.attach(context); } @Override - public Control getControl() { + public Control control() { return control; } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return info; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/InfoProperty.java b/praxiscore-code/src/main/java/org/praxislive/code/InfoProperty.java index 5dc02dbf..8893afcc 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/InfoProperty.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/InfoProperty.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2021 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -41,27 +41,27 @@ public void call(Call call, PacketRouter router) throws Exception { } } - public static class Descriptor extends ControlDescriptor { + public static class Descriptor extends ControlDescriptor { private final InfoProperty control; public Descriptor(int index) { - super(ComponentProtocol.INFO, Category.Internal, index); + super(Descriptor.class, ComponentProtocol.INFO, Category.Internal, index); control = new InfoProperty(); } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return ComponentProtocol.INFO_INFO; } @Override - public void attach(CodeContext context, Control previous) { + public void attach(CodeContext context, Descriptor previous) { control.context = context; } @Override - public Control getControl() { + public Control control() { return control; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/InjectRefImpl.java b/praxiscore-code/src/main/java/org/praxislive/code/InjectRefImpl.java index 975eba2e..b468698c 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/InjectRefImpl.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/InjectRefImpl.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2021 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -25,7 +25,6 @@ import java.util.Objects; import org.praxislive.code.userapi.Inject; import org.praxislive.code.userapi.Ref; -import org.praxislive.core.ExecutionContext; import org.praxislive.core.services.LogLevel; class InjectRefImpl extends Ref { @@ -44,34 +43,31 @@ protected void log(Exception ex) { context.getLog().log(LogLevel.ERROR, ex); } - static class Descriptor extends ReferenceDescriptor { + static class Descriptor extends ReferenceDescriptor { private final Field field; - private final Ref.Initializer initializer; + private final Ref.Initializer initializer; private CodeContext context; - private InjectRefImpl ref; + private InjectRefImpl ref; - private Descriptor(CodeConnector connector, Field field, Ref.Initializer initializer) { - super(field.getName()); + private Descriptor(CodeConnector connector, Field field, Ref.Initializer initializer) { + super(Descriptor.class, field.getName()); this.field = field; this.initializer = initializer; } @Override @SuppressWarnings("unchecked") - public void attach(CodeContext context, ReferenceDescriptor previous) { + public void attach(CodeContext context, Descriptor previous) { this.context = context; - if (previous instanceof InjectRefImpl.Descriptor) { - InjectRefImpl.Descriptor pd = (InjectRefImpl.Descriptor) previous; - if (isCompatible(pd)) { - ref = (InjectRefImpl) pd.ref; - pd.ref = null; + if (previous != null) { + if (isCompatible(previous)) { + ref = previous.ref; + previous.ref = null; } else { - pd.dispose(); + previous.dispose(); } - } else if (previous != null) { - previous.dispose(); } if (ref == null) { @@ -79,23 +75,35 @@ public void attach(CodeContext context, ReferenceDescriptor previous) { } ref.attach(context); - initAndSet(); + onInit(); } - private boolean isCompatible(Descriptor other) { + private boolean isCompatible(Descriptor other) { return field.getGenericType().equals(other.field.getGenericType()); } @Override - public void reset(boolean full) { - if (full && context.getExecutionContext().getState() != ExecutionContext.State.ACTIVE) { - dispose(); - } else { - initAndSet(); + @SuppressWarnings("unchecked") + public void onInit() { + try { + initializer.initialize((Ref) ref); + field.set(context.getDelegate(), ref.get()); + } catch (Exception ex) { + context.getLog().log(LogLevel.ERROR, ex); } } + @Override + public void onReset() { + ref.reset(); + } + + @Override + public void onStop() { + dispose(); + } + @Override public void dispose() { if (ref != null) { @@ -109,18 +117,8 @@ public void dispose() { } } } - - private void initAndSet() { - try { - ref.reset(); - initializer.initialize(ref); - field.set(context.getDelegate(), ref.get()); - } catch (Exception ex) { - context.getLog().log(LogLevel.ERROR, ex); - } - } - static Descriptor create(CodeConnector connector, Inject ann, Field field) { + static Descriptor create(CodeConnector connector, Inject ann, Field field) { try { Class handlerCls = ann.provider(); @@ -134,7 +132,7 @@ static Descriptor create(CodeConnector connector, Inject ann, Field field) if (provider.isSupportedType(field.getType())) { Ref.Initializer init = provider.initializerFor(field.getType()); field.setAccessible(true); - return new Descriptor<>(connector, field, Objects.requireNonNull(init)); + return new Descriptor(connector, field, Objects.requireNonNull(init)); } else { return null; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/InputImpl.java b/praxiscore-code/src/main/java/org/praxislive/code/InputImpl.java index c3256c80..44d42ebd 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/InputImpl.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/InputImpl.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -72,7 +72,7 @@ private static Descriptor createDescriptor(CodeConnector connector, return new Descriptor(id, category, index, field); } - static class Descriptor extends PortDescriptor + static class Descriptor extends PortDescriptor implements ControlInput.Link { private final Field field; @@ -80,20 +80,17 @@ static class Descriptor extends PortDescriptor private ControlInput port; private Descriptor(String id, Category category, int index, Field field) { - super(id, category, index); + super(Descriptor.class, id, category, index); this.input = new InputImpl(); this.field = field; } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof ControlInput) { - port = (ControlInput) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + port = previous.port; port.setLink(this); } else { - if (previous != null) { - previous.disconnectAll(); - } port = new ControlInput(this); } try { @@ -106,17 +103,17 @@ public void attach(CodeContext context, Port previous) { } @Override - public void reset(boolean full) { + public void onReset() { input.clearLinks(); } @Override - public Port getPort() { + public Port port() { return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return ControlInput.INFO; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/InputPortControl.java b/praxiscore-code/src/main/java/org/praxislive/code/InputPortControl.java index b4c321b5..4105c86c 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/InputPortControl.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/InputPortControl.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -54,13 +54,13 @@ public void call(Call call, PacketRouter router) throws Exception { router.route(call.reply()); } - static class Descriptor extends ControlDescriptor { + static class Descriptor extends ControlDescriptor { private final InputPortControl control; private final ControlInfo info; private Descriptor(String id, Category category, int index, ControlInput.Link link) { - super(id, category, index); + super(Descriptor.class, id, category, index); control = new InputPortControl(link); info = ControlInfo.createFunctionInfo( List.of(ArgumentInfo.of(Value.class)), @@ -70,16 +70,16 @@ private Descriptor(String id, Category category, int index, ControlInput.Link li } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return info; } @Override - public void attach(CodeContext context, Control previous) { + public void attach(CodeContext context, Descriptor previous) { } @Override - public Control getControl() { + public Control control() { return control; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/LogControl.java b/praxiscore-code/src/main/java/org/praxislive/code/LogControl.java index 0bf6bdbb..59716063 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/LogControl.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/LogControl.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2019 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -49,27 +49,27 @@ public void call(Call call, PacketRouter router) throws Exception { } } - public static class Descriptor extends ControlDescriptor { + public static class Descriptor extends ControlDescriptor { private final LogControl control; public Descriptor(int index) { - super(ID, Category.Internal, index); + super(Descriptor.class, ID, Category.Internal, index); control = new LogControl(); } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return null; } @Override - public void attach(CodeContext context, Control previous) { + public void attach(CodeContext context, Descriptor previous) { control.context = context; } @Override - public Control getControl() { + public Control control() { return control; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/MethodInput.java b/praxiscore-code/src/main/java/org/praxislive/code/MethodInput.java index 5a17dd7e..423922af 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/MethodInput.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/MethodInput.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -94,39 +94,36 @@ private static Descriptor createDescriptor(CodeConnector connector, return new Descriptor(id, category, index, input); } - static class Descriptor extends PortDescriptor implements ControlInput.Link { + static class Descriptor extends PortDescriptor implements ControlInput.Link { private final MethodInput input; private ControlInput port; private Descriptor(String id, Category category, int index, MethodInput input) { - super(id, category, index); + super(Descriptor.class, id, category, index); this.input = input; } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof ControlInput) { - port = (ControlInput) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + port = previous.port; port.setLink(this); } else { - if (previous != null) { - previous.disconnectAll(); - } port = new ControlInput(this); } input.attach(context); } @Override - public Port getPort() { + public Port port() { assert port != null; return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return ControlInput.INFO; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/OutputImpl.java b/praxiscore-code/src/main/java/org/praxislive/code/OutputImpl.java index d54dbd5c..26d22ce6 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/OutputImpl.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/OutputImpl.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -78,25 +78,22 @@ private static Descriptor createDescriptor(CodeConnector connector, return new Descriptor(id, category, index, field); } - static class Descriptor extends PortDescriptor { + static class Descriptor extends PortDescriptor { private ControlOutput port; private Field field; private Descriptor(String id, Category category, int index, Field field) { - super(id, category, index); + super(Descriptor.class, id, category, index); assert field != null; this.field = field; } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof ControlOutput) { - port = (ControlOutput) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + port = previous.port; } else { - if (previous != null) { - previous.disconnectAll(); - } port = new ControlOutput(); } try { @@ -108,12 +105,12 @@ public void attach(CodeContext context, Port previous) { } @Override - public Port getPort() { + public Port port() { return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return ControlOutput.INFO; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/PersistDescriptor.java b/praxiscore-code/src/main/java/org/praxislive/code/PersistDescriptor.java index 0a9ea176..5e8b48ad 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/PersistDescriptor.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/PersistDescriptor.java @@ -26,7 +26,7 @@ import org.praxislive.code.userapi.Persist; import org.praxislive.core.services.LogLevel; -class PersistDescriptor extends ReferenceDescriptor { +class PersistDescriptor extends ReferenceDescriptor { private static final Map, Object> PRIMITIVE_DEFAULTS = Map.of( int.class, Integer.valueOf(0), @@ -46,36 +46,33 @@ class PersistDescriptor extends ReferenceDescriptor { private CodeContext context; PersistDescriptor(Field field, boolean autoReset, boolean autoDispose) { - super(field.getName()); + super(PersistDescriptor.class, field.getName()); this.field = field; this.autoReset = autoReset; this.autoClose = autoDispose; } @Override - public void attach(CodeContext context, ReferenceDescriptor previous) { + public void attach(CodeContext context, PersistDescriptor previous) { this.context = context; - if (previous instanceof PersistDescriptor) { - var prev = (PersistDescriptor) previous; - if (field.getGenericType().equals(prev.field.getGenericType()) - && prev.context != null) { + if (previous != null) { + if (field.getGenericType().equals(previous.field.getGenericType()) + && previous.context != null) { try { field.set(context.getDelegate(), - prev.field.get(prev.context.getDelegate())); + previous.field.get(previous.context.getDelegate())); } catch (Exception ex) { context.getLog().log(LogLevel.ERROR, ex); } } else { - prev.dispose(); + previous.dispose(); } - } else if (previous != null) { - previous.dispose(); } } @Override - public void reset(boolean full) { - if (full && autoReset) { + public void onStop() { + if (autoReset) { try { if (autoClose) { handleAutoClose(); @@ -122,5 +119,5 @@ static PersistDescriptor create(CodeConnector connector, Persist ann, Field f return null; } } - + } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/PortDescriptor.java b/praxiscore-code/src/main/java/org/praxislive/code/PortDescriptor.java index 25a82c2e..e1b2d6ce 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/PortDescriptor.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/PortDescriptor.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2021 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -30,7 +30,7 @@ * underlying port may be configured from the previous iteration or carried * across. */ -public abstract class PortDescriptor { +public non-sealed abstract class PortDescriptor> extends Descriptor { public static enum Category { @@ -60,39 +60,30 @@ public static enum Category { AuxOut } - private final String id; private final Category category; private final int index; /** * Create a PortDescriptor. * + * @param type descriptor type * @param id the ID (must be a valid port ID) * @param category the category * @param index the index within the category (used for ordering - must be * unique) */ - protected PortDescriptor(String id, Category category, int index) { - this.id = id; + protected PortDescriptor(Class type, String id, Category category, int index) { + super(type, id); this.category = category; this.index = index; } - /** - * Get the ID. - * - * @return id - */ - public final String getID() { - return id; - } - /** * Get the category. * * @return category */ - public Category getCategory() { + public Category category() { return category; } @@ -101,62 +92,36 @@ public Category getCategory() { * * @return index */ - public int getIndex() { + public int index() { return index; } - /** - * Configure the port for the provided context. The previous port with the - * same ID is provided - it may be null or of a different type. If the - * previous port cannot be carried over, then this method must handle - * disconnecting and/or reconnecting as appropriate. - *

- * Note : any port passed in as previous will not be disposed - * - * @param context context being attached to - * @param previous previous port with the same ID, may be null or different - * type - */ - // @TODO this method should take a PortDescriptor in future versions - public abstract void attach(CodeContext context, Port previous); - /** * Get the wrapped port. Should only be called when attached - behaviour is * otherwise undefined. * * @return port */ - public abstract Port getPort(); + public abstract Port port(); /** * Get port info. * * @return info */ - public abstract PortInfo getInfo(); - - /** - * Hook called to reset during attachment / detachment, or execution context - * state changes. Full reset happens on execution context changes. - * - * @param full true if execution context state - */ - public void reset(boolean full) { - } - - /** - * Deprecated hook - no op! - * - * @deprecated - */ - @Deprecated - public void stopping() { - } + public abstract PortInfo portInfo(); /** - * Hook called on code context disposal for any port descriptors not carried - * over. + * Dispose the port descriptor. The default implementation calls + * {@link Port#disconnectAll()}. When overriding this method, call the super + * implementation or otherwise ensure that the port is disconnected. */ + @Override public void dispose() { + var port = port(); + if (port != null) { + port.disconnectAll(); + } } + } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/PropertyControl.java b/praxiscore-code/src/main/java/org/praxislive/code/PropertyControl.java index b63c7934..d632fa4b 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/PropertyControl.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/PropertyControl.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -117,15 +117,14 @@ private void checkInvoke(long time, boolean error) { } } - private void attach(CodeContext context, Control previous) { + private void attach(CodeContext context, PropertyControl previous) { this.context = context; - if (previous instanceof PropertyControl) { - PropertyControl pc = (PropertyControl) previous; - binding.attach(context, pc.binding); - latest = pc.latest; - latestSet = pc.latestSet; + if (previous != null) { + binding.attach(context, previous.binding); + latest = previous.latest; + latestSet = previous.latestSet; try { - binding.set(pc.binding.get()); + binding.set(previous.binding.get()); } catch (Exception ex) { // do nothing? } @@ -266,7 +265,7 @@ public Value getDefaultValue() { } - public static class Descriptor extends ControlDescriptor { + public static class Descriptor extends ControlDescriptor { private final PropertyControl control; private final Field propertyField; @@ -280,27 +279,31 @@ private Descriptor(String id, Method onChange, Method onError ) { - super(id, Category.Property, index); + super(Descriptor.class, id, Category.Property, index); control = new PropertyControl(info, binding, onChange, onError); this.propertyField = field; this.synthetic = false; } private Descriptor(String id, int index, Binding binding, Field field) { - super(id, Category.Synthetic, index); + super(Descriptor.class, id, Category.Synthetic, index); control = new PropertyControl(null, binding, null, null); propertyField = field; this.synthetic = true; } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return control.info; } @Override - public void attach(CodeContext context, Control previous) { - control.attach(context, previous); + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + control.attach(context, previous.control); + } else { + control.attach(context, null); + } if (propertyField != null) { try { propertyField.set(context.getDelegate(), control); @@ -311,18 +314,23 @@ public void attach(CodeContext context, Control previous) { } @Override - public Control getControl() { + public Control control() { return control; } public PortDescriptor createPortDescriptor() { - return new PortDescImpl(getID(), getIndex(), control); + return new PortDescImpl(id(), index(), control); + } + + @Override + public void onReset() { + control.reset(); } @Override - public void reset(boolean full) { - control.reset(full); - if (full && synthetic) { + public void onStop() { + control.finishAnimating(); + if (synthetic) { try { control.binding.set(control.binding.getDefaultValue()); } catch (Exception ex) { @@ -331,11 +339,6 @@ public void reset(boolean full) { } } - @Override - public void stopping() { - control.finishAnimating(); - } - public static Descriptor create(CodeConnector connector, P ann, Field field) { Binding binding = findBinding(connector, field); @@ -421,8 +424,6 @@ private static Binding findBinding(CodeConnector connector, Field field) { binding = BooleanBinding.create(connector, field); } else if (ValueBinding.isBindableFieldType(type)) { binding = ValueBinding.create(connector, field); - } else if (BytesBinding.isBindableFieldType(type)) { - binding = BytesBinding.create(connector, field); } if (binding == null && Property.class.isAssignableFrom(type)) { @@ -454,38 +455,35 @@ private static Method extractMethod(CodeConnector connector, String methodNam } - private static class PortDescImpl extends PortDescriptor implements ControlInput.Link { + private static class PortDescImpl extends PortDescriptor implements ControlInput.Link { private final PropertyControl control; private ControlInput port; private PortDescImpl(String id, int index, PropertyControl control) { - super(id, Category.Property, index); + super(PortDescImpl.class, id, Category.Property, index); this.control = control; } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof ControlInput) { - port = (ControlInput) previous; + public void attach(CodeContext context, PortDescImpl previous) { + if (previous != null) { + port = previous.port; port.setLink(this); } else { - if (previous != null) { - previous.disconnectAll(); - } port = new ControlInput(this); } } @Override - public Port getPort() { + public Port port() { assert port != null; return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return ControlInput.INFO; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/ProxyDescriptor.java b/praxiscore-code/src/main/java/org/praxislive/code/ProxyDescriptor.java index 618799d6..004950d2 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/ProxyDescriptor.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/ProxyDescriptor.java @@ -26,7 +26,7 @@ import org.praxislive.code.userapi.Proxy; import org.praxislive.core.services.LogLevel; -final class ProxyDescriptor extends ReferenceDescriptor implements ProxyContext.Handler { +final class ProxyDescriptor extends ReferenceDescriptor implements ProxyContext.Handler { private final Field field; private final Object delegate; @@ -34,21 +34,18 @@ final class ProxyDescriptor extends ReferenceDescriptor implements ProxyContext. private CodeContext context; protected ProxyDescriptor(Field field, Object delegate) { - super(field.getName()); + super(ProxyDescriptor.class, field.getName()); this.field = field; this.delegate = delegate; } @Override - public void attach(CodeContext context, ReferenceDescriptor previous) { + public void attach(CodeContext context, ProxyDescriptor previous) { this.context = context; - if (previous instanceof ProxyDescriptor) { - var prev = (ProxyDescriptor) previous; - if (!field.getType().equals(prev.field.getType())) { - prev.dispose(); + if (previous != null) { + if (!field.getType().equals(previous.field.getType())) { + previous.dispose(); } - } else if (previous != null) { - previous.dispose(); } try { var proxy = context.getComponent().getProxyContext() diff --git a/praxiscore-code/src/main/java/org/praxislive/code/RefImpl.java b/praxiscore-code/src/main/java/org/praxislive/code/RefImpl.java index 245ed55b..54bd3054 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/RefImpl.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/RefImpl.java @@ -48,14 +48,6 @@ private void attach(CodeContext context, Descriptor desc) { this.desc = desc; } - @Override - @Deprecated - public Ref asyncCompute(K key, Function function) { - var async = context.async(key, k -> (T) function.apply(k)); - setAsync(async); - return this; - } - @Override protected void reset() { super.reset(); @@ -95,7 +87,7 @@ void updateFromPublisher(RefImpl publisher) { } } - static class Descriptor extends ReferenceDescriptor { + static class Descriptor extends ReferenceDescriptor { private final Field refField; private final Type refType; @@ -108,7 +100,7 @@ static class Descriptor extends ReferenceDescriptor { private RefPort.OutputDescriptor outputPort; private Descriptor(CodeConnector connector, String id, Field refField, Type refType) { - super(id); + super(Descriptor.class, id); this.refField = refField; this.refType = refType; Ref.Publish pub = refField.getAnnotation(Ref.Publish.class); @@ -128,22 +120,19 @@ private Descriptor(CodeConnector connector, String id, Field refField, Type r } @Override - public void attach(CodeContext context, ReferenceDescriptor previous) { - if (previous instanceof RefImpl.Descriptor) { - RefImpl.Descriptor pd = (RefImpl.Descriptor) previous; - if (isCompatible(pd)) { - ref = pd.ref; - pd.removePublishing(); - pd.removeSubscription(); - if (pd.subscribeTo != null && subscribeTo == null) { + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + if (isCompatible(previous)) { + ref = previous.ref; + previous.removePublishing(); + previous.removeSubscription(); + if (previous.subscribeTo != null && subscribeTo == null) { ref.clear(); } - pd.ref = null; + previous.ref = null; } else { - pd.dispose(); + previous.dispose(); } - } else if (previous != null) { - previous.dispose(); } if (ref == null) { @@ -168,17 +157,24 @@ private boolean isCompatible(Descriptor other) { } @Override - public void reset(boolean full) { + public void onInit() { + checkPublishing(); + checkSubscription(); + } + + @Override + public void onReset() { if (ref != null) { - if (full) { - ref.dispose(); - removePublishing(); - removeSubscription(); - } else { - ref.reset(); - } - checkPublishing(); - checkSubscription(); + ref.reset(); + } + } + + @Override + public void onStop() { + if (ref != null) { + ref.dispose(); + removePublishing(); + removeSubscription(); } } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/RefPort.java b/praxiscore-code/src/main/java/org/praxislive/code/RefPort.java index 66d01671..69cd8b3c 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/RefPort.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/RefPort.java @@ -143,7 +143,7 @@ protected void update(List> refs) { } - static final class InputDescriptor extends PortDescriptor { + static final class InputDescriptor extends PortDescriptor { private final Field field; private final java.lang.reflect.Type type; @@ -156,7 +156,7 @@ private InputDescriptor(String id, int index, Field field, java.lang.reflect.Type type) { - super(id, category, index); + super(InputDescriptor.class, id, category, index); this.field = field; this.type = type; this.info = PortInfo.create(RefPort.class, @@ -165,14 +165,13 @@ private InputDescriptor(String id, } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof Input - && TypeUtils.equivalent(type, ((Input) previous).type)) { - port = (Input) previous; + public void attach(CodeContext context, InputDescriptor previous) { + if (previous != null && TypeUtils.equivalent(type, previous.type)) { + port = previous.port; port.reconfigure(this); } else { if (previous != null) { - previous.disconnectAll(); + previous.dispose(); } port = new Input<>(this); } @@ -184,17 +183,17 @@ public void attach(CodeContext context, Port previous) { } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return info; } @Override - public Port getPort() { + public Port port() { return port; } @Override - public void reset(boolean full) { + public void onReset() { port.refInput.clearLinks(); } @@ -302,7 +301,7 @@ private void revalidateInputs() { } - static final class OutputDescriptor extends PortDescriptor { + static final class OutputDescriptor extends PortDescriptor { private final RefImpl.Descriptor refDesc; private final PortInfo info; @@ -313,7 +312,7 @@ private OutputDescriptor(String id, Category category, int index, RefImpl.Descriptor refDesc) { - super(id, category, index); + super(OutputDescriptor.class, id, category, index); this.refDesc = refDesc; this.info = PortInfo.create(RefPort.class, PortInfo.Direction.OUT, @@ -321,27 +320,26 @@ private OutputDescriptor(String id, } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof Output - && TypeUtils.equivalent(refDesc.getRefType(), - ((Output) previous).refDesc.getRefType())) { - port = (Output) previous; + public void attach(CodeContext context, OutputDescriptor previous) { + if (previous != null && TypeUtils.equivalent(refDesc.getRefType(), + previous.refDesc.getRefType())) { + port = previous.port; port.reconfigure(this); } else { if (previous != null) { - previous.disconnectAll(); + previous.dispose(); } port = new Output<>(this); } } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return info; } @Override - public Port getPort() { + public Port port() { return port; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/ReferenceDescriptor.java b/praxiscore-code/src/main/java/org/praxislive/code/ReferenceDescriptor.java index 2f0b306d..991b025f 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/ReferenceDescriptor.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/ReferenceDescriptor.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2021 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -27,55 +27,15 @@ * ports. They include an ID, but no ordering or categories. * */ -public abstract class ReferenceDescriptor { - - private final String id; +public non-sealed abstract class ReferenceDescriptor> extends Descriptor { /** * Create a ReferenceDescriptor with the provided ID. * * @param id reference id */ - protected ReferenceDescriptor(String id) { - this.id = id; - } - - /** - * Get the ID. - * - * @return id - */ - public final String getID() { - return id; - } - - /** - * Configure the reference for the provided context during attachment. The - * previous reference descriptor with the same ID is provided - it may be - * null or of a different type. This method should handle disposal of the - * previous reference descriptor in cases where necessary (eg. not same - * type). - * - * @param context context being attached to - * @param previous previous reference descriptor with same ID, may be null - * or different type - */ - public abstract void attach(CodeContext context, ReferenceDescriptor previous); - - /** - * Hook called to reset during attachment / detachment, or execution context - * state changes. Full reset happens on execution context changes. - * - * @param full true if execution context state - */ - public void reset(boolean full) { - } - - /** - * Hook called on code context disposal for any references descriptor not - * carried over. - */ - public void dispose() { + protected ReferenceDescriptor(Class type, String id) { + super(type, id); } } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/ResourceProperty.java b/praxiscore-code/src/main/java/org/praxislive/code/ResourceProperty.java index 26091076..8f2cd4ff 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/ResourceProperty.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/ResourceProperty.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -41,7 +41,6 @@ import org.praxislive.core.Control; import org.praxislive.core.Lookup; import org.praxislive.core.Port; -import org.praxislive.core.ArgumentInfo; import org.praxislive.core.ControlInfo; import org.praxislive.core.PortInfo; import org.praxislive.core.services.TaskService; @@ -216,24 +215,24 @@ public String getEmptyValue() { } - public static class Descriptor extends ControlDescriptor { + public static class Descriptor extends ControlDescriptor { - private final Loader loader; + private final Loader loader; private final Field field; private final Method onChange, onError; private final ControlInfo info; - private ResourceProperty control; + private ResourceProperty control; private Descriptor( String id, int index, Field field, - Loader loader, + Loader loader, Method onChange, Method onError ) { - super(id, Category.Property, index); + super(Descriptor.class, id, Category.Property, index); this.loader = loader; this.field = field; this.onChange = onChange; @@ -243,33 +242,35 @@ private Descriptor( } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return info; } @Override @SuppressWarnings("unchecked") - public void attach(CodeContext context, Control previous) { - if (previous instanceof ResourceProperty - && ((ResourceProperty) previous).loader.getType() == loader.getType()) { - control = (ResourceProperty) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null && previous.loader.getType() == loader.getType()) { + control = previous.control; } else { + if (previous != null) { + previous.dispose(); + } control = new ResourceProperty<>(loader); } control.attach(context, field, onChange, onError); } @Override - public Control getControl() { + public Control control() { return control; } public PortDescriptor createPortDescriptor() { - return new PortDescImpl(getID(), getIndex(), this); + return new PortDescImpl(id(), index(), this); } - public static Descriptor create(CodeConnector connector, P ann, - Field field, Loader loader) { + public static Descriptor create(CodeConnector connector, P ann, + Field field, Loader loader) { if (!field.getType().isAssignableFrom(loader.getType())) { return null; } @@ -286,7 +287,7 @@ public static Descriptor create(CodeConnector connector, P ann, if (onErrorAnn != null) { onError = extractMethod(connector, onErrorAnn.value()); } - return new Descriptor<>(id, index, field, loader, onChange, onError); + return new Descriptor(id, index, field, loader, onChange, onError); } private static Method extractMethod(CodeConnector connector, String methodName) { @@ -302,38 +303,39 @@ private static Method extractMethod(CodeConnector connector, String methodNam } - private static class PortDescImpl extends PortDescriptor implements ControlInput.Link { + private static class PortDescImpl extends PortDescriptor + implements ControlInput.Link { - private final Descriptor dsc; + private final Descriptor dsc; private ControlInput port; - private PortDescImpl(String id, int index, Descriptor dsc) { - super(id, PortDescriptor.Category.Property, index); + private PortDescImpl(String id, int index, Descriptor dsc) { + super(PortDescImpl.class, id, PortDescriptor.Category.Property, index); this.dsc = dsc; } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof ControlInput) { - port = (ControlInput) previous; + public void attach(CodeContext context, PortDescImpl previous) { + if (previous != null) { + port = previous.port; port.setLink(this); } else { if (previous != null) { - previous.disconnectAll(); + previous.dispose(); } port = new ControlInput(this); } } @Override - public Port getPort() { + public Port port() { assert port != null; return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return ControlInput.INFO; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/ResponseHandler.java b/praxiscore-code/src/main/java/org/praxislive/code/ResponseHandler.java index e6ec1110..57d62639 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/ResponseHandler.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/ResponseHandler.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2022 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -38,7 +38,7 @@ /** * */ -class ResponseHandler extends ControlDescriptor implements Control { +class ResponseHandler extends ControlDescriptor implements Control { static final String ID = "_reply"; private static final PError UNKNOWN_ERROR = PError.of("Unknown error"); @@ -48,16 +48,15 @@ class ResponseHandler extends ControlDescriptor implements Control { private CodeContext context; ResponseHandler(int index) { - super(ID, Category.Internal, index); + super(ResponseHandler.class, ID, Category.Internal, index); this.resultMap = new HashMap<>(); } @Override - public void attach(CodeContext context, Control previous) { - if (previous instanceof ResponseHandler) { - ResponseHandler prev = (ResponseHandler) previous; - resultMap.putAll(prev.resultMap); - prev.resultMap.clear(); + public void attach(CodeContext context, ResponseHandler previous) { + if (previous != null) { + resultMap.putAll(previous.resultMap); + previous.resultMap.clear(); } this.context = context; } @@ -82,12 +81,12 @@ public void call(Call call, PacketRouter router) throws Exception { } @Override - public Control getControl() { + public Control control() { return this; } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return null; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/TableProperty.java b/praxiscore-code/src/main/java/org/praxislive/code/TableProperty.java index 79a73bc9..a5e3bf4c 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/TableProperty.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/TableProperty.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -127,7 +127,7 @@ public Value execute() throws Exception { } - static class Descriptor extends ControlDescriptor { + static class Descriptor extends ControlDescriptor { private final Field field; private final boolean isList; @@ -143,7 +143,7 @@ private Descriptor( Method onChange, Method onError ) { - super(id, ControlDescriptor.Category.Property, index); + super(Descriptor.class, id, ControlDescriptor.Category.Property, index); this.field = field; this.isList = isList; this.onChange = onChange; @@ -151,24 +151,26 @@ private Descriptor( } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return INFO; } @Override @SuppressWarnings("unchecked") - public void attach(CodeContext context, Control previous) { - if (previous instanceof TableProperty - && ((TableProperty) previous).isList == isList) { - control = (TableProperty) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null && previous.isList == isList) { + control = previous.control; } else { + if (previous != null) { + previous.dispose(); + } control = new TableProperty(isList); } control.attach(context, field, onChange, onError); } @Override - public Control getControl() { + public Control control() { return control; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/TriggerControl.java b/praxiscore-code/src/main/java/org/praxislive/code/TriggerControl.java index b30fbee2..242b650c 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/TriggerControl.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/TriggerControl.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -72,7 +72,7 @@ protected void trigger(long time) { }); } - private void attach(CodeContext context, Control previous) { + private void attachImpl(CodeContext context, Control previous) { this.context = context; binding.attach(context); if (previous instanceof TriggerControl) { @@ -209,7 +209,7 @@ public boolean peek() { } - public static class Descriptor extends ControlDescriptor { + public static class Descriptor extends ControlDescriptor { private final TriggerControl control; private Field triggerField; @@ -219,19 +219,23 @@ public Descriptor(String id, int index, Binding binding) { } public Descriptor(String id, int index, Binding binding, Field triggerField) { - super(id, Category.Action, index); + super(Descriptor.class, id, Category.Action, index); control = new TriggerControl(binding); this.triggerField = triggerField; } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return INFO; } @Override - public void attach(CodeContext context, Control previous) { - control.attach(context, previous); + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + control.attachImpl(context, previous.control); + } else { + control.attachImpl(context, null); + } if (triggerField != null) { try { triggerField.set(context.getDelegate(), control); @@ -242,21 +246,23 @@ public void attach(CodeContext context, Control previous) { } @Override - public void reset(boolean full) { + public void onReset() { control.clearLinks(); control.maxIndex(Integer.MAX_VALUE); - if (full) { - control.index(0); - } } @Override - public Control getControl() { + public void onStart() { + control.index(0); + } + + @Override + public Control control() { return control; } public PortDescriptor createPortDescriptor() { - return new PortDescImpl(getID(), getIndex(), control); + return new PortDescImpl(id(), index(), control); } public static Descriptor create(CodeConnector connector, @@ -287,38 +293,36 @@ public static Descriptor create(CodeConnector connector, } - private static class PortDescImpl extends PortDescriptor implements ControlInput.Link { + private static class PortDescImpl extends PortDescriptor + implements ControlInput.Link { private final TriggerControl control; private ControlInput port; private PortDescImpl(String id, int index, TriggerControl control) { - super(id, Category.Action, index); + super(PortDescImpl.class, id, Category.Action, index); this.control = control; } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof ControlInput) { - port = (ControlInput) previous; + public void attach(CodeContext context, PortDescImpl previous) { + if (previous != null) { + port = previous.port; port.setLink(this); } else { - if (previous != null) { - previous.disconnectAll(); - } port = new ControlInput(this); } } @Override - public Port getPort() { + public Port port() { assert port != null; return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return ControlInput.INFO; } diff --git a/praxiscore-code/src/main/java/org/praxislive/code/TypeConverter.java b/praxiscore-code/src/main/java/org/praxislive/code/TypeConverter.java deleted file mode 100644 index e4535c29..00000000 --- a/praxiscore-code/src/main/java/org/praxislive/code/TypeConverter.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2018 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - * - */ -package org.praxislive.code; - -import java.lang.annotation.Annotation; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.praxislive.core.Value; -import org.praxislive.core.ValueFormatException; -import org.praxislive.core.Lookup; -import org.praxislive.core.ArgumentInfo; -import org.praxislive.core.types.PString; - -/** - * - * - */ -@Deprecated -public abstract class TypeConverter { - - public abstract Value toArgument(T value); - - public abstract T fromArgument(Value value) throws ValueFormatException; - - public abstract Class getType(); - - public ArgumentInfo getInfo() { - return ArgumentInfo.info(); - } - - public boolean isRealTimeSafe() { - return false; - } - - public Value getDefaultArgument() { - return PString.EMPTY; - } - - public T getDefaultValue() { - return null; - } - - public static interface Provider { - - public TypeConverter getTypeConverter(Class type, Annotation ... annotations); - - } - - public final static TypeConverter find(Class type, Annotation ... annotations) { - Provider[] providers = Lookup.SYSTEM.findAll(Provider.class).toArray(Provider[]::new); - try { - for (Provider p : providers) { - TypeConverter converter = p.getTypeConverter(type, annotations); - if (converter != null) { - return converter; - } - } - } catch (Exception ex) { - Logger.getLogger(TypeConverter.class.getName()) - .log(Level.SEVERE, "Exception looking for TypeConverter", ex); - } - return null; - } - -} diff --git a/praxiscore-code/src/main/java/org/praxislive/code/userapi/Input.java b/praxiscore-code/src/main/java/org/praxislive/code/userapi/Input.java index 58b6aa05..eb6fd715 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/userapi/Input.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/userapi/Input.java @@ -47,17 +47,6 @@ protected void attach(CodeContext context) { this.context = context; } - /** - * Return a {@link Linkable.Double} for reacting on inputs. None numeric - * inputs will be ignored. - * - * @return Linkable.Double of input - */ - @Deprecated(forRemoval = true) - public Linkable.Double values() { - return new DoubleLink(); - } - /** * Return a {@link Linkable.Double} for reacting on inputs. None numeric * inputs will be ignored. diff --git a/praxiscore-code/src/main/java/org/praxislive/code/userapi/Property.java b/praxiscore-code/src/main/java/org/praxislive/code/userapi/Property.java index 5f24f844..34735d80 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/userapi/Property.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/userapi/Property.java @@ -195,27 +195,6 @@ public Property link(DoubleConsumer consumer) { return this; } - @Deprecated(forRemoval = true) - public Property link(DoubleConsumer... consumers) { - for (DoubleConsumer consumer : consumers) { - link(consumer); - } - return this; - } - - /** - * Return a new {@link Linkable.Double} for observing changing values. The - * double value will be as if calling {@link #getDouble()}. - *

- * This method is deprecated. Switch to {@link #doubles} instead. - * - * @return Linkable.Double of values. - */ - @Deprecated(forRemoval = true) - public Linkable.Double values() { - return new DoubleLink(); - } - /** * Return a new {@link Linkable.Double} for observing changing values. The * double value will be as if calling {@link #getDouble()}. @@ -357,7 +336,7 @@ protected boolean hasLinks() { return links.length > 0; } - protected void reset(boolean full) { + protected void reset() { clearLinks(); if (animator != null) { animator.onDoneConsumer = null; diff --git a/praxiscore-code/src/main/java/org/praxislive/code/userapi/Ref.java b/praxiscore-code/src/main/java/org/praxislive/code/userapi/Ref.java index 0d153427..deb83a86 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/userapi/Ref.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/userapi/Ref.java @@ -190,23 +190,6 @@ public Ref setAsync(Async async) { return this; } - /** - * Run an intensive or time consuming function as a background task to - * update the value. The function should be self-contained and try not to - * capture or access any state from the component. Use the key argument to - * pass in data required to compute the new value - ideally not the current - * contents of the Ref unless it is immutable or thread-safe. - * - * @param type of key value - * @param key a key value used by the function to calculate the new value - * @param function an intensive or time-consuming function - * @return this - */ - @Deprecated - public Ref asyncCompute(K key, Function function) { - throw new UnsupportedOperationException(); - } - /** * Bind something (usually a callback / listener) to the reference, * providing for automatic attachment and removal on reference change, reset diff --git a/praxiscore-code/src/test/java/org/praxislive/code/userapi/StructTest.java b/praxiscore-code/src/test/java/org/praxislive/code/userapi/StructTest.java index 0193d77d..27f5cee3 100644 --- a/praxiscore-code/src/test/java/org/praxislive/code/userapi/StructTest.java +++ b/praxiscore-code/src/test/java/org/praxislive/code/userapi/StructTest.java @@ -3,6 +3,7 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.DataOutputStream; +import java.util.OptionalInt; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -88,15 +89,15 @@ public void testReadFrom() throws Exception { data1.forEachIn(struct1, s -> { assertEquals(0, count[0]); count[0]++; - assertEquals(new PVector(10, 20, 30), s.vec1); - assertEquals(new PVector(40, 50, 60), s.vec2); + assertEquals(new VecD3(10, 20, 30), s.vec1); + assertEquals(new VecD3(40, 50, 60), s.vec2); }); UnsizedStructImpl struct2 = new UnsizedStructImpl(); data2.forEachIn(struct2, s -> { assertEquals(1, count[0]); count[0]++; assertEquals(TEST_STRING, s.sdo.string); - assertEquals(new PVector(40, 50, 60), s.vec); + assertEquals(new VecD3(40, 50, 60), s.vec); }); double[] data = new double[6]; @@ -140,15 +141,15 @@ public void testSize() { private static class StructImpl extends Struct { - PVector vec1 = register(new PVector()); - PVector vec2 = register(new PVector()); + VecD3 vec1 = register(new VecD3(0, 0, 0)); + VecD3 vec2 = register(new VecD3(0, 0, 0)); } private static class UnsizedStructImpl extends Struct { StringDataObject sdo = register(new StringDataObject()); - PVector vec = register(new PVector()); + VecD3 vec = register(new VecD3(0, 0, 0)); } @@ -168,4 +169,67 @@ public void readFrom(DataInput in) throws Exception { } + private static class VecD3 implements DataObject { + + double x, y, z; + + VecD3(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public void writeTo(DataOutput out) throws Exception { + out.writeDouble(x); + out.writeDouble(y); + out.writeDouble(z); + } + + @Override + public void readFrom(DataInput in) throws Exception { + x = in.readDouble(); + y = in.readDouble(); + z = in.readDouble(); + } + + private final static OptionalInt SIZE = OptionalInt.of(3 * Double.BYTES); + + @Override + public OptionalInt size() { + return SIZE; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 41 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); + hash = 41 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); + hash = 41 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final VecD3 other = (VecD3) obj; + if (Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x)) { + return false; + } + if (Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y)) { + return false; + } + return Double.doubleToLongBits(this.z) == Double.doubleToLongBits(other.z); + } + + } + } diff --git a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreBodyContext.java b/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreBodyContext.java deleted file mode 100644 index b24e8c95..00000000 --- a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreBodyContext.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2018 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - */ - -package org.praxislive.core.code; - -import org.praxislive.code.CodeUtils; -import org.praxislive.code.ClassBodyContext; - -/** - * - * - */ -public class CoreBodyContext extends ClassBodyContext { - - public final static String TEMPLATE = - CodeUtils.load(CoreBodyContext.class, "resources/core_template.pxj"); - - - public CoreBodyContext() { - super(CoreCodeDelegate.class); - } - - @Override - public String[] getDefaultImports() { - return CodeUtils.defaultImports(); - } - -} diff --git a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCode.java b/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCode.java index 84cba345..ff660297 100644 --- a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCode.java +++ b/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCode.java @@ -30,8 +30,7 @@ */ public class CoreCode { - private final static List DEFAULT_IMPORTS - = List.of(CodeUtils.defaultImports()); + private final static List DEFAULT_IMPORTS = CodeUtils.defaultImports(); private final static CodeFactory.Base BASE = CodeFactory.base(CoreCodeDelegate.class, @@ -52,9 +51,9 @@ private CoreCode() { } /** - * Access {@link CodeFactory.Base} for {@link CoreContainerDelegate}. + * Access {@link CodeFactory.Base} for {@link CoreCodeDelegate}. * - * @return code factory base for CoreContainerDelegate. + * @return code factory base for CoreCodeDelegate. */ public static CodeFactory.Base base() { return BASE; diff --git a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCodeContext.java b/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCodeContext.java index 23f80101..c7c186d4 100644 --- a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCodeContext.java +++ b/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCodeContext.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -28,7 +28,7 @@ /** * - * + * */ public class CoreCodeContext extends CodeContext { @@ -37,29 +37,30 @@ public CoreCodeContext(CoreCodeConnector connector) { } @Override - protected void starting(ExecutionContext source, boolean fullStart) { + protected void onInit() { try { getDelegate().init(); } catch (Exception e) { getLog().log(LogLevel.ERROR, e, "Exception thrown during init()"); } - if (fullStart) { - try { - getDelegate().starting(); - } catch (Exception e) { - getLog().log(LogLevel.ERROR, e, "Exception thrown during starting()"); - } + + } + + @Override + protected void onStart() { + try { + getDelegate().starting(); + } catch (Exception e) { + getLog().log(LogLevel.ERROR, e, "Exception thrown during starting()"); } } @Override - protected void stopping(ExecutionContext source, boolean fullStop) { - if (fullStop) { - try { - getDelegate().stopping(); - } catch (Exception e) { - getLog().log(LogLevel.ERROR, e, "Exception thrown during stopping()"); - } + protected void onStop() { + try { + getDelegate().stopping(); + } catch (Exception e) { + getLog().log(LogLevel.ERROR, e, "Exception thrown during stopping()"); } } diff --git a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCodeFactory.java b/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCodeFactory.java deleted file mode 100644 index 66f2e082..00000000 --- a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreCodeFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2018 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - * - */ -package org.praxislive.core.code; - -import org.praxislive.code.CodeContext; -import org.praxislive.code.CodeFactory; -import org.praxislive.core.ComponentType; - -public class CoreCodeFactory extends CodeFactory { - - private final static CoreBodyContext CBC = new CoreBodyContext(); - - public CoreCodeFactory(ComponentType type, - Class baseClass, - String sourceTemplate) { - super(CBC, type, baseClass, sourceTemplate); - } - - @Override - public Task task() { - return new CoreContextCreator(); - } - - private class CoreContextCreator extends Task { - - private CoreContextCreator() { - super(CoreCodeFactory.this); - } - - @Override - protected CodeContext createCodeContext(CoreCodeDelegate delegate) { - return new CoreCodeContext(new CoreCodeConnector(this, delegate)); - } - - - } - -} diff --git a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreContainerCodeContext.java b/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreContainerCodeContext.java index 8aaae411..73fff63a 100644 --- a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreContainerCodeContext.java +++ b/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreContainerCodeContext.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2021 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -31,35 +31,35 @@ * A {@link CodeContext} for core containers. */ class CoreContainerCodeContext extends CodeContainer.Context { - + CoreContainerCodeContext(CoreContainerCodeConnector connector) { super(connector); } @Override - protected void starting(ExecutionContext source, boolean fullStart) { + protected void onInit() { try { getDelegate().init(); } catch (Exception e) { getLog().log(LogLevel.ERROR, e, "Exception thrown during init()"); } - if (fullStart) { - try { - getDelegate().starting(); - } catch (Exception e) { - getLog().log(LogLevel.ERROR, e, "Exception thrown during starting()"); - } + } + + @Override + protected void onStart() { + try { + getDelegate().starting(); + } catch (Exception e) { + getLog().log(LogLevel.ERROR, e, "Exception thrown during starting()"); } } @Override - protected void stopping(ExecutionContext source, boolean fullStop) { - if (fullStop) { - try { - getDelegate().stopping(); - } catch (Exception e) { - getLog().log(LogLevel.ERROR, e, "Exception thrown during stopping()"); - } + protected void onStop() { + try { + getDelegate().stopping(); + } catch (Exception e) { + getLog().log(LogLevel.ERROR, e, "Exception thrown during stopping()"); } } diff --git a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreRootContainerCodeContext.java b/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreRootContainerCodeContext.java index ea12414c..3ae6721b 100644 --- a/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreRootContainerCodeContext.java +++ b/praxiscore-core-code/src/main/java/org/praxislive/core/code/CoreRootContainerCodeContext.java @@ -31,38 +31,38 @@ * A {@link CodeContext} for core root containers. */ class CoreRootContainerCodeContext extends CodeRootContainer.Context { - + CoreRootContainerCodeContext(CoreRootContainerCodeConnector connector) { super(connector); } @Override - protected void starting(ExecutionContext source, boolean fullStart) { - super.starting(source, fullStart); + protected void onInit() { try { getDelegate().init(); } catch (Exception e) { getLog().log(LogLevel.ERROR, e, "Exception thrown during init()"); } - if (fullStart) { - try { - getDelegate().starting(); - } catch (Exception e) { - getLog().log(LogLevel.ERROR, e, "Exception thrown during starting()"); - } + } + + @Override + protected void onStart() { + try { + getDelegate().starting(); + } catch (Exception e) { + getLog().log(LogLevel.ERROR, e, "Exception thrown during starting()"); } + super.onStart(); } @Override - protected void stopping(ExecutionContext source, boolean fullStop) { - if (fullStop) { - try { - getDelegate().stopping(); - } catch (Exception e) { - getLog().log(LogLevel.ERROR, e, "Exception thrown during stopping()"); - } + protected void onStop() { + try { + getDelegate().stopping(); + } catch (Exception e) { + getLog().log(LogLevel.ERROR, e, "Exception thrown during stopping()"); } - super.stopping(source, fullStop); + super.onStop(); } @Override diff --git a/praxiscore-hub/src/main/java/org/praxislive/hub/DefaultComponentFactoryService.java b/praxiscore-hub/src/main/java/org/praxislive/hub/DefaultComponentFactoryService.java index 9db88a2e..1c5cce42 100644 --- a/praxiscore-hub/src/main/java/org/praxislive/hub/DefaultComponentFactoryService.java +++ b/praxiscore-hub/src/main/java/org/praxislive/hub/DefaultComponentFactoryService.java @@ -103,10 +103,11 @@ private class NewInstanceControl extends AbstractAsyncControl { protected Call processInvoke(Call call) throws Exception { ComponentType type = ComponentType.from(call.args().get(0)).orElseThrow(); ComponentFactory factory = registry.getComponentFactory(type); - if (factory.getFactoryService() != ComponentFactoryService.class) { + ComponentFactory.Redirect redirect = factory.componentRedirect().orElse(null); + if (redirect != null) { ControlAddress altFactory = getLookup().find(Services.class) - .flatMap(srvs -> srvs.locate(factory.getFactoryService())) - .map(cmp -> ControlAddress.of(cmp, ComponentFactoryService.NEW_INSTANCE)) + .flatMap(srvs -> srvs.locate(redirect.service())) + .map(cmp -> ControlAddress.of(cmp, redirect.control())) .orElseThrow(() -> new IllegalStateException("Alternative factory service not found")); return Call.create(altFactory, @@ -132,10 +133,11 @@ private class NewRootInstanceControl extends AbstractAsyncControl { protected Call processInvoke(Call call) throws Exception { ComponentType type = ComponentType.from(call.args().get(0)).orElseThrow(); ComponentFactory factory = registry.getRootComponentFactory(type); - if (factory.getRootFactoryService() != RootFactoryService.class) { + ComponentFactory.Redirect redirect = factory.rootRedirect().orElse(null); + if (redirect != null) { ControlAddress altFactory = getLookup().find(Services.class) - .flatMap(srvs -> srvs.locate(factory.getRootFactoryService())) - .map(cmp -> ControlAddress.of(cmp, RootFactoryService.NEW_ROOT_INSTANCE)) + .flatMap(srvs -> srvs.locate(redirect.service())) + .map(cmp -> ControlAddress.of(cmp, redirect.control())) .orElseThrow(() -> new IllegalStateException("Alternative factory service not found")); return Call.create(altFactory, @@ -143,7 +145,7 @@ protected Call processInvoke(Call call) throws Exception { call.time(), call.args()); } else { - Root root = factory.createRootComponent(type); + Root root = factory.createRoot(type); return call.reply(PReference.of(root)); } } diff --git a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/ConnectedProperty.java b/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/ConnectedProperty.java index 4cb595d5..080c7f82 100644 --- a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/ConnectedProperty.java +++ b/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/ConnectedProperty.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -54,27 +54,27 @@ public ControlInfo getInfo() { } - public static class Descriptor extends ControlDescriptor { + public static class Descriptor extends ControlDescriptor { private final ConnectedProperty control; public Descriptor(String id, int index) { - super(id, ControlDescriptor.Category.Property, index); + super(Descriptor.class, id, ControlDescriptor.Category.Property, index); control = new ConnectedProperty(); } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return control.getInfo(); } @Override - public void attach(CodeContext context, Control previous) { + public void attach(CodeContext context, Descriptor previous) { control.context = (TFCodeContext) context; } @Override - public Control getControl() { + public Control control() { return control; } diff --git a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/DeviceProperty.java b/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/DeviceProperty.java index a3e2526d..1703549b 100644 --- a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/DeviceProperty.java +++ b/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/DeviceProperty.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -22,7 +22,7 @@ */ package org.praxislive.tinkerforge; -import org.praxislive.code.AbstractBasicProperty; +import org.praxislive.base.AbstractProperty; import org.praxislive.code.CodeContext; import org.praxislive.code.ControlDescriptor; import org.praxislive.core.Value; @@ -35,7 +35,7 @@ /** * */ -class DeviceProperty extends AbstractBasicProperty { +class DeviceProperty extends AbstractProperty { private final static ControlInfo INFO = ControlInfo.createPropertyInfo( ArgumentInfo.of(PString.class, @@ -63,27 +63,27 @@ public ControlInfo getInfo() { } - static class Descriptor extends ControlDescriptor { + static class Descriptor extends ControlDescriptor { private final DeviceProperty control; Descriptor(String id, int index) { - super(id, Category.Property, index); + super(Descriptor.class, id, Category.Property, index); control = new DeviceProperty(); } @Override - public ControlInfo getInfo() { + public ControlInfo controlInfo() { return control.getInfo(); } @Override - public void attach(CodeContext context, Control previous) { + public void attach(CodeContext context, Descriptor previous) { control.context = (TFCodeContext) context; } @Override - public Control getControl() { + public Control control() { return control; } diff --git a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/TFBodyContext.java b/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/TFBodyContext.java deleted file mode 100644 index 60d218a6..00000000 --- a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/TFBodyContext.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2020 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - */ -package org.praxislive.tinkerforge; - -import org.praxislive.code.CodeUtils; -import org.praxislive.code.ClassBodyContext; - -/** - * - */ -public class TFBodyContext extends ClassBodyContext { - - private final static String[] IMPORTS = CodeUtils.join( - CodeUtils.defaultImports(), new String[]{ - "com.tinkerforge.*", - "org.praxislive.tinkerforge.userapi.*", - "static org.praxislive.tinkerforge.userapi.Constants.*" - }); - - public TFBodyContext() { - super(TFCodeDelegate.class); - } - - @Override - public String[] getDefaultImports() { - return IMPORTS.clone(); - } - -} diff --git a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/TFCode.java b/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/TFCode.java new file mode 100644 index 00000000..47039d3c --- /dev/null +++ b/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/TFCode.java @@ -0,0 +1,59 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2023 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code 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 Lesser General Public License + * version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit https://www.praxislive.org if you need additional information or + * have any questions. + */ +package org.praxislive.tinkerforge; + +import java.util.List; +import java.util.stream.Stream; +import org.praxislive.code.CodeFactory; +import org.praxislive.code.CodeUtils; + +/** + * Tinkerforge code utility functions. + */ +public class TFCode { + + private static final List DEFAULT_IMPORTS + = Stream.concat(CodeUtils.defaultImports().stream(), + Stream.of("com.tinkerforge.*", + "org.praxislive.tinkerforge.userapi.*", + "static org.praxislive.tinkerforge.userapi.Constants.*")) + .toList(); + + private static final CodeFactory.Base BASE + = CodeFactory.base(TFCodeDelegate.class, + DEFAULT_IMPORTS, + (task, delegate) -> new TFCodeContext(new TFCodeConnector(task, delegate))); + + private TFCode() { + + } + + /** + * Access {@link CodeFactory.Base} for {@link TFCodeDelegate}. + * + * @return code factory base for TFCodeDelegate. + */ + public static final CodeFactory.Base base() { + return BASE; + } + +} diff --git a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/TFCodeFactory.java b/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/TFCodeFactory.java deleted file mode 100644 index 7d7aaa27..00000000 --- a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/TFCodeFactory.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2020 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - * - */ -package org.praxislive.tinkerforge; - -import org.praxislive.code.CodeContext; -import org.praxislive.code.CodeFactory; -import org.praxislive.core.ComponentType; - -/** - * - */ -public class TFCodeFactory extends CodeFactory { - - - private final static TFBodyContext CBC = new TFBodyContext(); - - public TFCodeFactory(ComponentType type, - Class baseClass, - String sourceTemplate) { - super(CBC, type, baseClass, sourceTemplate); - } - - @Override - public Task task() { - return new TaskImpl(); - } - - private class TaskImpl extends Task { - - public TaskImpl() { - super(TFCodeFactory.this); - } - - @Override - protected CodeContext createCodeContext(TFCodeDelegate delegate) { - return new TFCodeContext(new TFCodeConnector(this, delegate)); - } - - } - -} diff --git a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/components/TFComponents.java b/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/components/TFComponents.java index fe7cc73f..4a035fd9 100644 --- a/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/components/TFComponents.java +++ b/praxiscore-tinkerforge/src/main/java/org/praxislive/tinkerforge/components/TFComponents.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -22,11 +22,10 @@ package org.praxislive.tinkerforge.components; import org.praxislive.code.AbstractComponentFactory; -import org.praxislive.core.ComponentType; import org.praxislive.core.services.ComponentFactory; import org.praxislive.core.services.ComponentFactoryProvider; +import org.praxislive.tinkerforge.TFCode; import org.praxislive.tinkerforge.TFCodeDelegate; -import org.praxislive.tinkerforge.TFCodeFactory; /** * @@ -68,7 +67,7 @@ private void build() { } private void add(String type, Class cls, String path) { - add(data(new TFCodeFactory(ComponentType.of(type), cls, source(path)))); + add(TFCode.base().create(type, cls, source(path))); } } diff --git a/praxiscore-video-code/src/main/java/org/praxislive/video/code/OffScreenGraphicsInfo.java b/praxiscore-video-code/src/main/java/org/praxislive/video/code/OffScreenGraphicsInfo.java index 151b56c4..3d9e4b4b 100644 --- a/praxiscore-video-code/src/main/java/org/praxislive/video/code/OffScreenGraphicsInfo.java +++ b/praxiscore-video-code/src/main/java/org/praxislive/video/code/OffScreenGraphicsInfo.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -42,7 +42,7 @@ class OffScreenGraphicsInfo { private final OffScreen.Format format; private final Field field; - private VideoCodeContext context; + private VideoCodeContext context; private OffScreenGraphics graphics; private OffScreenGraphicsInfo(Field field, diff --git a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoBodyContext.java b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoBodyContext.java deleted file mode 100644 index a800e563..00000000 --- a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoBodyContext.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2018 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - */ -package org.praxislive.video.code; - -import org.praxislive.code.CodeUtils; -import org.praxislive.code.ClassBodyContext; - -/** - * - * - */ -public class VideoBodyContext extends ClassBodyContext { - - public final static String TEMPLATE = - CodeUtils.load(VideoBodyContext.class, "resources/video_template.pxj"); - - private final static String[] IMPORTS = CodeUtils.join( - CodeUtils.defaultImports(), new String[]{ - "org.praxislive.video.code.userapi.*", - "static org.praxislive.video.code.userapi.VideoConstants.*" - }); - - public VideoBodyContext() { - super(VideoCodeDelegate.class); - } - - @Override - public String[] getDefaultImports() { - return IMPORTS.clone(); - } - -} diff --git a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCode.java b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCode.java new file mode 100644 index 00000000..450b2bda --- /dev/null +++ b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCode.java @@ -0,0 +1,58 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2023 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code 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 Lesser General Public License + * version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit https://www.praxislive.org if you need additional information or + * have any questions. + */ +package org.praxislive.video.code; + +import java.util.List; +import java.util.stream.Stream; +import org.praxislive.code.CodeFactory; +import org.praxislive.code.CodeUtils; + +/** + * Video code utility functions. + */ +public class VideoCode { + + private static final List DEFAULT_IMPORTS + = Stream.concat(CodeUtils.defaultImports().stream(), + Stream.of("org.praxislive.video.code.userapi.*", + "static org.praxislive.video.code.userapi.VideoConstants.*")) + .toList(); + + private static final CodeFactory.Base BASE + = CodeFactory.base(VideoCodeDelegate.class, + DEFAULT_IMPORTS, + (task, delegate) -> new VideoCodeContext(new VideoCodeConnector(task, delegate))); + + private VideoCode() { + + } + + /** + * Access {@link CodeFactory.Base} for {@link VideoCodeDelegate}. + * + * @return code factory base for VideoCodeDelegate. + */ + public static CodeFactory.Base base() { + return BASE; + } + +} diff --git a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeConnector.java b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeConnector.java index 1e1347b2..46071582 100644 --- a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeConnector.java +++ b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeConnector.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -41,7 +41,7 @@ * * */ -public class VideoCodeConnector extends CodeConnector { +public class VideoCodeConnector extends CodeConnector { private final static String INIT = "init"; private final static String UPDATE = "update"; @@ -52,8 +52,8 @@ public class VideoCodeConnector extends CodeConnect private boolean hasInit; private boolean hasUpdate; - public VideoCodeConnector(CodeFactory.Task contextCreator, - T delegate) { + public VideoCodeConnector(CodeFactory.Task contextCreator, + VideoCodeDelegate delegate) { super(contextCreator, delegate); offscreen = new LinkedHashMap<>(); } @@ -92,7 +92,7 @@ protected void analyseField(Field field) { P p = field.getAnnotation(P.class); if (p != null) { - ResourceProperty.Descriptor ipd = + ResourceProperty.Descriptor ipd = ResourceProperty.Descriptor.create(this, p, field, ImageLoader.getDefault()); if (ipd != null) { addControl(ipd); @@ -107,7 +107,7 @@ protected void analyseField(Field field) { if (PFont.class.isAssignableFrom(field.getType())) { P p = field.getAnnotation(P.class); if (p != null) { - ResourceProperty.Descriptor fpd = + ResourceProperty.Descriptor fpd = ResourceProperty.Descriptor.create(this, p, field, FontLoader.getDefault()); if (fpd != null) { addControl(fpd); diff --git a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeContext.java b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeContext.java index 2af45eac..58dbc03b 100644 --- a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeContext.java +++ b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeContext.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -40,12 +40,12 @@ /** * - * + * */ -public class VideoCodeContext extends CodeContext { +public class VideoCodeContext extends CodeContext { private final static UnaryOperator DEFAULT_RENDER_QUERY = b -> b; - + private final VideoOutputPort.Descriptor output; private final VideoInputPort.Descriptor[] inputs; private final Map offscreen; @@ -55,47 +55,43 @@ public class VideoCodeContext extends CodeContext renderQuery = DEFAULT_RENDER_QUERY; - public VideoCodeContext(VideoCodeConnector connector) { + public VideoCodeContext(VideoCodeConnector connector) { super(connector, connector.hasUpdate()); setupRequired = true; output = connector.extractOutput(); resetOnSetup = !connector.hasInit(); - + List ins = new ArrayList<>(); - for (String id : getPortIDs()) { - PortDescriptor pd = getPortDescriptor(id); - if (pd instanceof VideoInputPort.Descriptor) { - ins.add((VideoInputPort.Descriptor) pd); - } - } + inputs = portIDs().map(this::getPortDescriptor) + .filter(VideoInputPort.Descriptor.class::isInstance) + .map(VideoInputPort.Descriptor.class::cast) + .toArray(VideoInputPort.Descriptor[]::new); - inputs = ins.toArray(new VideoInputPort.Descriptor[ins.size()]); - offscreen = connector.extractOffScreenInfo(); - + processor = new Processor(inputs.length); } @Override - protected void configure(CodeComponent cmp, CodeContext oldCtxt) { - output.getPort().getPipe().addSource(processor); + protected void configure(CodeComponent cmp, CodeContext oldCtxt) { + output.port().getPipe().addSource(processor); for (VideoInputPort.Descriptor vidp : inputs) { - processor.addSource(vidp.getPort().getPipe()); + processor.addSource(vidp.port().getPipe()); } - configureOffScreen((VideoCodeContext) oldCtxt); + configureOffScreen((VideoCodeContext) oldCtxt); getDelegate().context = this; } - - private void configureOffScreen(VideoCodeContext oldCtxt) { + + private void configureOffScreen(VideoCodeContext oldCtxt) { Map oldOffscreen = oldCtxt == null ? Collections.EMPTY_MAP : oldCtxt.offscreen; - offscreen.forEach( (id, osgi) -> osgi.attach(this, oldOffscreen.remove(id))); - oldOffscreen.forEach( (id, osgi) -> osgi.release()); + offscreen.forEach((id, osgi) -> osgi.attach(this, oldOffscreen.remove(id))); + oldOffscreen.forEach((id, osgi) -> osgi.release()); } @Override - protected void starting(ExecutionContext source, boolean fullStart) { + protected void onInit() { setupRequired = true; renderQuery = DEFAULT_RENDER_QUERY; try { @@ -113,10 +109,8 @@ protected void starting(ExecutionContext source, boolean fullStart) { } @Override - protected void stopping(ExecutionContext source, boolean fullStop) { - if (fullStop) { - offscreen.forEach((id, osgi) -> osgi.release()); - } + protected void onStop() { + offscreen.forEach((id, osgi) -> osgi.release()); } @Override @@ -127,11 +121,11 @@ protected void tick(ExecutionContext source) { getLog().log(LogLevel.ERROR, e, "Exception thrown during update()"); } } - + void attachRenderQuery(UnaryOperator renderQuery) { this.renderQuery = Objects.requireNonNull(renderQuery); } - + void attachRenderQuery(String source, UnaryOperator renderQuery) { PortDescriptor pd = getPortDescriptor(source); if (pd instanceof VideoInputPort.Descriptor) { @@ -140,7 +134,7 @@ void attachRenderQuery(String source, UnaryOperator renderQuery) { getLog().log(LogLevel.ERROR, "No source found to attach render query : " + source); } } - + void attachAlphaQuery(String source, UnaryOperator alphaQuery) { PortDescriptor pd = getPortDescriptor(source); if (pd instanceof VideoInputPort.Descriptor) { @@ -149,9 +143,9 @@ void attachAlphaQuery(String source, UnaryOperator alphaQuery) { getLog().log(LogLevel.ERROR, "No source found to attach alpha query : " + source); } } - + private class Processor extends AbstractProcessPipe { - + private SurfacePGraphics pg; private SurfacePImage[] images; @@ -169,7 +163,7 @@ protected void update(long time) { protected void callSources(Surface output, long time) { validateImages(output); int count = getSourceCount(); - for (int i=0; i < count; i++) { + for (int i = 0; i < count; i++) { callSource(getSource(i), images[i].surface, time); } } @@ -200,7 +194,7 @@ protected void render(Surface output, long time) { releaseImages(); flush(); } - + private void validateImages(Surface output) { VideoCodeDelegate del = getDelegate(); for (int i = 0; i < images.length; i++) { @@ -217,13 +211,13 @@ private void validateImages(Surface output) { } } } - + private void releaseImages() { for (SurfacePImage image : images) { image.surface.release(); } } - + private void setImageField(VideoCodeDelegate delegate, Field field, PImage image) { try { field.set(delegate, image); @@ -231,18 +225,18 @@ private void setImageField(VideoCodeDelegate delegate, Field field, PImage image getLog().log(LogLevel.ERROR, ex); } } - + private void validateOffscreen(Surface output) { offscreen.forEach((id, osgi) -> osgi.validate(output)); } - + private void endOffscreen() { offscreen.forEach((id, osgi) -> osgi.endFrame()); } - + private void invokeSetup(VideoCodeDelegate delegate) { if (resetOnSetup) { - reset(false); + resetAndInitialize(); } try { delegate.setup(); @@ -250,7 +244,7 @@ private void invokeSetup(VideoCodeDelegate delegate) { getLog().log(LogLevel.ERROR, ex, "Exception thrown from setup()"); } } - + private void invokeDraw(VideoCodeDelegate delegate) { try { delegate.draw(); @@ -259,8 +253,6 @@ private void invokeDraw(VideoCodeDelegate delegate) { } } - - } private static class SurfacePGraphics extends PGraphics { diff --git a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeDelegate.java b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeDelegate.java index bac4388a..867a34b5 100644 --- a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeDelegate.java +++ b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeDelegate.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2019 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -47,7 +47,7 @@ public class VideoCodeDelegate extends DefaultCodeDelegate { public int width; public int height; - VideoCodeContext context; + VideoCodeContext context; PGraphics pg; void setupGraphics(PGraphics pg, int width, int height) { diff --git a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeFactory.java b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeFactory.java deleted file mode 100644 index 398ad15d..00000000 --- a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoCodeFactory.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2018 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - * - */ -package org.praxislive.video.code; - -import org.praxislive.code.CodeContext; -import org.praxislive.code.CodeFactory; -import org.praxislive.core.ComponentType; - -public class VideoCodeFactory extends CodeFactory { - - private final static VideoBodyContext VBC = new VideoBodyContext(); - - public VideoCodeFactory(ComponentType type, - Class baseClass, - String sourceTemplate) { - super(VBC, type, baseClass, sourceTemplate); - } - - @Override - public Task task() { - return new VideoContextCreator(); - } - - private class VideoContextCreator extends Task { - - private VideoContextCreator() { - super(VideoCodeFactory.this); - } - - @Override - protected CodeContext createCodeContext(VideoCodeDelegate delegate) { - return new VideoCodeContext(new VideoCodeConnector(this, delegate)); - } - - } - -} diff --git a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoInputPort.java b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoInputPort.java index 0e6875e4..98b19049 100644 --- a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoInputPort.java +++ b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoInputPort.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -28,7 +28,6 @@ import java.util.function.UnaryOperator; import org.praxislive.code.CodeContext; import org.praxislive.code.PortDescriptor; -import org.praxislive.core.Port; import org.praxislive.core.PortInfo; import org.praxislive.core.types.PMap; import org.praxislive.video.DefaultVideoInputPort; @@ -71,7 +70,7 @@ protected boolean isRenderRequired(VideoPipe source, long time) { } - static class Descriptor extends PortDescriptor { + static class Descriptor extends PortDescriptor { private final static PortInfo INFO = PortInfo.create(VideoPort.class, PortInfo.Direction.IN, PMap.EMPTY); @@ -84,39 +83,36 @@ static class Descriptor extends PortDescriptor { } Descriptor(String id, int index, Field field) { - super(id, Category.In, index); + super(Descriptor.class, id, Category.In, index); this.field = field; field.setAccessible(true); } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof VideoInputPort) { - VideoInputPort vip = (VideoInputPort) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + VideoInputPort vip = previous.port; if (vip.pipe.getSinkCount() == 1) { vip.pipe.getSink(0).removeSource(vip.pipe); } port = vip; } else { - if (previous != null) { - previous.disconnectAll(); - } port = new VideoInputPort(); } } @Override - public VideoInputPort getPort() { + public VideoInputPort port() { return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return INFO; } @Override - public void reset(boolean full) { + public void onReset() { alphaQuery = DEFAULT_QUERY; port.pipe.query = DEFAULT_QUERY; } diff --git a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoOutputPort.java b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoOutputPort.java index 19b0789e..e485d79d 100644 --- a/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoOutputPort.java +++ b/praxiscore-video-code/src/main/java/org/praxislive/video/code/VideoOutputPort.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -24,7 +24,6 @@ import org.praxislive.code.CodeContext; import org.praxislive.code.PortDescriptor; -import org.praxislive.core.Port; import org.praxislive.core.PortInfo; import org.praxislive.core.types.PMap; import org.praxislive.video.DefaultVideoOutputPort; @@ -50,39 +49,36 @@ VideoPipe getPipe() { } - static class Descriptor extends PortDescriptor { + static class Descriptor extends PortDescriptor { private final static PortInfo INFO = PortInfo.create(VideoPort.class, PortInfo.Direction.OUT, PMap.EMPTY); private VideoOutputPort port; Descriptor(String id, int index) { - super(id, Category.Out, index); + super(Descriptor.class, id, Category.Out, index); } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof VideoOutputPort) { - VideoOutputPort vip = (VideoOutputPort) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + VideoOutputPort vip = previous.port; if (vip.pipe.getSourceCount() == 1) { vip.pipe.removeSource(vip.pipe.getSource(0)); } port = vip; } else { - if (previous != null) { - previous.disconnectAll(); - } port = new VideoOutputPort(new Placeholder()); } } @Override - public VideoOutputPort getPort() { + public VideoOutputPort port() { return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return INFO; } diff --git a/praxiscore-video-components/src/main/java/org/praxislive/video/components/VideoComponents.java b/praxiscore-video-components/src/main/java/org/praxislive/video/components/VideoComponents.java index ad2c225c..810cc264 100644 --- a/praxiscore-video-components/src/main/java/org/praxislive/video/components/VideoComponents.java +++ b/praxiscore-video-components/src/main/java/org/praxislive/video/components/VideoComponents.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -22,18 +22,18 @@ package org.praxislive.video.components; import org.praxislive.code.AbstractComponentFactory; -import org.praxislive.core.ComponentType; import org.praxislive.core.services.ComponentFactory; import org.praxislive.core.services.ComponentFactoryProvider; +import org.praxislive.video.code.VideoCode; import org.praxislive.video.code.VideoCodeDelegate; -import org.praxislive.video.code.VideoCodeFactory; /** * - * + * */ public class VideoComponents implements ComponentFactoryProvider { - private final static Factory instance = new Factory(); + + private static final Factory instance = new Factory(); @Override public ComponentFactory getFactory() { @@ -47,37 +47,34 @@ private Factory() { } private void build() { - + // custom add("video:custom", VideoCustom.class, VideoCustom.TEMPLATE_PATH); add("video:composite", VideoComposite.class, VideoComposite.TEMPLATE_PATH); add("video:xfader", VideoXFader.class, VideoXFader.TEMPLATE_PATH); - + // built-in - // CORE VIDEO add("video:snapshot", VideoSnapshot.class, VideoSnapshot.TEMPLATE_PATH); add("video:still", VideoStill.class, VideoStill.TEMPLATE_PATH); - + // ANALYSIS add("video:analysis:frame-delay", VideoAnalysisFrameDelay.class, VideoAnalysisFrameDelay.TEMPLATE_PATH); add("video:analysis:difference", VideoAnalysisDifference.class, VideoAnalysisDifference.TEMPLATE_PATH); - + // FX add("video:fx:blur", VideoFXBlur.class, VideoFXBlur.TEMPLATE_PATH); - + // SOURCE add("video:source:noise", VideoSourceNoise.class, VideoSourceNoise.TEMPLATE_PATH); - + } private void add(String type, Class cls, String path) { - add(data( - new VideoCodeFactory(ComponentType.of(type), cls, source(path)) - )); + add(VideoCode.base().create(type, cls, source(path))); } - + } -} \ No newline at end of file +} diff --git a/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerComponents.java b/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerComponents.java index c227257e..61a18b4b 100644 --- a/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerComponents.java +++ b/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerComponents.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -22,11 +22,10 @@ package org.praxislive.video.gstreamer.components; import org.praxislive.code.AbstractComponentFactory; -import org.praxislive.core.ComponentType; import org.praxislive.core.services.ComponentFactory; import org.praxislive.core.services.ComponentFactoryProvider; +import org.praxislive.video.code.VideoCode; import org.praxislive.video.code.VideoCodeDelegate; -import org.praxislive.video.code.VideoCodeFactory; /** * @@ -53,9 +52,7 @@ private void build() { } private void add(String type, Class cls, String path) { - add(data( - new VideoCodeFactory(ComponentType.of(type), cls, source(path)) - )); + add(VideoCode.base().create(type, cls, source(path))); } } diff --git a/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerVideoCapture.java b/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerVideoCapture.java index 051cb061..1d9d5ef5 100644 --- a/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerVideoCapture.java +++ b/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerVideoCapture.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2020 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -304,24 +304,21 @@ private void messageOnEOS() { } } - static class Descriptor extends ReferenceDescriptor { + static class Descriptor extends ReferenceDescriptor { private final Field field; private GStreamerVideoCapture capture; private Descriptor(String id, Field field) { - super(id); + super(Descriptor.class, id); this.field = field; } @Override - public void attach(CodeContext context, ReferenceDescriptor previous) { - if (previous instanceof Descriptor) { - Descriptor prevImpl = (Descriptor) previous; - capture = prevImpl.capture; - prevImpl.capture = null; - } else if (previous != null) { - previous.dispose(); + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + capture = previous.capture; + previous.capture = null; } if (capture == null) { @@ -339,8 +336,13 @@ public void attach(CodeContext context, ReferenceDescriptor previous) { } @Override - public void reset(boolean full) { - capture.reset(full); + public void onReset() { + capture.reset(false); + } + + @Override + public void onStop() { + capture.reset(true); } @Override diff --git a/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerVideoPlayer.java b/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerVideoPlayer.java index 9b238ece..14415466 100644 --- a/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerVideoPlayer.java +++ b/praxiscore-video-gstreamer/src/main/java/org/praxislive/video/gstreamer/components/GStreamerVideoPlayer.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2019 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -53,10 +53,10 @@ /** * - * + * */ class GStreamerVideoPlayer implements VideoPlayer { - + private volatile State state; private final PlayBin playbin; @@ -408,24 +408,21 @@ private void messageOnEOS() { } } - static class Descriptor extends ReferenceDescriptor { + static class Descriptor extends ReferenceDescriptor { private final Field field; private GStreamerVideoPlayer player; private Descriptor(String id, Field field) { - super(id); + super(Descriptor.class, id); this.field = field; } @Override - public void attach(CodeContext context, ReferenceDescriptor previous) { - if (previous instanceof Descriptor) { - Descriptor prevImpl = (Descriptor) previous; - player = prevImpl.player; - prevImpl.player = null; - } else if (previous != null) { - previous.dispose(); + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + player = previous.player; + previous.player = null; } if (player == null) { @@ -443,8 +440,13 @@ public void attach(CodeContext context, ReferenceDescriptor previous) { } @Override - public void reset(boolean full) { - player.reset(full); + public void onReset() { + player.reset(false); + } + + @Override + public void onStop() { + player.reset(true); } @Override diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DClassBodyContext.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DClassBodyContext.java deleted file mode 100644 index a92f187d..00000000 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DClassBodyContext.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2018 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - */ - -package org.praxislive.video.pgl.code; - -import org.praxislive.code.CodeUtils; -import org.praxislive.code.ClassBodyContext; - -/** - * - * - */ -public class P2DClassBodyContext extends ClassBodyContext { - - public final static String TEMPLATE - = CodeUtils.load(P2DClassBodyContext.class, "resources/p3d_template.pxj"); - - private final static String[] IMPORTS = CodeUtils.join( - CodeUtils.defaultImports(), new String[]{ - "org.praxislive.video.pgl.code.userapi.*", - "static org.praxislive.video.pgl.code.userapi.Constants.*" - }); - - public P2DClassBodyContext() { - super(P2DCodeDelegate.class); - } - - @Override - public String[] getDefaultImports() { - return IMPORTS.clone(); - } - - - -} diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeConnector.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeConnector.java index d644302a..3c41d604 100644 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeConnector.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeConnector.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -96,7 +96,7 @@ protected void analyseField(Field field) { P p = field.getAnnotation(P.class); if (p != null) { if (PImage.class.isAssignableFrom(field.getType())) { - ResourceProperty.Descriptor ipd + ResourceProperty.Descriptor ipd = ResourceProperty.Descriptor.create(this, p, field, ImageLoader.getDefault()); if (ipd != null) { addControl(ipd); @@ -108,7 +108,7 @@ protected void analyseField(Field field) { } if (PFont.class.isAssignableFrom(field.getType())) { - ResourceProperty.Descriptor fpd + ResourceProperty.Descriptor fpd = ResourceProperty.Descriptor.create(this, p, field, FontLoader.getDefault()); if (fpd != null) { addControl(fpd); @@ -120,7 +120,7 @@ protected void analyseField(Field field) { } if (PShape.class.isAssignableFrom(field.getType())) { - ResourceProperty.Descriptor spd + ResourceProperty.Descriptor spd = ResourceProperty.Descriptor.create(this, p, field, ShapeLoader.getDefault()); if (spd != null) { addControl(spd); diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeContext.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeContext.java index c020fe7f..61a6188d 100644 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeContext.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeContext.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -30,7 +30,6 @@ import java.util.Optional; import org.praxislive.code.CodeComponent; import org.praxislive.code.CodeContext; -import org.praxislive.code.PortDescriptor; import org.praxislive.core.ExecutionContext; import org.praxislive.core.services.LogLevel; import org.praxislive.video.pgl.PGLContext; @@ -63,14 +62,10 @@ public P2DCodeContext(P2DCodeConnector connector) { List ins = new ArrayList<>(); - for (String id : getPortIDs()) { - PortDescriptor pd = getPortDescriptor(id); - if (pd instanceof PGLVideoInputPort.Descriptor) { - ins.add((PGLVideoInputPort.Descriptor) pd); - } - } - - inputs = ins.toArray(new PGLVideoInputPort.Descriptor[ins.size()]); + inputs = portIDs().map(this::getPortDescriptor) + .filter(PGLVideoInputPort.Descriptor.class::isInstance) + .map(PGLVideoInputPort.Descriptor.class::cast) + .toArray(PGLVideoInputPort.Descriptor[]::new); offscreen = connector.extractOffScreenInfo(); @@ -79,9 +74,9 @@ public P2DCodeContext(P2DCodeConnector connector) { @Override protected void configure(CodeComponent cmp, CodeContext oldCtxt) { - output.getPort().getPipe().addSource(processor); + output.port().getPipe().addSource(processor); for (PGLVideoInputPort.Descriptor vidp : inputs) { - processor.addSource(vidp.getPort().getPipe()); + processor.addSource(vidp.port().getPipe()); } configureOffScreen((P2DCodeContext) oldCtxt); } @@ -94,7 +89,7 @@ private void configureOffScreen(P2DCodeContext oldCtxt) { } @Override - protected void starting(ExecutionContext source) { + protected void onInit() { setupRequired = true; try { getDelegate().init(); @@ -104,7 +99,7 @@ protected void starting(ExecutionContext source) { } @Override - protected void stopping(ExecutionContext source, boolean fullStop) { + protected void onStop() { offscreen.forEach((id, osgi) -> osgi.release()); } @@ -173,7 +168,7 @@ protected void render(Surface output, long time) { del.configure(pglOut.getContext().parent(), pg, output.getWidth(), output.getHeight()); if (setupRequired) { if (resetOnSetup) { - reset(false); + resetAndInitialize(); } try { del.setup(); diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeDelegate.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeDelegate.java index cf3a4220..5a1544ef 100644 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeDelegate.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeDelegate.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2022 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -23,7 +23,6 @@ package org.praxislive.video.pgl.code; import java.util.Optional; -import org.praxislive.code.DefaultCodeDelegate; import org.praxislive.video.pgl.code.userapi.Constants; import org.praxislive.video.pgl.code.userapi.PFont; import org.praxislive.video.pgl.code.userapi.PGraphics2D; @@ -32,7 +31,7 @@ import org.praxislive.video.pgl.code.userapi.PShape; import processing.core.PApplet; -public class P2DCodeDelegate extends DefaultCodeDelegate { +public class P2DCodeDelegate extends PGLCodeDelegate { public int width; public int height; @@ -542,57 +541,4 @@ public void filter(PShader shader) { pg.filter(shader); } - @Override - @SuppressWarnings("deprecation") - public double noise(double x) { - return super.noise(x); - } - - @Override - @SuppressWarnings("deprecation") - public double noise(double x, double y) { - return super.noise(x, y); - } - - @Override - @SuppressWarnings("deprecation") - public double noise(double x, double y, double z) { - return super.noise(x, y, z); - } - - @Override - @SuppressWarnings("deprecation") - public void noiseDetail(int lod) { - super.noiseDetail(lod); - } - - @Override - @SuppressWarnings("deprecation") - public void noiseDetail(int lod, double falloff) { - super.noiseDetail(lod, falloff); - } - - @Override - @SuppressWarnings("deprecation") - public void noiseSeed(long what) { - super.noiseSeed(what); - } - - @Override - @SuppressWarnings("deprecation") - public void arrayCopy(Object src, Object dst) { - super.arrayCopy(src, dst); - } - - @Override - @SuppressWarnings("deprecation") - public void arrayCopy(Object src, Object dst, int length) { - super.arrayCopy(src, dst, length); - } - - @Override - @SuppressWarnings("deprecation") - public void arrayCopy(Object src, int srcPosition, Object dst, int dstPosition, int length) { - super.arrayCopy(src, srcPosition, dst, dstPosition, length); - } } diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeFactory.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeFactory.java deleted file mode 100644 index 7d217ab6..00000000 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P2DCodeFactory.java +++ /dev/null @@ -1,45 +0,0 @@ - - -package org.praxislive.video.pgl.code; - -import org.praxislive.code.CodeContext; -import org.praxislive.code.CodeFactory; -import org.praxislive.core.ComponentType; - - -public class P2DCodeFactory extends CodeFactory { - - private final static P2DClassBodyContext CBC = new P2DClassBodyContext(); - - private final boolean emptyDefault; - - public P2DCodeFactory(String type) { - super(CBC, ComponentType.of(type), P2DClassBodyContext.TEMPLATE); - emptyDefault = true; - } - - public P2DCodeFactory(String type, String sourceTemplate) { - super(CBC, ComponentType.of(type), sourceTemplate); - emptyDefault = false; - } - - @Override - public Task task() { - return new P2DContextCreator(); - } - - private class P2DContextCreator extends Task { - - private P2DContextCreator() { - super(P2DCodeFactory.this); - } - - @Override - protected CodeContext createCodeContext(P2DCodeDelegate delegate) { - return new P2DCodeContext(new P2DCodeConnector(this, delegate)); - } - - - } - -} diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DClassBodyContext.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DClassBodyContext.java deleted file mode 100644 index aa4e5e58..00000000 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DClassBodyContext.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2018 Neil C Smith. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 3 only, as - * published by the Free Software Foundation. - * - * This code 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 Lesser General Public License - * version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License version 3 - * along with this work; if not, see http://www.gnu.org/licenses/ - * - * - * Please visit https://www.praxislive.org if you need additional information or - * have any questions. - */ -package org.praxislive.video.pgl.code; - -import org.praxislive.code.CodeUtils; -import org.praxislive.code.ClassBodyContext; - -/** - * - * - */ -public class P3DClassBodyContext extends ClassBodyContext { - - public final static String TEMPLATE - = CodeUtils.load(P3DClassBodyContext.class, "resources/p3d_template.pxj"); - - private final static String[] IMPORTS = CodeUtils.join( - CodeUtils.defaultImports(), new String[]{ - "org.praxislive.video.pgl.code.userapi.*", - "static org.praxislive.video.pgl.code.userapi.Constants.*" - }); - - public P3DClassBodyContext() { - super(P3DCodeDelegate.class); - } - - @Override - public String[] getDefaultImports() { - return IMPORTS.clone(); - } - -} diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeConnector.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeConnector.java index eb6f1d27..72588630 100644 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeConnector.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeConnector.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -96,7 +96,7 @@ protected void analyseField(Field field) { P p = field.getAnnotation(P.class); if (p != null) { if (PImage.class.isAssignableFrom(field.getType())) { - ResourceProperty.Descriptor ipd + ResourceProperty.Descriptor ipd = ResourceProperty.Descriptor.create(this, p, field, ImageLoader.getDefault()); if (ipd != null) { addControl(ipd); @@ -108,7 +108,7 @@ protected void analyseField(Field field) { } if (PFont.class.isAssignableFrom(field.getType())) { - ResourceProperty.Descriptor fpd + ResourceProperty.Descriptor fpd = ResourceProperty.Descriptor.create(this, p, field, FontLoader.getDefault()); if (fpd != null) { addControl(fpd); @@ -120,7 +120,7 @@ protected void analyseField(Field field) { } if (PShape.class.isAssignableFrom(field.getType())) { - ResourceProperty.Descriptor spd + ResourceProperty.Descriptor spd = ResourceProperty.Descriptor.create(this, p, field, ShapeLoader.getDefault()); if (spd != null) { addControl(spd); diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeContext.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeContext.java index 10910cc9..293910b4 100644 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeContext.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeContext.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2019 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -30,7 +30,6 @@ import java.util.Optional; import org.praxislive.code.CodeComponent; import org.praxislive.code.CodeContext; -import org.praxislive.code.PortDescriptor; import org.praxislive.core.ExecutionContext; import org.praxislive.core.services.LogLevel; import org.praxislive.video.pgl.PGLContext; @@ -64,14 +63,10 @@ public P3DCodeContext(P3DCodeConnector connector) { List ins = new ArrayList<>(); - for (String id : getPortIDs()) { - PortDescriptor pd = getPortDescriptor(id); - if (pd instanceof PGLVideoInputPort.Descriptor) { - ins.add((PGLVideoInputPort.Descriptor) pd); - } - } - - inputs = ins.toArray(new PGLVideoInputPort.Descriptor[ins.size()]); + inputs = portIDs().map(this::getPortDescriptor) + .filter(PGLVideoInputPort.Descriptor.class::isInstance) + .map(PGLVideoInputPort.Descriptor.class::cast) + .toArray(PGLVideoInputPort.Descriptor[]::new); offscreen = connector.extractOffScreenInfo(); @@ -81,9 +76,9 @@ public P3DCodeContext(P3DCodeConnector connector) { @Override protected void configure(CodeComponent cmp, CodeContext oldCtxt) { super.configure(cmp, oldCtxt); - output.getPort().getPipe().addSource(processor); + output.port().getPipe().addSource(processor); for (PGLVideoInputPort.Descriptor vidp : inputs) { - processor.addSource(vidp.getPort().getPipe()); + processor.addSource(vidp.port().getPipe()); } P3DCodeContext oldP3DCtxt = (P3DCodeContext) oldCtxt; configureOffScreen(oldP3DCtxt); @@ -105,7 +100,7 @@ private void configureProcessor(P3DCodeContext oldP3DCtxt) { } @Override - public void starting(ExecutionContext source) { + public void onInit() { setupRequired = true; // processor.dispose3D(); try { @@ -116,7 +111,12 @@ public void starting(ExecutionContext source) { } @Override - protected void stopping(ExecutionContext source, boolean fullStop) { + protected void onReset() { + processor.dispose3D(); + } + + @Override + protected void onStop() { processor.dispose3D(); offscreen.forEach((id, osgi) -> osgi.release()); } @@ -196,7 +196,7 @@ protected void render(Surface output, long time) { // pg.resetMatrix(); if (setupRequired) { if (resetOnSetup) { - reset(false); + resetAndInitialize(); } p3d.style(null); try { diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeDelegate.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeDelegate.java index 42c43fed..042bf2d2 100644 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeDelegate.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeDelegate.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2022 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -23,7 +23,6 @@ package org.praxislive.video.pgl.code; import java.util.Optional; -import org.praxislive.code.DefaultCodeDelegate; import org.praxislive.video.pgl.code.userapi.Constants; import org.praxislive.video.pgl.code.userapi.PFont; import org.praxislive.video.pgl.code.userapi.PGraphics3D; @@ -32,7 +31,7 @@ import org.praxislive.video.pgl.code.userapi.PShape; import processing.core.PApplet; -public class P3DCodeDelegate extends DefaultCodeDelegate { +public class P3DCodeDelegate extends PGLCodeDelegate { public int width; public int height; @@ -753,59 +752,5 @@ public void resetShader() { public void filter(PShader shader) { pg.filter(shader); } - - @Override - @SuppressWarnings("deprecation") - public double noise(double x) { - return super.noise(x); - } - - @Override - @SuppressWarnings("deprecation") - public double noise(double x, double y) { - return super.noise(x, y); - } - - @Override - @SuppressWarnings("deprecation") - public double noise(double x, double y, double z) { - return super.noise(x, y, z); - } - - @Override - @SuppressWarnings("deprecation") - public void noiseDetail(int lod) { - super.noiseDetail(lod); - } - - @Override - @SuppressWarnings("deprecation") - public void noiseDetail(int lod, double falloff) { - super.noiseDetail(lod, falloff); - } - - @Override - @SuppressWarnings("deprecation") - public void noiseSeed(long what) { - super.noiseSeed(what); - } - - @Override - @SuppressWarnings("deprecation") - public void arrayCopy(Object src, Object dst) { - super.arrayCopy(src, dst); - } - - @Override - @SuppressWarnings("deprecation") - public void arrayCopy(Object src, Object dst, int length) { - super.arrayCopy(src, dst, length); - } - - @Override - @SuppressWarnings("deprecation") - public void arrayCopy(Object src, int srcPosition, Object dst, int dstPosition, int length) { - super.arrayCopy(src, srcPosition, dst, dstPosition, length); - } } diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeFactory.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeFactory.java deleted file mode 100644 index 439cfa00..00000000 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/P3DCodeFactory.java +++ /dev/null @@ -1,45 +0,0 @@ - - -package org.praxislive.video.pgl.code; - -import org.praxislive.code.CodeContext; -import org.praxislive.code.CodeFactory; -import org.praxislive.core.ComponentType; - - -public class P3DCodeFactory extends CodeFactory { - - private final static P3DClassBodyContext CBC = new P3DClassBodyContext(); - - private final boolean emptyDefault; - - public P3DCodeFactory(String type) { - super(CBC, ComponentType.of(type), P3DClassBodyContext.TEMPLATE); - emptyDefault = true; - } - - public P3DCodeFactory(String type, String sourceTemplate) { - super(CBC, ComponentType.of(type), sourceTemplate); - emptyDefault = false; - } - - @Override - public Task task() { - return new P3DContextCreator(); - } - - private class P3DContextCreator extends Task { - - private P3DContextCreator() { - super(P3DCodeFactory.this); - } - - @Override - protected CodeContext createCodeContext(P3DCodeDelegate delegate) { - return new P3DCodeContext(new P3DCodeConnector(this, delegate)); - } - - - } - -} diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLCode.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLCode.java new file mode 100644 index 00000000..d54aa2ea --- /dev/null +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLCode.java @@ -0,0 +1,72 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2023 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code 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 Lesser General Public License + * version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit https://www.praxislive.org if you need additional information or + * have any questions. + */ +package org.praxislive.video.pgl.code; + +import java.util.List; +import java.util.stream.Stream; +import org.praxislive.code.CodeFactory; +import org.praxislive.code.CodeUtils; + +/** + * PGL code utility functions. + */ +public class PGLCode { + + private static final List DEFAULT_IMPORTS + = Stream.concat(CodeUtils.defaultImports().stream(), + Stream.of("org.praxislive.video.pgl.code.userapi.*", + "static org.praxislive.video.pgl.code.userapi.Constants.*")) + .toList(); + + private static final CodeFactory.Base BASE_2D + = CodeFactory.base(P2DCodeDelegate.class, + DEFAULT_IMPORTS, + (task, delegate) -> new P2DCodeContext(new P2DCodeConnector(task, delegate))); + + private static final CodeFactory.Base BASE_3D + = CodeFactory.base(P3DCodeDelegate.class, + DEFAULT_IMPORTS, + (task, delegate) -> new P3DCodeContext(new P3DCodeConnector(task, delegate))); + + private PGLCode() { + + } + + /** + * Access {@link CodeFactory.Base} for {@link P2DCodeDelegate}. + * + * @return code factory base for P2DCodeDelegate. + */ + public static CodeFactory.Base base2D() { + return BASE_2D; + } + + /** + * Access {@link CodeFactory.Base} for {@link P3DCodeDelegate}. + * + * @return code factory base for P3DCodeDelegate. + */ + public static CodeFactory.Base base3D() { + return BASE_3D; + } + +} diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLCodeDelegate.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLCodeDelegate.java new file mode 100644 index 00000000..8a170bf6 --- /dev/null +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLCodeDelegate.java @@ -0,0 +1,255 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2023 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code 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 Lesser General Public License + * version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit https://www.praxislive.org if you need additional information or + * have any questions. + * + */ + +package org.praxislive.video.pgl.code; + +import java.lang.reflect.Array; +import java.util.Random; +import org.praxislive.code.DefaultCodeDelegate; +import org.praxislive.code.userapi.Constants; + +/** + * + */ +abstract class PGLCodeDelegate extends DefaultCodeDelegate { + + // PERLIN NOISE - copied from Processing core. + // @TODO fully convert to double??? + private static final int PERLIN_YWRAPB = 4; + private static final int PERLIN_YWRAP = 1 << PERLIN_YWRAPB; + private static final int PERLIN_ZWRAPB = 8; + private static final int PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB; + private static final int PERLIN_SIZE = 4095; + private static final float cosLUT[]; + private static final float SINCOS_PRECISION = 0.5f; + private static final int SINCOS_LENGTH = (int) (360f / SINCOS_PRECISION); + + static { + cosLUT = new float[SINCOS_LENGTH]; + for (int i = 0; i < SINCOS_LENGTH; i++) { + cosLUT[i] = (float) Math.cos(i * Constants.DEG_TO_RAD * SINCOS_PRECISION); + } + } + private int perlin_octaves = 4; // default to medium smooth + private float perlin_amp_falloff = 0.5f; // 50% reduction/octave + private int perlin_TWOPI, perlin_PI; + private float[] perlin_cosTable; + private float[] perlin; + private Random perlinRandom; + + /** + * Computes the Perlin noise function value at point x. + * + * @param x + * @return + */ + public double noise(double x) { + return noise(x, 0f, 0f); + } + + /** + * Computes the Perlin noise function value at the point x, y. + * + * @param x + * @param y + * @return + */ + public double noise(double x, double y) { + return noise(x, y, 0f); + } + + /** + * Computes the Perlin noise function value at x, y, z. + * + * @param x + * @param z + * @param y + * @return + */ + public double noise(double x, double y, double z) { + if (perlin == null) { + if (perlinRandom == null) { + perlinRandom = new Random(); + } + perlin = new float[PERLIN_SIZE + 1]; + for (int i = 0; i < PERLIN_SIZE + 1; i++) { + perlin[i] = perlinRandom.nextFloat(); + } + perlin_cosTable = cosLUT; + perlin_TWOPI = perlin_PI = SINCOS_LENGTH; + perlin_PI >>= 1; + } + + if (x < 0) { + x = -x; + } + if (y < 0) { + y = -y; + } + if (z < 0) { + z = -z; + } + + int xi = (int) x, yi = (int) y, zi = (int) z; + float xf = (float) (x - xi); + float yf = (float) (y - yi); + float zf = (float) (z - zi); + float rxf, ryf; + + float r = 0; + float ampl = 0.5f; + + float n1, n2, n3; + + for (int i = 0; i < perlin_octaves; i++) { + int of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB); + + rxf = noise_fsc(xf); + ryf = noise_fsc(yf); + + n1 = perlin[of & PERLIN_SIZE]; + n1 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1); + n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; + n2 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2); + n1 += ryf * (n2 - n1); + + of += PERLIN_ZWRAP; + n2 = perlin[of & PERLIN_SIZE]; + n2 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2); + n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; + n3 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3); + n2 += ryf * (n3 - n2); + + n1 += noise_fsc(zf) * (n2 - n1); + + r += n1 * ampl; + ampl *= perlin_amp_falloff; + xi <<= 1; + xf *= 2; + yi <<= 1; + yf *= 2; + zi <<= 1; + zf *= 2; + + if (xf >= 1.0f) { + xi++; + xf--; + } + if (yf >= 1.0f) { + yi++; + yf--; + } + if (zf >= 1.0f) { + zi++; + zf--; + } + } + return r; + } + + private float noise_fsc(float i) { + return 0.5f * (1.0f - perlin_cosTable[(int) (i * perlin_PI) % perlin_TWOPI]); + } + + // make perlin noise quality user controlled to allow + // for different levels of detail. lower values will produce + // smoother results as higher octaves are surpressed + /** + * + * @param lod + */ + public void noiseDetail(int lod) { + if (lod > 0) { + perlin_octaves = lod; + } + } + + /** + * + * @param lod + * @param falloff + */ + public void noiseDetail(int lod, double falloff) { + if (lod > 0) { + perlin_octaves = lod; + } + if (falloff > 0) { + perlin_amp_falloff = (float) falloff; + } + } + + /** + * + * @param what + */ + public void noiseSeed(long what) { + if (perlinRandom == null) { + perlinRandom = new Random(); + } + perlinRandom.setSeed(what); + perlin = null; + } + + // end of Perlin noise functions + // start of PApplet statics + /** + * Copies an array (or part of an array) to another array. The src array is + * copied to the dst array, beginning at the position specified by srcPos + * and into the position specified by dstPos. The number of elements to copy + * is determined by length. + * + * @param src + * @param srcPosition + * @param dst + * @param dstPosition + * @param length + */ + public void arrayCopy(Object src, int srcPosition, Object dst, int dstPosition, int length) { + System.arraycopy(src, srcPosition, dst, dstPosition, length); + } + + /** + * Copies an array (or part of an array) to another array. The src array is + * copied to the dst array. The number of elements to copy is determined by + * length. + * + * @param src + * @param dst + * @param length + */ + public void arrayCopy(Object src, Object dst, int length) { + System.arraycopy(src, 0, dst, 0, length); + } + + /** + * Copies an array to another array. The src array is copied to the dst + * array. + * + * @param src + * @param dst + */ + public void arrayCopy(Object src, Object dst) { + System.arraycopy(src, 0, dst, 0, Array.getLength(src)); + } + +} diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLCustomFactoryProvider.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLCustomFactoryProvider.java index 4c92e598..9601c4dc 100644 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLCustomFactoryProvider.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLCustomFactoryProvider.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -19,23 +19,21 @@ * Please visit https://www.praxislive.org if you need additional information or * have any questions. */ - package org.praxislive.video.pgl.code; import org.praxislive.code.AbstractComponentFactory; import org.praxislive.core.services.ComponentFactory; import org.praxislive.core.services.ComponentFactoryProvider; - /** * - * + * */ public class PGLCustomFactoryProvider implements ComponentFactoryProvider { + private static final Factory instance = new Factory(); - private static Factory instance = new Factory(); - + @Override public ComponentFactory getFactory() { return instance; } @@ -47,8 +45,10 @@ private Factory() { } private void build() { - add(data(new P2DCodeFactory("video:gl:p2d"))); - add(data(new P3DCodeFactory("video:gl:p3d"))); + add(PGLCode.base2D().create("video:gl:p2d", P2DCodeDelegate.class, + source("resources/p2d_template.pxj"))); + add(PGLCode.base3D().create("video:gl:p3d", P3DCodeDelegate.class, + source("resources/p3d_template.pxj"))); } } diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLVideoInputPort.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLVideoInputPort.java index 430de41e..8c9cf7bb 100644 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLVideoInputPort.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLVideoInputPort.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -20,13 +20,11 @@ * have any questions. * */ - package org.praxislive.video.pgl.code; import java.lang.reflect.Field; import org.praxislive.code.CodeContext; import org.praxislive.code.PortDescriptor; -import org.praxislive.core.Port; import org.praxislive.core.PortInfo; import org.praxislive.core.types.PMap; import org.praxislive.video.DefaultVideoInputPort; @@ -36,68 +34,64 @@ /** * - * + * */ class PGLVideoInputPort extends DefaultVideoInputPort { - + private Placeholder pipe; - + private PGLVideoInputPort(Placeholder pipe) { super(pipe); this.pipe = pipe; } - + VideoPipe getPipe() { return pipe; } - - - static class Descriptor extends PortDescriptor { - + + static class Descriptor extends PortDescriptor { + private final static PortInfo INFO = PortInfo.create(VideoPort.class, PortInfo.Direction.IN, PMap.EMPTY); - + private PGLVideoInputPort port; private Field field; - + Descriptor(String id, int index) { this(id, index, null); } - + Descriptor(String id, int index, Field field) { - super(id, Category.In, index); + super(Descriptor.class, id, Category.In, index); this.field = field; } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof PGLVideoInputPort) { - PGLVideoInputPort vip = (PGLVideoInputPort) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + PGLVideoInputPort vip = previous.port; if (vip.pipe.getSinkCount() == 1) { vip.pipe.getSink(0).removeSource(vip.pipe); } port = vip; } else { - if (previous != null) { - previous.disconnectAll(); - } port = new PGLVideoInputPort(new Placeholder()); } } @Override - public PGLVideoInputPort getPort() { + public PGLVideoInputPort port() { return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return INFO; } - + Field getField() { return field; } - + } - + } diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLVideoOutputPort.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLVideoOutputPort.java index e36b0885..ff85b932 100644 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLVideoOutputPort.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/PGLVideoOutputPort.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -24,7 +24,6 @@ import org.praxislive.code.CodeContext; import org.praxislive.code.PortDescriptor; -import org.praxislive.core.Port; import org.praxislive.core.PortInfo; import org.praxislive.core.types.PMap; import org.praxislive.video.DefaultVideoOutputPort; @@ -34,58 +33,54 @@ /** * - * + * */ class PGLVideoOutputPort extends DefaultVideoOutputPort { - + private Placeholder pipe; - + private PGLVideoOutputPort(Placeholder pipe) { super(pipe); this.pipe = pipe; } - + VideoPipe getPipe() { return pipe; } - - - static class Descriptor extends PortDescriptor { - + + static class Descriptor extends PortDescriptor { + private final static PortInfo INFO = PortInfo.create(VideoPort.class, PortInfo.Direction.OUT, PMap.EMPTY); - + private PGLVideoOutputPort port; - + Descriptor(String id, int index) { - super(id, Category.Out, index); + super(Descriptor.class, id, Category.Out, index); } @Override - public void attach(CodeContext context, Port previous) { - if (previous instanceof PGLVideoOutputPort) { - PGLVideoOutputPort vip = (PGLVideoOutputPort) previous; + public void attach(CodeContext context, Descriptor previous) { + if (previous != null) { + PGLVideoOutputPort vip = previous.port; if (vip.pipe.getSourceCount() == 1) { vip.pipe.removeSource(vip.pipe.getSource(0)); } port = vip; } else { - if (previous != null) { - previous.disconnectAll(); - } port = new PGLVideoOutputPort(new Placeholder()); } } @Override - public PGLVideoOutputPort getPort() { + public PGLVideoOutputPort port() { return port; } @Override - public PortInfo getInfo() { + public PortInfo portInfo() { return INFO; } - + } - + } diff --git a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/userapi/PShape.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/userapi/PShape.java index 756ac6b9..98f4997c 100644 --- a/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/userapi/PShape.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/userapi/PShape.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Neil C Smith. + * Copyright 2023 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 only, as @@ -31,7 +31,6 @@ package org.praxislive.video.pgl.code.userapi; import java.util.Optional; -import org.praxislive.code.userapi.PVector; import org.praxislive.video.pgl.PGLContext; /** diff --git a/praxiscore-code/src/main/java/org/praxislive/code/userapi/PVector.java b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/userapi/PVector.java similarity index 99% rename from praxiscore-code/src/main/java/org/praxislive/code/userapi/PVector.java rename to praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/userapi/PVector.java index 82fa712d..47d8f39c 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/userapi/PVector.java +++ b/praxiscore-video-pgl-code/src/main/java/org/praxislive/video/pgl/code/userapi/PVector.java @@ -1,5 +1,5 @@ /* - Copyright 2018 Neil C Smith + Copyright 2023 Neil C Smith Derived from the Processing project - http://processing.org @@ -21,7 +21,7 @@ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -package org.praxislive.code.userapi; +package org.praxislive.video.pgl.code.userapi; import java.io.DataInput; import java.io.DataOutput; @@ -70,7 +70,6 @@ * * @webref math */ -@Deprecated(forRemoval = true) public class PVector implements Serializable, DataObject { /**