Praxis LIVE build:120123

A short note that a new build, and first full release, of Praxis LIVE is now available for download from http://code.google.com/p/praxis/

This is a slightly late post as I was concentrating on getting it finished and uploaded prior to flying to Toronto on Wednesday. There’s a wide range of new features, including a live GUI editor, a MIDI control editor, and component editors. The project system, save support and hub management have been revisited to make them much more robust. Many components have been refactored to ensure a more consistent naming and ordering of controls and ports. And the UI has had a bit of spit and polish, with a consistent icon style and colour scheme throughout – it’s looking sexy now! :-)

Read the full release notes.

The image above shows one of the major additions to this release, the GUI editor. Praxis uses MigLayout and the edit overlay allows you to drag components from the palette into a running control panel, and move them around using the arrow keys. Component properties are accessible by double-clicking to open the component editor dialogs (or in the properties window). Drag and drop of existing components, and a UI for other layout features is coming soon.  And I’ll blog a bit more about the implementation as it develops.

NB. Some of the architectural changes mean that projects from EA builds may not be fully compatible.  The examples have all been updated.  It is intended to keep backwards compatibility from this release onwards.

So, it’s a full release – is it beta?

No, though it’s better! :-D   Simply put, a couple of blog posts I’ve read over the last month or so have convinced me that the whole alpha, beta, whatever cycle is just not right for a project like Praxis / Praxis LIVE that is continually evolving.  Different features are at a different stage of evolution – some are what I’d consider release quality, some are beta, and some are quite definitely temperamental, anti-social, and marked as such!  The important thing is that it’s usable, the basic architecture is complete, and the framework (Praxis) and visual editor (Praxis LIVE) are now in sync and developing concurrently.  So, from now on there will be frequent incremental releases on a 4-6 week timetable.

So, what’s next?

Lot’s more components (some of which are already in testing), improved OpenGL support (which didn’t make this release, sorry), and much better documentation (I have a project where I have to teach 2 people to use Praxis LIVE this next month, so that will help!).

And some blogging about the details; the fun (and occasional hair pulling) of Java audio / video; and the joys of hacking on top of the NetBeans platform, without which none of this would have been possible.

JNA 3.4.0 on the NetBeans Platform

This is a little problem that’s been bugging me for a while – how to use a newer version of JNA (Java Native Access) with a NetBeans platform application.  The recently released JNA 3.4.0 brings some major performance improvements for callbacks, and as this improvement was requested by me (particularly for JNAJack) I’m damn well going to use it! :-)

So, what’s the problem?

Well,

  • JNA is in the platform, but it’s an old version.
  • A number of platform modules require JNA.
  • JNA includes a native library, which precludes having multiple versions of JNA in the module system.
  • JNA in the platform only allows friend dependencies (don’t get me started on the annoyance of friend dependencies on modules that provide native libs!)

And, the solution -

  • Create a new library wrapper module for JNA 3.4.0. Give the wrapper module the same code name base as the core JNA module – org.netbeans.libs.jna
  • Give the new wrapper module the same major release version as the platform JNA (1), and a specification version higher than the platform JNA (I chose 3.4.0 as the logical choice)
  • Make sure JNA is enabled in the platform. This confused me for a while, but the excluded modules list has no sense of clusters, so if you exclude JNA from the platform, your new module will also be excluded!  (that would probably make a good RFE)
  • Make sure you’ve got a module in your application that has a dependency on the new JNA module (ie. depends on version 3.4.0).  Not sure how necessary this is, but it seems to ensure the right module is loaded, and you’ll need the dependency to rely on the new features anyway.

Run your application and look at the module list in the log.  You should see the new version of JNA being loaded.

So, are we done?

Well, not quite.  This allows us to run our application from the IDE with the new JNA module.  However, if you build a zip distribution you’ll notice that the old JNA module is still in the platform folder.  It shouldn’t cause a problem, but it takes up space and for safety’s sake it would be better to get rid of it.

To do that, I copied the build-zip target from the build harness into the build.xml file of my application, and made a few changes (see comment).

