Glimmer

Faint insights into (mostly) the world of automation

Finding Reminders in Evernote

| Comments

Here is a hint that I was not able to find quickly in Google nor in the EverNote help.

Enter “Reminders” into the Search Bar and then select “Notes with Reminders” to find all notes that have reminders. Very logical but took a few minutes and hopefully this short post will same someone else a few.

NetBeans Template Configurer

| Comments

Many years ago, I wrote a post about how to use the NetBeans template system for my students. It quickly covered the basics and demonstrated how to set things up for the course’s documentation standard.

In Fall 2017, one of the UAB EE333 Project teams built a clever tool to do this initialization for the student. This makes it much easier for the new student to set up the automation at the beginning before they have any real experience with NetBeans. The tool solicits the data needed (student name, email, course) and installs the templates.

It has been tested on both Windows 10 and Mac OS 10.12 with NetBeans 8.2 and attempts to work with earlier and later versions of things but that is mostly outside the testing space. The team consisting of

  • Dylan Dalton
  • Schauber Gbalou
  • Matthew Manuel
  • Joey Richardson
  • Darrin Wang

have agreed to having the source code of their tool on GitHub under a MIT license. UAB students should be able to find a compiled version of the code in the form of a templates.jar file in their course Learning Management System.

The students cleverly put the basic templates (modified versions of the ones in NetBeans) in the jar file as resources allowing one to modify the templates as desired but only have to distribute a jar file to new students. We placed the code into Github.

Java Sound Update 2

| Comments

This is an update to a prior article.

UAB EE Students Andrew Peturis, Chaselyn Langley and other team members produced an interesting GUI Application for children to associate sounds with images. In the course of doing this, they wished to expand the control of the audio beyond my original example. They discovered a bit of behavior that was not (at least clearly) documented in the JAVA API.

They modified the original demo substantially for their application and supplied a limited version of it to me as an update to benefit future classes (as well as the broader Internete Community). I merged their two classes into one focused only on the sound system behaviour and hopefully preserved the important behaviors they wished to document. The new code is show below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 * File: Sound.java
 * Authors: Andrew Peturis, Chaselyn Langley, David Green
 * Vers: 1.1.0 12/10/2015 dgg - update example to standalone
 * Vers: 1.0.0 10/20/2015 agp - initial coding
 *
 * Credits:  Team SoundBox - EE333 Fall 2015
 */

import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Sound {

    private String sound;
    private Clip clip;
    private boolean isPlaying;  // Sound loaded up and has started playing (may be paused)


    // Don't allow default constructor
    private Sound() {
    }

    public Sound(String sound) {
        this.sound = sound;
        isPlaying = false;
    }

    // Play a sound using javax.sound and Clip interface
    public void play() {
        try {
            if (!isPlaying) {
                // Create a clip to hold a sound
                clip = AudioSystem.getClip();
                clip.open(AudioSystem.getAudioInputStream(new File(sound)));
                isPlaying = true;
            }
            // Play the audio clip with the audioplayer class
            clip.start();
        } catch (LineUnavailableException | UnsupportedAudioFileException | IOException e ) {
            System.out.println("Things did not go well");
            System.exit(-1);
        }
    }

    // Continue a stopped sound
    public void resume() {
        if (isPlaying) {
            clip.start();
        }
    }

    // Pause a playing sound
    public void pause() {
        // clip.stop() will only pause the sound and still leave the sound in the line
        // waiting to be continued. It does not actually clear the line so a new action could be performed.
        if (isPlaying) {
            clip.stop();
        }
    }

    // Stop a sound from playing and clear out the line to play another sound if need be.
    public void end() {
        if (isPlaying) {
            pause();
            // clip.close(); will clear out the line and allow a new sound to play. clip.flush() was not 
            // used because it can only flush out a line of data already performed.
            clip.close();
            isPlaying = false;
        }
    }

    // Small demo program
    public static void main(String[] args) {
        Sound sound = new Sound("predator.wav");
        try {
            sound.play();
            System.out.println("Playing for 1 second");
            Thread.sleep(1000);     // let it play a second
            sound.pause();          // pause
            System.out.println("Pausing for 5 seconds");
            Thread.sleep(5000);     // continue playing
            System.out.println("Playing for 1 second");
            sound.resume();
            Thread.sleep(1000);      // play have a second
            System.out.println("Ending, resuming which should silently fail");
            sound.end();            // End sound
            sound.resume();         // Should be silent
            Thread.sleep(5000);     // Wait 5 seconds
            System.out.println("Playing again for 5 seconds");
            sound.play();           // Should start again
            Thread.sleep(5000);
            sound.end();
        } catch( InterruptedException e) {
            // just fall to end
            // System.exit(0);
        }
    }
}

