Wednesday, August 15, 2012

new water bottle

About a week ago I was shopping at a local thrift store and found a good sized metal water bottle.

This was good, except for the water bottle being branded, and I prefer to not have visible brands on my stuff.

The response was completely logical for me:


I covered the bottle with strips of white hockey tape, with as little overlap as I could.

Then I painted the bottle with acrylic paint, freehand, trying my best to color each strip one color.

Finally I glossed it with some of the gloss that my sister uses to make her masks shiny, though this step was not even really necessary.

I am happy with how the water bottle looks now, and it holds a pleasing amount of water, some time in the future I will actually measure how much water that is.

Neon yellow basic hammock

I learned how to make basic cloth hammocks about two years ago, they are quite comfortable and most are easy to transport.


This is one of the recently created ones.  I got the material before I left for Eclipse, and hung it as a no-sew hammock there for casual napping.  Later on one of the stops on the way home I sewed it at a friend's place to make it hang easier, and even more recently I trimmed it down to 2.5m in length so that it would hang between my regular two hammock trees and fit under my rain tarp.

The fabric is a fairly thick raincoat nylon.  This particular one does not stretch at all so it takes me a little while to get comfortable enough to sleep.

Combined with the rain cover this hammock is good for all summer weather: wind, rain, and clear.  I have also slept out in all of these with it already.

The main thing that keeps the rain off the hammock is the metal rings that divide the rope on the tree from the rope on the hammock.

The reason I created this hammock was because one of my hammocks that I took to Evolve left to go on an adventure without me.

Sunday, August 12, 2012

Joining audiobook mp3 files together

I like to listen to audiobooks sometimes when I am walking and relaxing, and I like to listen to them on an iPod, but usually when I find them they are split up into a large number of mp3 files, and the iPod does not deal with them very well.

After getting sufficiently annoyed at the problem I decided it was time to find a way to join the files together into one, so it was easier to manage, also it would be nice to be able to reliably resume in the same place as I left off, it would keep resuming several minutes away from where I paused it.

The results of my tinkering was a small script to decode a directory of mp3 files, and then encode the resulting audio stream into a single constant bitrate mp3 file. I used a 64kbit rate since I was only dealing with speech.

#!/bin/bash
[ "$1" ] || {
  echo use: $0 directory
  exit 0
}

for file in "$1"/*; do
  ffmpeg -i "$file" -acodec pcm_s16be -f s16be -ar 44100 -ac 2 -
done |
  lame -r -x -b 64 --cbr -s 44.1 --bitwidth 16 -m j - "$1".mp3
The script takes a directory as a parameter, and outputs an mp3 file by the same name. Remember to leave the trailing slash off the directory name, unless you want to get a hidden mp3 file in that directory as a result.

Tuesday, February 21, 2012

Swing Slider Example

I wrote a Slider 'Hello World' program to make sure I understand how to use them to control another value in the user interface.

Here is that self contained simple example.

package ca.sarah_happy.sandbox.circles;

import java.awt.BorderLayout;
import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SliderSample implements Runnable {
    public static void main(String[] args) {
        /*
         * do all the work on the GUI thread.
         */
        SwingUtilities.invokeLater(new SliderSample());
    }

    /*
     * things I will need access to later.
     */

    private JSlider slider;
    private JLabel label;

    /*
     * do the work of creating the user interface.
     */

    @Override
    public void run() {
        slider = new JSlider();
        slider.setPaintTicks(true);
        slider.setPaintLabels(true);
        slider.setMaximum(127);
        slider.setMinimum(-128);
        slider.setMajorTickSpacing(32);
        slider.setMinorTickSpacing(8);
        slider.setValue(0);

        label = new JLabel("value = " + slider.getValue());

        JFrame frame = new JFrame("Slider Sample");
        frame.setLocationByPlatform(true);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        Container p = frame.getContentPane();
        p.add(label, BorderLayout.SOUTH);
        p.add(slider);

        slider.addChangeListener(sliderChangeListener);

        frame.pack();
        frame.setVisible(true);
    }

    /*
     * and things that will be triggered later
     */

    private ChangeListener sliderChangeListener = new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            String adjust = "";
            if (slider.getValueIsAdjusting()) {
                adjust = " (adjusting)";
            }
            label.setText("value = " + slider.getValue() + adjust);
        }
    };
}

Saturday, February 11, 2012