<target name="build-zip" depends="build,build-launchers" description="Builds a ZIP distribution of the suite, launchers, and selected modules from the platform.">
  <mkdir dir="${dist.dir}"/>
  <!-- pathfileset does not support 'prefix' and 'filemode' parameters,
       we have to copy them to temp location -->
  <tempfile property="temp.dir.nbexec" destdir="${suite.build.dir}" deleteonexit="true" prefix="nbexec"/>
  <tempfile property="temp.dir.rest" destdir="${suite.build.dir}" deleteonexit="delete" prefix="rest"/>
  <subant genericantfile="${harness.dir}/suite.xml" target="copy-cluster" inheritrefs="true">
    <property name="dest.dir" value="${temp.dir.rest}"/>
    <property name="nbexec.dir" value="${temp.dir.nbexec}"/>
    <property name="build.dir" value="${suite.build.dir}"/>
    <resources refid="zip.platform.clusters"/>
  </subant>
  <zip destfile="${dist.dir}/${app.name}.zip">
    <zipfileset dir="${build.launcher.dir}/bin/" filemode="755" prefix="${app.name}/bin"/>
    <zipfileset dir="${build.launcher.dir}/etc/" prefix="${app.name}/etc"/>
    <zipfileset dir="${temp.dir.nbexec}" filemode="755" prefix="${app.name}"/>
    <zipfileset dir="${temp.dir.rest}" prefix="${app.name}">
      <!-- FOLLOWING THREE LINES REMOVE JNA FROM PLATFORM -->
      <exclude name="platform/**/org-netbeans-libs-jna*"/>
      <exclude name="platform/**/jna-3.2.7.jar"/>
      <exclude name="platform/**/*jnidispatch*"/>
    </zipfileset>

    <!-- Yes, the doubled app.name is a bit ugly, but better than the alternative; cf. #66441: -->
    <zipfileset dir="${cluster}" prefix="${app.name}/${app.name}">
      <exclude name="config/Modules/*.xml_hidden"/>
    </zipfileset>
  </zip>
</target>

In particular, notice the three exclude lines that match various artefacts of the JNA module and exclude them from the zip file (and therefore also from the installers).

This all seems to be working fine, and will be used in the (slightly late) first full release of Praxis, which is based on NetBeans platform 7.0.  It may require tweaking to work with other versions of the platform.

Embedded Satellite View Redux

This is something I’ve been meaning to write up for a couple of months now …

Praxis LIVE uses the NetBeans visual library to create a patcher-style graph editor.  The first EA release of Praxis LIVE had the satellite view for this graph editor inside a separate (Navigator) component, which proved to be a real usability nightmare in practice.  I then saw Geertjan’s post about an Embedded Satellite Panel (with due thanks to Lukasz Jopek), which inspired me to look at embedding the satellite view within the graph editor itself.  Having the satellite view in the top left still felt awkward in practice though – the bottom right feels more natural for me in use.

This code swaps FlowLayout for GridBagLayout, which gives much greater flexibility in positioning the satellite view.  The weight parameters ensure the grid cell takes up the whole of the available area, and the anchor and inset parameters place our satellite view in the bottom-right corner, with a neat gap from the the edge.

The other change is to make the panel holding the satellite view opaque, which feels a bit neater.

JPanel viewPanel = new JPanel(new BorderLayout());
JScrollPane scroll = new JScrollPane(
  scene.createView(),
  JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
  JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
viewPanel.add(scroll, BorderLayout.CENTER);

JPanel satellitePanel = new JPanel();
satellitePanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.weighty = 1;
gbc.insets = new Insets(0,0,25,25);
gbc.anchor = GridBagConstraints.SOUTHEAST;
JComponent view = scene.createSatelliteView();
JPanel holder = new JPanel(new BorderLayout());
holder.setBorder(new LineBorder(Color.LIGHT_GRAY, 1));
holder.add(view);
satellitePanel.add(holder, gbc);
satellitePanel.setOpaque(false);

panel = new JLayeredPane();
panel.setLayout(new OverlayLayout(panel));
panel.add(viewPanel, JLayeredPane.DEFAULT_LAYER);
panel.add(satellitePanel, JLayeredPane.PALETTE_LAYER);

The result …

Source code in context.

Praxis LIVE EA:111130

A third early-access build of Praxis LIVE is now available for download from http://code.google.com/p/praxis/  This release includes the start of OpenGL support (based on LWJGL, with a bit of code “borrowed” from libGDX), a new Settings API, and improvements to the Projects system, as well as a range of smaller improvements and bug fixes.

A first beta release is planned for (hopefully!) the end of the year, bringing graphical editing of control panels (GUIs) and MIDI bindings, improved OpenGL support, a range of new audio, video & control components, and improved documentation.  Features planned that may not make it into the first beta, though work has started, include support for live-coding GLSL video effects, and the ability to export Praxis LIVE projects as standalone applications.

Read the full release notes.

The most exciting bit for me is finally getting into implementing the OpenGL renderer. Above you can see a live webcam image of yours truly disintegrating into over 10,000 particles using the OpenGL pipeline. The particle code is live-compiled Java inside a code component, all editable on the fly and using a subset of the Processing API. Once more ops are hardware accelerated and it’s possible to get live-compiled GLSL shaders in there too, this could get fun! :-)

