Wednesday, December 30, 2015

Fuer Elise

Not a tech post at all, it's an arrangement of Fuer Elise for ukulele. This is pretty easy to play. My uke is strung with a low G, but this sounds fine with a regular G also.

Here's a link to a compressed MuseScore2 file in case you want to edit or play it in MuseScoreFuer_Elise.mscz


Thursday, October 29, 2015

Using Antlr with jEdit

I've written a number of parsers in the past with javacc, but my recent struggles in modifying my Java 7 grammar to support Java 8 got me to looking at other options. I'd been reading good things about Antlr 4 (Antlr is at www.antlr.org), so I gave it a try. I've been very impressed. It's easy to use, well documented, and well architected. The on-line documentation is great, but it's worth buying the book.

Of course, I'm creating and editing Antlr grammars with jEdit, so I wrote a few things for jEdit to make it easier to work with Antlr.

First is an edit mode for the *.g4 grammar files:
https://sourceforge.net/p/jedit/svn/HEAD/tree/jEdit/trunk/modes/antlr4.xml

This lets jEdit provide syntax highlighting for the grammar files. Here's an example using the Java 8 grammar:


grammar Java8;

@lexer::members {
    public static final int WHITESPACE = 1;
    public static final int COMMENTS = 2;
}

/*
 * Productions from §3 (Lexical Structure)
 */

literal
    :   IntegerLiteral
    |   FloatingPointLiteral
    |   BooleanLiteral
    |   CharacterLiteral
    |   StringLiteral
    |   NullLiteral
    ;

/*
 * Productions from §4 (Types, Values, and Variables)
 */

type
    :   primitiveType
    |   referenceType
    ;

primitiveType
    :   annotation* numericType
    |   annotation* 'boolean'
    ;

Antlr produces a couple of *.tokens files, one for the parser, and one for the lexer. It turns out these are just properties files, which jEdit already has good support for. To get jEdit to recognize these token files as property files, it is just a matter of going to Utilities - Global Options - Editing, choosing the Properties edit mode, and adding "token" as a file name extension to the existing list of extensions. Now the token files look like this:


THROW=45 
STATIC=39 
INTERFACE=29 
AND_ASSIGN=96 
BREAK=5 
BYTE=6 
ELSE=16 
IF=23 
ENUM=17 
SUB=83 
BANG=70 
LPAREN=58 
DOT=66 
CASE=7

Notice there is no order to these, so the JavaSideKick plugin, which supports properties files, is very useful:
















Even more useful is an Antlr Sidekick. The parser for this Sidekick is written in Antlr. I packaged Antlr itself in a separate library plugin so it can be updated independently of the Antlr Sidekick plugin.


Notice the lexer and parser rules are in separate nodes in the tree and the usual sidekick features such as sorting and filtering are supported.

The Antlr Sidekick also has one action that is really useful, if a *.g4 file is the current file in jEdit, then going to Plugins - AntlrSidekick - Generate files will run Antlr on the g4 file and generate (or regenerate) the parser, lexer, and listener files, so there is no need to go to the command line to do so.


Friday, August 28, 2015

Getting rid of the Java beep

This has been quite an adventure. I didn't think that something as simple-sounding as adding an option to jEdit to turn off the beeping noise that some of the components make would be a big deal. I thought it would be something along the lines of adding a utility method that checked a property to see if the beep should happen or not, then change all the beep calls to use this new utility method. Not even close to the right solution. The problem with this approach is that many of the JVM provided Swing components also beep and, of course, those components would have no idea about my utility method.
After some research on the internet and perusing the Swing source code, the right way to cause a component to beep is to use the look and feel to provide error feedback to the user. In fact, that is the exact method in the look and feel to use: provideErrorFeedback. By default, this method simply calls Toolkit.beep(). Here is the complete method as implemented in Java 1.8:

    /**
     * Invoked when the user attempts an invalid operation,
     * such as pasting into an uneditable <code>JTextField</code>
     * that has focus. The default implementation beeps. Subclasses
     * that wish different behavior should override this and provide
     * the additional feedback.
     *
     * @param component the <code>Component</code> the error occurred in,
     *                  may be <code>null</code>
     *                  indicating the error condition is not directly
     *                  associated with a <code>Component</code>
     * @since 1.4
     */
    public void provideErrorFeedback(Component component) {
        Toolkit toolkit = null;
        if (component != null) {
            toolkit = component.getToolkit();
        } else {
            toolkit = Toolkit.getDefaultToolkit();
        }
        toolkit.beep();
    } // provideErrorFeedback()