Creating a Line Segment Graphic

| Comments

The following code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
 * File: CreateSimplePlot.java
 * Author: David Green <dgreen@uab.edu>
 * Vers: 1.1.0 09/21/2015 dgg - change from Etch-A-Sketch to Plotter
 * Vers: 1.0.0 09/10/2014 dgg - initial coding
 *
 * Credits:  (if any for sections of code)
 */

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

/**
 * Code from:  http://www.java2s.com/Code/Java/2D-Graphics-GUI/DrawanImageandsavetopng.htm
 * (modifications by ...)
 * @author David Green <dgreen@uab.edu>
 */
public class CreateSimplePlot {

  static public void main(String args[]) throws Exception {

    double t;       // time
    double oldT;    // old time
    double deltaT;  // time increment
    double y;       // plot value
    double oldY;    // old plot value

    try {
      int width = 700, height = 500;

      // TYPE_INT_ARGB specifies the image format: 8-bit RGBA packed
      // into integer pixels
      BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

      Graphics2D ig2 = bi.createGraphics();

      // make full image white
      ig2.fillRect(0, 0, 700, 500);

      // draw black lines
      ig2.setPaint(Color.BLACK);

      oldT = 0.;
      oldY = plotFunction(oldT);
      deltaT = 5.;


      for (t = deltaT; t < 700.; t += deltaT ) {
        y = 250.0 + 200.0 * Math.sin( (t / 200.) * 2. * Math.PI );
        ig2.drawLine((int) oldT, (int) oldY, (int) t, (int) y);
        oldY = y;
        oldT = t;
      }

      // write the resulting file
      ImageIO.write(bi, "PNG", new File("plot.png"));

    } catch (IOException ie) {
      System.out.println("Exception raised " + ie);
    }
  }

  private static double plotFunction(double t) {
    return 250.0 + 200.0 * Math.sin( (t / 200.) * 2. * Math.PI );
  }
}

produces

Figure 1. Sinusoid example plot

as a PNG graphic file.

Software Programming Skills Popularity

| Comments

There are lots of ways to evaluate popularity, and in the end, all are probably very transitory. In his Quartz article, Max Nisen examined American job data and reports the top ten slanguage/frameworks (by salary offers) are

  1. Ruby on Rails
  2. Objective C
  3. Python
  4. Java
  5. C++
  6. JavaScript
  7. C
  8. R
  9. C#
  10. Visual Basic

Java Sound Update

| Comments

For years, I have been using (and advising the use of sun.audio) for playing sounds in the Java VM using Alvin Alexander’s article for inspiration. The downside of this approach, of course, is the dependency on classes that are not part of the JAVA API and therefore might change at anytime although they have been relatively stable for many years.

Recently, I found a stackoverflow discussion noting the existence of AudioSystem (and related clases).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
 * File: ModernRingPhone.java
 * Author: David Green <dgreen@uab.edu>
 * Assignment:  SoundOff - EE333 Fall 2014
 * Vers: 1.0.0 10/23/2014 dgg - initial coding
 *
 * Credits:  Concepts from http://stackoverflow.com/questions/15475276/short-sound-file-plays-in-netbeans-but-not-in-jar
 */

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;

/**
 *
 * @author David Green <dgreen@uab.edu>
 */
public class ModernRingPhone {

  public static void main(String[] args)
  {
    try {
        // open the sound file as a Java input stream
        String gongFile = "telephone-ring-3.wav";

        // create an audiostream from the inputstream
        Clip clip = AudioSystem.getClip();
        clip.open(AudioSystem.getAudioInputStream(new File(gongFile)));

        // play the audio clip with the audioplayer class
        clip.start();

        // wait for sound to finish before terminating program (necessary for 
        // running inside NetBeans, at least)
        Thread.sleep(10000);
    }
    catch ( Exception e) {
        System.out.println("Things did not go well" );
        e.printStackTrace();
        System.exit(-1);
    }
  }
}

Update: 2015-02-08 Removed unnecessary line of code

Update: 2015-12-10 Revised example is available here.

Updating Java/NetBeans on OS X

| Comments

Oracle Java on OS X

After moving to Oracle’s Java to use on OS X, one finds a new System Preference pane which launches a Java preferences App. Included here is a preset option to update Java. However, one should note that if one installed the JDK (Java Development Kit) as opposed to the JRE (Java Run Time environment) only the JRE portion of the package is automatically updated. It appears one has to manually download and update the JDK to get that portion of the package updated. Investigating a bit, it looks like the attention is on the JRE and only the linkages for the Applet usage are updated automatically. The JDK and its command line version of java are not updated in addition to all the other components of the JDK. This is probably not all bad as it means the development environment does not change on you without notice.