tracking mouse events example

I expect to need a program to inspect mouse events soon. I intend to find out how mouse events are delivered on a touch screen, when I have access to such a device. In the mean time I put together a program to display the mouse events that are visible to a java application.

package org.yi.happy.mouse;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

/**
 * Track mouse events over a panel and log in a text area.
 */
public class MouseTrackMain implements Runnable {
    private final JTextArea textArea;
    {
        textArea = new JTextArea(10, 80);
        textArea.setEditable(false);
    }

    private void log(String event) {
        textArea.append(event + "\n");
    }

    private void log(String event, MouseEvent e) {
        log(event + ": " + e);
    }

    private MouseListener mouse = new MouseListener() {
        @Override
        public void mouseClicked(MouseEvent e) {
            log("click", e);
        }

        @Override
        public void mousePressed(MouseEvent e) {
            log("pressed", e);
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            log("released", e);
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            log("entered", e);
        }

        @Override
        public void mouseExited(MouseEvent e) {
            log("exited", e);
        }
    };

    private MouseMotionListener mouseMotion = new MouseMotionListener() {
        @Override
        public void mouseMoved(MouseEvent e) {
            log("moved", e);
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            log("dragged", e);
        }
    };

    @Override
    public void run() {
        JPanel blankPanel = new JPanel();
        blankPanel.setPreferredSize(new Dimension(400, 300));
        blankPanel.setBackground(new Color(0x7f, 0x7f, 0xff));

        JScrollPane scroll = new JScrollPane(textArea);

        JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        split.add(blankPanel);
        split.add(scroll);

        JFrame window = new JFrame("Mouse Track");
        Container panel = window.getContentPane();
        panel.setLayout(new BorderLayout());
        panel.add(split);

        blankPanel.addMouseListener(mouse);
        blankPanel.addMouseMotionListener(mouseMotion);

        window.pack();
        window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        window.setLocationByPlatform(true);
        window.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MouseTrackMain());
    }
}

This program is laid out so that there are no forward references.

Tuesday, December 27, 2011

Recover text messages from nandroid backup

The objective is to restore the text messages that were on my Android phone before it got re-flashed, with an end result of all the old and current text messages being on the phone.

I have a nandroid backup image at ~/work/backup/, and the phone attached by USB with debugging enabled.

Previously I tried to install the yaffs file system on a Linux box and mount the image over loop back, however that did not work, the images failed to mount.

The solution turns out to be simple...

download the source for unyaffs, a program which extracts all the files form a yaffs image.

download unyaffs.c and unyaffs.h into ~/work/.

compile the source.
cd ~/work
gcc -o unyaffs unyaffs.c

make a target directory and run the program from the target directory.
mkdir data.img
cd data.img
../unyaffs ~/work/backup/data.img

after some quick reading I find that the text message database are at data/com.android.providers.telephony/databases/mmssms.db.

On the phone use SMS Backup & Restore to save the current text messages.

Make a backup of the message database on the phone, just in case.
adb pull /data/data/com.android.providers.telephony/databases/mmssms.db ~/work/mmssms.db-current

Push the pre-flash message database with the old messages onto the phone
adb push ~/work/data.img/data/com.android.providers.telephony/databases/mmssms.db /data/data/com.android.providers.telephony/databases/mmssms.db

Reboot the phone.

Only the old messages should be visible on the phone now.

On the phone use SMS Backup & Restore to restore the text messages that were just saved, there should be no need to check for duplicate messages.

All the messages should be visible now. All done.

Saturday, December 24, 2011

Minimal Swing GUI example

A well behaved graphical application will place windows like other applications on the platform place them, and will exit when the last window is closed, and also all GUI work will happen on the event thread, this example does all of that.

package org.yi.happy.teaching.gui;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class SwingLaunch {
    public static void main(String[] args) {

        /* ALL GUI work should be done on the event thread */
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {

                /* make a window */
                JFrame frame = new JFrame(SwingLaunch.class.getName());
                frame.pack();

                /*
                 * when all the windows are disposed the application will exit,
                 * make the window automatically dispose when it is closed
                 */
                frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

                /* put the window where the platform would put it */
                frame.setLocationByPlatform(true);

                /* show the window on the screen */
                frame.setVisible(true);
            }
        });
    }
}

For Day Job I have also written a GUI Launcher class that takes a swing component or a class and launches a window containing it with these settings.