I grepped the Swing source code, and no component calls Toolkit.beep() directly. The only call to Toolkit.beep() is in the provideErrorFeedback method. So this leads me to believe that the proper way to implement a beep is via the look and feel rather than calling Toolkit.beep() directly. My next thought was to use one of the byte code manipulation libraries like BCEL or Javaassist in the LookAndFeel plugin to change the method to look like this:
 public void provideErrorFeedback(Component component) {
     if (!"true".equals(System.getProperty("allowBeep")))
         return;
     Toolkit toolkit = null;
     if (component != null) {
         toolkit = component.getToolkit();
     } else {
         toolkit = Toolkit.getDefaultToolkit();
     }
     toolkit.beep();
 } // provideErrorFeedback()

That seemed pretty straightforward, so I wrote a class loader for the LookAndFeel plugin that would insert the line or the whole method. This worked well, until I realized that this will only work for a look and feel loaded through the LookAndFeel plugin, not any of the Swing look and feels. I know many people are satisfied with Metal or Nimbus, and this approach wouldn't work for those. I did go ahead and give it a go anyway, adjusting the LookAndFeel plugin to let the user select the built-in look and feels and attempt to patch them on the fly, but the JVM security manager wouldn't allow it.
A note about the byte code manipulation libraries, I ended up using Javassist as it is easier to work with. BCEL is fine, but works at a lower level and has a fairly steep learning curve.
My last approach, and the most successful, is to use the Java instrumentation API and use that to patch javax.swing.LookAndFeel directly. This works well since every look and feel that I have the source code to does not override the provideErrorFeedback method in that class, so it's the single place where all look and feels, and thus all components, go to make a beep. The downside of this is the code must kick in at JVM start up time, which means it can't be in a regular jEdit plugin, since those don't get loaded until well after the JVM classes.
Using the instrumentation API is really simple. All that is needed is a Java agent. The one I wrote looks like this:

package javassist;

import java.io.*;
import java.lang.instrument.*;
import java.security.ProtectionDomain;

/**
 * Simple java agent to fix the <code>provideErrorFeedback</code> in javax.swing.LookAndFeel.
 * This adds a line to that method to check the System property "allowBeep" before it 
 * proceeds with beeping. If "allowBeep" is anything other than "true", the method returns
 * immediately without providing any error feedback.
 */
public final class LNFAgent implements ClassFileTransformer {

    private static final String CLASS_TO_PATCH = "javax/swing/LookAndFeel";

    public static void premain( String agentArgument, final Instrumentation instrumentation ) {
        LNFAgent agent = null;

        try {
            agent = new LNFAgent();
        } catch ( Exception e ) {
            System.out.println("LNFAgent not installed.");
            return;
        }
        instrumentation.addTransformer( agent );
        System.setProperty("LNFAgentInstalled", "true");
    }

    @Override
    public byte[] transform( final ClassLoader loader, String className, final Class classBeingRedefined, final ProtectionDomain protectionDomain, final byte[] classfileBuffer ) throws IllegalClassFormatException {
        byte[] result = null;

        if ( className.equals( CLASS_TO_PATCH ) ) {
            try {
                CtClass ctClass = ClassPool.getDefault().makeClass( new DataInputStream( new ByteArrayInputStream( classfileBuffer ) ) );
                CtMethod ctMethod = ctClass.getDeclaredMethod( "provideErrorFeedback" );
                ctMethod.insertBefore( "if (!\"true\".equals(System.getProperty(\"allowBeep\"))) return;" );
                result = ctClass.toBytecode();
            } catch ( Exception e ) {
                System.err.println("Unable to patch javax.swing.LookAndFeel to disable beeps.");
            }
        }
        return result;
    }
}
Here's a quick run through of this code:
  • First, I put this code in the javassist package. My thought is to go ahead and make a plugin out of Javassist anyway, and insert this agent into the Javassist jar file.
  • The premain method is the method required by the instrumentation API. This method gets called on JVM start up and initializes the agent. For this purpose. I'm setting a System property to indicate that the agent has been installed so that my LookAndFeel plugin can know.
  • The transform method is where the actual code gets inserted into the provideErrorFeedback method. Again, this method is specified by the instrumentation API. Notice that the Javassist code is only 3 lines. The corresponding BCEL code was about 30.