NetBeans on OS X

To update NetBeans, download a later version, start the new version and agree to migration from the earlier release. Then, when you are ready to eliminate the old version of NetBeans, go to the /Applications/NetBeans directory and delete only that old version.

Update: 25 Jan 2014 — The template directory is made when the first template is created. On the Mac, it is located at ~/Library/Application\ Support/NetBeans/7.4/config/Templates and has a Classes directory and a Properties directory. It appears that one can move the templates from one config directory to a new one as part of migrating.

Using MySQL With Bitnami on Vagrant VM

| Comments

The Bitnami install doccumented earlier is a bit broken relative to MySQL. Evidently, when Bitnami installs in the VM situation and moves itself to the /opt/rubystack... directory, it expects to be a slightly more traditional install and use the userid mysql for running the MySQL server. However, the built databases are secured to the vagrant user account (at least in my release). This is relatively easy to confirm, try starting the server

 sudo ~/rubystack/ctlscript.sh start mysql

and not that it fails (after a bit). One can look at the mysqld.log in ~/rubystack/mysql/data directory and see access errors.

The fix is to give the mysql user access to the MySQL data directory:

cd ~/rubystack/mysql  
sudo chown -R mysql.vagrant data

After this is done, the startup command should work.

To start MySQL

cd rubystack  
sudo ./ctlscript.sh start mysql

To stop MySQL

cd rubystack  
sudo ./ctlscript.sh stop mysql

Create MySQL databases for dev, test, production

The following sequence setups the development, test, and production databases for the Rails project tbd4students.

tbd4students> mysql -u root
CREATE DATABASE tbd4students_development DEFAULT CHARACTER SET utf8;
GRANT ALL PRIVILEGES ON tbd4students_development.* TO 'vagrant'@'localhost' IDENTIFIED BY 'password';
CREATE DATABASE tbd4students_test DEFAULT CHARACTER SET utf8;
GRANT ALL PRIVILEGES ON tbd4students_test.* TO 'vagrant'@'localhost' IDENTIFIED BY 'password';
CREATE DATABASE tbd4students_production DEFAULT CHARACTER SET utf8;
GRANT ALL PRIVILEGES ON tbd4students_production.* TO 'vagrant'@'localhost' IDENTIFIED BY 'password';
EXIT;

In this example, the username vagrant (default in the VM) with a password of ‘password’ is used to access the server. There is also a presumption that the root password to the MySQL server is blank. This configuration, of course, is NO security and is only useful when on a closed system. One should research how to configure things more securely for anything that will be Internet (or even LAN) visible.

Make a New Rails 3.2 App in the VM Environment

| Comments

After installing the VM on the computer, one can make a new Rails App by the following process:

  • Go to the machine directory in your host machine using the command line
  • Start up the VM if it is not running vagrant up
  • Connect to the machine vagrant ssh
  • First time only, tell git who you are

       git config --global user.email "you@example.com"
       git config --global user.name "Your Name"
    
  • Change to the directory that is shared between the guest OS and the host OS cd /vagrant

  • Create a new Rails application without running bundler rails new appname --skip-bundle
  • Install git’s tracking repository git init appname
  • Change to the application directory cd appname
  • Update .gitignore to skip tracking database.yml You can edit this on the host side rather than the OS side if you like your local editor better but use one that likes Unix line endings (i.e. NOT Notepad).
.gitignore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# See http://help.github.com/ignore-files/ for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
#   git config --global core.excludesfile ~/.gitignore_global

# Ignore bundler config
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3

# Ignore all logfiles and tempfiles.
/log/*.log
/tmp

# Ignore database.yml
/config/database.yml
  • Move the code to check in to the staging area git add .
  • Commit the code the repository git commit -m "Initial commit after ignoring database.yml"
  • Make a copy of database.yml for archival cp config/database.yml config/database-example.yml
  • Modify the Gemfile to include thin, theracer, and quiet_assets gems.
Gemfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
source 'https://rubygems.org'

gem 'rails', '3.2.13'

# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'

gem 'sqlite3'
gem 'thin'
gem 'quiet_assets', :group => :development


# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'

  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
  gem 'therubyracer', :platforms => :ruby

  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'

# To use Jbuilder templates for JSON
# gem 'jbuilder'

# Use unicorn as the app server
# gem 'unicorn'

# Deploy with Capistrano
# gem 'capistrano'

# To use debugger
# gem 'debugger'


  • Run bundle to lock in the gemfiles using the local version of the gems bundle install --local
  • Start up the Rails app rails s
  • On the host side, point the browser to http://192.168.33.10:3000 and ensure that the base Rails “Welcome aboard” is visible.

Updated 7 June 2013 after presentation to class — correcting two typos.