Blogging has kind of given way to coding in the last couple of months – more blogging is planned as I head towards beta … honest!

The dark arts of NetBeans hackery

Since before it was a NetBeans RCP based application, Praxis had its own Swing look-and-feel – a (minimal) fork of the lovely NimROD. Well, when I was transitioning to the NetBeans platform, I was determined to keep this look-and-feel. Unfortunately, this being a dark (white on black) look-and-feel, a small amount of hackery was required to get NetBeans to play nicely. I thought I’d document three of these here. What follows may be of use to any NetBeans developer working with non-default look and feels; it may not make much sense to a non-NetBeans developer!

Hack #1

I install the Praxis LAF within a ModuleInstall class’s restored() method. This makes the build process nice and simple, but it does have its drawbacks.

Praxis tabs problem

Here you can see an early attempt at installing the Praxis look and feel.  hmm … the look and feel doesn’t have any green in it, so where did that green tab come from?

NetBeans has some code (in the org.netbeans.swing.plaf module) that handles changing the look and feel at runtime, switching out values from the old look and feel. Unfortunately, a few values set in AllLFCustoms are never removed and are set using a class called GuaranteedValue. Most of the GuaranteedValues delegate to another value in the UI table – unfortunately, they only delegate at creation time, which means the old values (in this case the green from my GTK theme) hangs about.

So, what do I do about it? In the code below from my ModuleInstall I take the nuclear option, completely clearing the UIDefaults table before installing my look and feel, then make sure all the necessary values are set in my LFCustoms subclass.

public void restored() {
 try {
   EventQueue.invokeAndWait(new Runnable() {
     @Override
     public void run() {
       UIManager.getDefaults().clear();
       ClassLoader cl = Lookup.getDefault().lookup(ClassLoader.class);
       UIManager.put("ClassLoader", cl);
       UIManager.put("Nb.PraxisLFCustoms", new PraxisLFCustoms());
       try {
         LookAndFeel laf = new PraxisLookAndFeel();
         UIManager.setLookAndFeel(laf);
       } catch (UnsupportedLookAndFeelException ex) {}
     }
   });
 } catch (Exception ex) {}
}

Hack #2

So, now the main text and tabs in my look and feel are looking OK. However, there are still a few issues. Firstly, notice the help pane in the Property component here -

Praxis Property TopComponent visual problem

This isn’t used much in Praxis yet, but that text that currently says “Unrecognized File” is not meant to be black and barely readable! This component is a JEditorPane, and unfortunately JEditorPane’s don’t care much about your default colour scheme. There is a client property for JEditorPane to get it to play ball, but how to get access to this component in order to set it when it’s hidden inside non-public code?

Well, to do this I create a custom UI delegate for JEditorPanes and register it in my LFCustoms class (from #1). In this I set the required client property.

public class HonorDisplayEditorPaneUI extends BasicEditorPaneUI {

  public static ComponentUI createUI(JComponent c) {
    c.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
    return new HonorDisplayEditorPaneUI();
  }
}

Problem solved!

Praxis Property TopComponent fixed

Hack #3

The third and final hack I’m going to demonstrate is with the Options dialog. Here you can see the problem – the Options dialog buttons along the top have colours and borders hard-coded in that don’t fit well with our colour scheme.

Praxis Options dialog with problem

So, apart from wanting to scream why, why, why, why, why??? :-) what can be done about it? The buttons are a hidden inner class, which is inaccessible, and subclass JLabel – ah, there’s our answer, in similar fashion to #2 we can create a custom UI delegate and override some of the behaviour.

In this class I create a custom UI delegate just for JLabel subclasses from the Options module, and listen in and override properties being set.  I also make sure the parent JPanel has its background set to black.

public class OptionsAwareLabelUI extends MetalLabelUI {