To get the JVM to load this code on start up requires two more adjustments.
First, the manifest in the jar needs a couple of settings. These 3 lines need to be added:

Premain-Class: javassist.LNFAgent
Agent-Class: javassist.LNFAgent
Boot-Class-Path: JavassistPlugin.jar
Technically, all that is required by the instrumentation API is the Premain-Class and Agent-Class settings. The Boot-Class-Path is required to get the rest of Javassist loaded.
Once this adjusted manifest is added to the jar file, all coding is complete.
The last step is to adjust the command line to start jEdit to invoke the agent on start up. I have a small script I use to start jEdit that sets a couple of environment variables. It looks like this:

#!/bin/sh
export JEDIT_HOME=/home/danson/apps/jedit/current

# Antialias fonts everywhere possible.
ANTIALIAS_ALL="-Dawt.useSystemAAFontSettings=on -Dswing.aatext=true"
export VISUAL=/home/danson/bin/jeditcommit
export EDITOR=$VISUAL

# this one for general usage
#java -Xmx620m -Xms512m ${ANTIALIAS_ALL} "-Djedit.home=$JEDIT_HOME" -jar "$JEDIT_HOME/jedit.jar" -reuseview "$@"


# this one for debugging
#java ${ANTIALIAS_ALL} -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8001,suspend=n -Xmx512m -jar /home/danson/apps/jedit/current/jedit.jar -reuseview > /dev/null 2>&1 &

# this one for no beeps
java -javaagent:/home/danson/.jedit/jars/JavassistPlugin.jar -Xmx620m -Xms512m ${ANTIALIAS_ALL} "-Djedit.home=$JEDIT_HOME" -jar "$JEDIT_HOME/jedit.jar" -reuseview "$@"

The key piece here is that -javaagent part. This tells the JVM to look in JavassistPlugin.jar for a java agent. The manifest tells the JVM the rest of the details. Once the agent is loaded, every single class that the JVM loads is passed to the transform method in the agent, which looks only for the javax.swing.LookAndFeel class, and inserts the tiny bit of code needed to toggle the beep.
That's really all there is to it. My main problems with this approach are
  • The command line to start jEdit needs to be set by hand. There isn't a way to get the agent code to run without including the -javaagent parameter.
  • Packaging this as a jEdit plugin is not right, since jEdit loads plugins late in the start up process and loads them each in their own classloader. Since this agent code is loaded way before jEdit, it can't take advantage of any of the usual plugin facilities.
  • When used as an agent, the plugin cannot be reloaded since it is loaded in the system classloader.
  • And the biggest problem is that I shouldn't need to patch a JVM class. Really, Sun/Oracle should have included what is basically a one-liner to allow apps to turn off the error feedback. It's a simple fix that quite a few people would take advantage of, myself included.
One more note: the right way to make a beep is to make a call like this:
javax.swing.UIManager.getLookAndFeel().provideErrorFeedback(null);
Instead of null, the appropriate component can be passed. Using Toolkit.beep() directly short-circuits the ability of the look and feel to provide it's own implementation of appropriate error feedback, so don't do it! Now I need to go through the jEdit code itself and change out all 156 of those calls to Toolkit.beep()



















Friday, May 22, 2015

Arduino speaker controller

I've had this project in mind for a while, and finally got around to it. I wanted a way to turn on or off the various speakers around the house. In addition to the front room, where the main stereo is, we have speakers in the dining room, hot tub area, and back patio. Previously, I could turn on the amp, pick a playlist from Kodi, and make it play all from my phone, but if I was outside on the patio, I had to go back in the house and push a button to turn on the speakers. No more! Now I have a simple web app and an Arduino controller to turn on the speakers.

 I got a lot of inspiration and ideas for this project from http://www.33snowflakes.com/blog/arduino-android-speaker-selector/. There is even a link to a nice looking Android app to control the speaker relays, but I couldn't get it to work, so I just did a little web app that runs on Arduino to control the speakers. I got just about all the parts from Amazon:


Here is the wiring to control the relay board. The brown wire on the left connects to the 9V output on the Arduino to power the relays themselves. The black wire on the right is the ground, and is common to the board and the relays. The white wire connects to the 5V output on the Arduino to power the relay circuit board.

A close up of the connections on the relay board. Again, the brown wire on the right is connected to the 9V output on the Arduino and powers the relays themselves, while the white wire is connected to the 5V output on the Arduino to power the relay circuit board. The other wires are connected to pins 2 through 9 on the Arduino to actually trigger the relays.


Here are the connections on the Arduino side. You can see the 5V white wire, the black ground wire, and the 9V brown wire. The other wires are connected to pins 2 though 9 to control the 8 relays.

Just a big picture of the completed wiring between the Arduino and the relay board

A shot of everything in the box. My dremel skills aren't the best, but this will be in a cabinet and essentially hidden from view, so it's okay. There are cut outs for the ethernet, USB, and power connections.

The speakers will connect here. It might have been better if I'd found similar connectors that were all black. For this use, each speaker gets two connectors. The negative wire is cut, then one of the cut ends goes in the top row of connectors and the other cut end connects to the corresponding connector in the bottom row. The relay then completes the circuit. These are installed right to left, so the right most connector is controlled by relay 1, and the left most connector is controlled by relay 8. I did it this way so it would be easier to wire into my stereo cabinet. Note that this piece is one of about 6 that make all the speakers work. 

A shot of the inside. It looks messy, but it's pretty straightforward.


The code is a simple web server. The IP address is hard-coded to 192.168.2.251 so it's easy to bookmark in my phone's browser. The web page it produces looks like this, both on my phone and on my desktop browser:


Pretty plain, but it does the right thing.




/*
Simple web server to serve a form to turn on or off digital pins. In this case,
the pins are connected to relays to turn speakers on or off. This uses pins
2 through 9 in pairs, so 2 and 3 control the hot tub speakers, 4 and 5 control
the dining room speakers, and 6 and 7 control the portico speakers. 8 and 9 are
available in case I ever find a need to connect one more pair of speakers.
*/

#include <SPI.h>
#include <Ethernet.h>
#include <string.h>

// MAC address can be anything that is unique within the local network.
byte mac[] = {0x00, 0x1E, 0x2A, 0x77, 0x24, 0x02 };

// Some unused IP address on the local network.
byte ip[] = {192, 168, 2, 251 }; 

// web server, nothing fancy, just port 80 for http
EthernetServer server( 80 ); 

#define RELAY_ON 0
#define RELAY_OFF 1


// true, just show speaker status or false, actually change the speaker states
boolean showStatus = false;

// which zones are on or off, initially, all are off
boolean zone1 = false;
boolean zone2 = false;
boolean zone3 = false;
boolean zone4 = false;

// pin definition, one pin per speaker, 
// so the left speaker in zone 1 is pin 2, etc
static const int zone1L = 2;
static const int zone1R = 3;
static const int zone2L = 4;
static const int zone2R = 5;
static const int zone3L = 6;
static const int zone3R = 7;
static const int zone4L = 8;
static const int zone4R = 9;


// set up pins, initially all speakers in all zones are off
void setupPins() {
    digitalWrite(zone1L, RELAY_OFF);
    digitalWrite(zone1R, RELAY_OFF);
    digitalWrite(zone2L, RELAY_OFF);
    digitalWrite(zone2R, RELAY_OFF);
    digitalWrite(zone3L, RELAY_OFF);
    digitalWrite(zone3R, RELAY_OFF);
    digitalWrite(zone4L, RELAY_OFF);
    digitalWrite(zone4R, RELAY_OFF);

    pinMode( zone1L, OUTPUT );
    pinMode( zone1R, OUTPUT );
    pinMode( zone2L, OUTPUT );
    pinMode( zone2R, OUTPUT );
    pinMode( zone3L, OUTPUT );
    pinMode( zone3R, OUTPUT );
    pinMode( zone4L, OUTPUT );
    pinMode( zone4R, OUTPUT );
    
    delay(4000);
}

void setup() {
    Ethernet.begin( mac, ip );
    server.begin();

    setupPins();
}

// set up buffer for reading web requests
static const int bufferMax = 128;
int bufferSize;
char buffer[ bufferMax ];

void loop() {
    EthernetClient client = server.available();
    if ( client ) {
        waitForRequest( client );
        handleRequest();
        client.stop();
    }
}

void waitForRequest( EthernetClient client ) 
{
    bufferSize = 0;

    while ( client.connected() ) {
        if ( client.available() ) {
            char c = client.read();
            if ( c == '\n' ) {
                break;
            }
            else {
                if ( bufferSize < bufferMax ) {
                    buffer[ bufferSize++ ] = c;
                }
                else {
                    break;
                }
            }
        }
    }
}

void handleRequest() {
    // Received buffer contains a standard HTTP GET line, something like
    // "GET /?X=X&Y=Y HTTP/1.1". 
    // Could have up to 4 parameters, 1=on&2=on&3=on&4=on,
    // one for each set of speakers. All that is necessary here is to
    // extract the query string and check for each of the zone numbers.
    String request = String(buffer);
    int firstSpace = request.indexOf(" ");   // right after GET
    int lastSpace = request.indexOf(" ", firstSpace + 1); // just after the query string
    request = request.substring(firstSpace, lastSpace);
    
    showStatus = request.indexOf("?") == -1;
    zone1 = request.indexOf("1") > -1;
    zone2 = request.indexOf("2") > -1;
    zone3 = request.indexOf("3") > -1;
    zone4 = request.indexOf("4") > -1;

    if (!showStatus) {
        setSpeakerState();
    }
    sendPage();
}

void setSpeakerState() {
    digitalWrite(zone1L, zone1 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone1R, zone1 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone2L, zone2 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone2R, zone2 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone3L, zone3 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone3R, zone3 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone4L, zone4 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone4R, zone4 ? RELAY_ON : RELAY_OFF);
}

void sendPage() {
    printHead();
    printForm();
    printTail();
}

// the 'bootstrap' css makes the page look good in desktop browsers and on phones
void printHead() {
    server.print("<html>\n<head>\n<title>Speaker Control</title>\n");
    server.print("<meta name='viewport' content='width=device-width, initial-scale=1'>\n");
    server.print("<link rel='stylesheet' href='http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css'>\n");
    server.print("</head>\n<body>\n"); 
}

void printForm() {
   server.print("<div class='container'>\n");
   server.print("<h2>Speaker Control</h2><br/>\n");
   server.print("<form action='/' role='form'>\n");
   
   int pinState = digitalRead(zone4L);                                           
   server.print("<div class='checkbox'><label><input type='checkbox' name='4'");
   server.print(pinState == RELAY_ON ? " checked='checked'" : "");
   server.print(">Hot tub</label></div><br/>\n");

   pinState = digitalRead(zone3L);                                           
   server.print("<div class='checkbox'><label><input type='checkbox' name='3'");
   server.print(pinState == RELAY_ON ? " checked='checked'" : "");               
   server.print(">Dining room</label></div><br/>\n");                            
                                                                             
   pinState = digitalRead(zone2L);                                           
   server.print("<div class='checkbox'><label><input type='checkbox' name='2'");
   server.print(pinState == RELAY_ON ? " checked='checked'" : "");               
   server.print(">Portico</label></div><br/>\n");                        
                                                                             
   pinState = digitalRead(zone1L);
   server.print("<div class='checkbox'><label><input type='checkbox' name='1'");
   server.print(pinState == RELAY_ON ? " checked='checked'" : "");               
   server.print(">(Empty)</label></div><br/>\n");                            
                                                                             
   server.print("<br/>\n");
   server.print("<button type='submit' class='btn btn-default'>Save</button>\n");
   server.print("</form>\n");
   
   server.print("</div>\n");
}

void printTail() {
   server.print("</body>\n</html>\n"); 
}