  private static final Color oldHighlighted = new Color(224, 232, 246);
  private final Color fgNormal = MetalLookAndFeel.getBlack();
  private final Color bgNormal = MetalLookAndFeel.getWhite();
  private final Color bgSelected = MetalLookAndFeel.getPrimaryControlShadow();
  private final Color bgHighlighted = bgSelected.darker().darker();
  private final Border normalBorder = new EmptyBorder(6, 8, 6, 8);
  private final Border highlightBorder = new CompoundBorder(
    new CompoundBorder(
      new LineBorder(bgNormal),
      new BevelBorder(BevelBorder.LOWERED)),
    new EmptyBorder(3, 5, 3, 5));
  private boolean ignoreChanges;

@Override
public void propertyChange(PropertyChangeEvent e) {
  if (ignoreChanges) {
    super.propertyChange(e);
    return;
  }
  if (!(e.getSource() instanceof JLabel)) {
    super.propertyChange(e);
    return;
  }
  JLabel c = (JLabel) e.getSource();
  checkParent(c);
  if ("background".equals(e.getPropertyName())) {
    ignoreChanges = true;
    Color bgCurrent = c.getBackground();
    if (Color.WHITE.equals(bgCurrent)) {
      c.setBackground(bgNormal);
    } else if (oldHighlighted.equals(bgCurrent)) {
      c.setBackground(bgHighlighted);
    } else if (!bgNormal.equals(bgCurrent)) {
      c.setBackground(bgSelected);
    }
    ignoreChanges = false;
  } else if ("foreground".equals(e.getPropertyName())) {
    ignoreChanges = true;
    if (!fgNormal.equals(c.getForeground())) {
      c.setForeground(fgNormal);
    }
    ignoreChanges = false;
  } else if ("border".equals(e.getPropertyName())) {
    ignoreChanges = true;
    Border current = c.getBorder();
    if (current instanceof EmptyBorder) {
      c.setBorder(normalBorder);
    } else {
      c.setBorder(highlightBorder);
    }
    ignoreChanges = false;
  } else {
    super.propertyChange(e);
  }
}

private void checkParent(JComponent c) {
  Component parent = c.getParent();
  if (parent instanceof JPanel) {
    if (!bgNormal.equals(parent.getBackground())) {
      parent.setBackground(bgNormal);
    }
  }
}

public static ComponentUI createUI(JComponent c) {
  if (c.getClass().getName().startsWith("org.netbeans.modules.options")) {
    return new OptionsAwareLabelUI();
  } else {
    return MetalLabelUI.createUI(c);
  }
}
}

And now we get this – not perfect yet, but at least it’s the right colour-scheme!

Praxis Options dialog fixed

Conclusion

Well, a rather long first post about NetBeans but hopefully this is of use to someone else.  Just remember, they’re hacks and rely on underlying behaviour of non-public code so will need checking against new versions of the NetBeans platform.

You can find all this code in LAF module in the Praxis LIVE repository.

Now, I’m off to write some RFE’s so hopefully these hacks won’t be needed in future! :-)

Hello World!

So, how exactly does one start a blog?! :-)

What’s it all about?

This is a development blog for Praxis and Praxis LIVE. Praxis is a free, open-source Java-based modular framework for live creative play with video, images, audio, and other media. Its primary focus is on the easy development of generative and interactive media installations, as well as live performance. Praxis LIVE is a graphical, patcher-style interface for developing Praxis projects ‘on the fly’. Praxis is developed by UK Artist and Technologist Neil C Smith. It is partly inspired by projects such as AudioMulch, Bidule and Isadora, and to a lesser extent Pure Data and Processing; however, it is not intended to be a clone of any of them.

This blog is a repository for me to upload code, thoughts, snippets and resources relating to Praxis, Java (in particular relating to Java audio, graphics and video), developing on top of the NetBeans rich-client platform, and to media coding in general.

What’s it look like?

Praxis LIVE screenshot

Praxis LIVE

A live compiled particle system blended on top of a live webcam image.  Also shows some of the blend modes available in the underlying graphics library.

Who are you?

My name is Neil C Smith, and I am a UK-based artist & technologist. You can find more about me and my practice at http://neilcsmith.net. Praxis derives from code I have used in my professional practice for a number of years, and most of my more recent work is developed with Praxis itself.

What you look like? :-)

If you’re really that interested, that’s me behind all the particles above.