Wednesday, July 11, 2012

Java's Annotation Processing API

Okay, I haven't posted in a long time, but I just want a quick note to say, Java's Annotation Processing API is absolutely amazing.

It takes a little while to get used to using mirrors rather than reflection, but once things fall into place, you can do amazing amounts of metaprogramming with it.

I had a project which was processing properties found in data-model classes (classes which map directly to tables in a database), and we were processing these properties via certain annotations.

Unfortunately, I didn't take into account the need to annotate methods in the model classes as well, and that requirement came in very shortly after I released the processor.

Within 10 minutes I was able to swap out the processing upon a VariableElement to simply an Element class, and not have to introduce any new code to adjust for processing a method versus a property.

Okay, I had one minor adjustment.  VariableElement has an "asType()" method which returns the TypeMirror for the static type of a property.  ExecutableElement (a method) has a "getReturnType()" method which returns the TypeMirror for the method.  I had to do a little bit of processing on the types to make sure I get their return types properly extracted.

Other than that, however, it was nice and clean.

Monday, April 4, 2011

Flex 360

Will be attending the conference this year down in Denver -- we convinced my employer to send two of us from the team. Should have some very interesting topics.

Sunday, March 20, 2011

OSX, Login Screens, and Battery Information

I know it's probably weird, but I really don't like it when I boot up my Macbook and don't know if I should plug it in or not.  Sometimes, if it's very low on battery power, I'll just turn it back off again and get on my PC (I do a lot of coding from the couch :).

So, I asked myself, why not try and find a way to dynamically update my login screen with battery information?  There are a number of posts for updating the login text.  I took this basic idea and combined it with a Python script I wrote for parsing out the battery status.

Some of the content in the battery script was taken from a recent post on Lifehacker, showing how you can build a script which will vocally alert you when your battery status is getting critical.

Anyway, the first step was to build a script (I prefer Python) which will gather battery stats from ioreg and parse it for the current battery capacity, maximum battery capacity, and external charge capability.  The last option (yes/no) lets us know if the laptop is plugged into the wall.

Here's the script I came up with

#!/usr/bin/python
import subprocess
import os, sys

BATTERY_CMD = ["/usr/sbin/ioreg", "-l"]
GREP_CMD    = ["/usr/bin/egrep", "Capacity|ExternalChargeCapable"]

def main(argv):
    content      = getBatteryStatus()
    print(content)

    return 0

def getBatteryStatus():
    process = subprocess.Popen(BATTERY_CMD, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    grep    = subprocess.Popen(GREP_CMD, stdin=process.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    grep.wait()
    output  = grep.communicate()[0]
    batteryStatus = output.split("\n")
    if len(batteryStatus) < 3:
        print(batteryStatus)
        return "Could not get battery status"
   
    if "Yes" in batteryStatus[0]:
        return "Laptop is plugged into the wall"
    else:
        maxCapacity = float(batteryStatus[1].split("=")[1].lstrip())
        curCapacity = float(batteryStatus[2].split("=")[1].lstrip())
        remaining   = 100 * (curCapacity / maxCapacity)
        return "Battery Remaining: %.02f%s" % (remaining, "%")

if __name__ == "__main__":
    sys.exit(main(sys.argv))


 This script basically runs the following command: ioreg -l | egrep Capacity|ExternalChargeCapable.  This bundles the content into a large string, delimited by "\n" characters.  Parsing this is a simple value of extracting everything after the "=" sign.

Anyway, this script prints either the percentage or the status of the wall plug.

The second part of this exercise was to create a StartupItem for my Macbook.  This was actually very easy (as the upper link shows).  Create a new directory in "/Library/StartupItems" called logintext.  Inside this directory, you'll need to copy the above script, and add 2 new scripts:

Call the first one, StartupParameters.plist, and add the following content:

{
Description = "Sets LoginwindowText";
Provides = ("logintext");
}


This script informs the startup process of which script to execute when starting up. This guarantees all initializations of the Macbook will have up-to-date knowledge of the battery life.

The last script is called "logintext". In this script, put the following content:

#!/bin/sh
batteryText=`/Library/StartupItems/logintext/batteryScript.py`
defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$batteryText"


This script executes the Python script and sets the loginwindow's preference (LoginwindowText) to the output from the script.

Log in as root (sudo su -) and add a new cronjob to execute this script every 2 minutes:

*/2 * * * * /Library/StartupItems/logintext/logintext


And it should keep your system relatively up-to-date!

Monday, January 3, 2011

Pianobar, iTunes, and GeekTool

For those of you who haven't seen Pianobar, it's a great little terminal-based player for Pandora.  It was featured on Lifehacker as a Flash-free player for Mac and Linux (and Cygwin-based Windows installations).

Of course, being the fan of Conky that I am, my first thoughts were to find a way to parse out the content from Pianobar and display them on the desktop.  This, it turns out, was a bit harder than it seemed.  The content streaming into the terminal is littered with extra characters, which are great when viewing from the console.  These characters, however, need to be extracted from the content so the raw data is accessible.  Moreover, Pianobar has a nice feature which prints the time remaining for the currently playing song.  This information is printed to the console using the '\r' character so the time overwrites itself.  When diverted to a file, this results in excessively long lines which need to be parsed.

With this in mind, I started my latest project was to extract this information and print it so tools like Conky and GeekTool could print them to the desktop while they are running.  The result, though a bit hacky, was fairly nice.

Once this was finished, however, another idea struck me: what if I'm playing iTunes rather than Pianobar?  I'd still like to display this content on the desktop.  What's more, I'd like to use the same program to do both.

So, my next project was to extend this script so it could handle multiple musical inputs.

I've posted the results to SourceForge.  Let me know what you think!

Saturday, August 14, 2010

Gnome-Shell: First Impressions

So I installed the latest bits of Gnome-shell on my desktop -- yeah, I tend to just plunge right in w/nary a thought to my system's stability, don't I??

Anyway, here are my immediate thoughts, after about an hour of playing with/using it:

Look and Feel
The overall feel is pretty slick: my CPU is handling transitions pretty well, though I think my graphics card fan has been running non-stop.  That's kinda to be expected, except that Enlightenment has been doing these transitions w/out acceleration for years...that's a bit strange.  Why the desktop people don't get together and compare notes, I can't for the life of me figure out.  If Gnome-Shell could do what it does and not need a souped-up graphics card, Linux would have an even better appeal.

That said, the effects are nice.  Compiz is gone, so no wobbly windows, but what's there is decent.  When you push your mouse to the upper-left, you get the Activities view; same as clicking the Activities icon.  The zoom is really nice.  Swapping between desktops is bloody fast from the Activities view, and the zooms are very smooth.  The effects when you drag windows to/from different desktops are also quite nice.  They self-arrange in the desktop, so moving applications around is kinda fun.  After a while, you'll probably stop noticing though.  Adding/removing desktops is also quite nice: they slide up or down.  It seems like they are more focused on utility: effects are there to aid you in understanding what's happening, not necessarily for entertainment.  Being the somewhat racoonish person that I am, however, I like shiny things.  They could definitely use more effects and animations, but this is still good.

Application Switching
The application switcher is pretty darn cool.  It's a bit like Gnome's switcher, but with 2 new features (that I can see):

1. Apps running on the current desktop are visually separated from the other apps running.  There's a divider between them, so you know where apps are (generally speaking -- you know they are either "here" or "_somewhere_ else").
2. Those apps with multiple instances have a down-arrow, which you can either hover over w/the mouse, or navigate to using Ctrl+~.  It will then drop down and allow you (using the mouse or Ctrl+~) to select one of the instances.  Instances are displayed in a nice sub-switcher, so point #1 (separator) is also displayed.  The key-combo is awkward though:
  Hit Ctrl+Tab, holding Ctrl, press Tab until you highlight the application you want
  Holding Ctrl, press ~ to drop into the instance-switcher; holding Ctrl, press ~ to swap between instances
  Holding Ctrl, press Tab to get back to the main switcher

It's not terrible -- I could get used to it, but it will take a little while, and it could be better.  Also, you cannot use Ctrl+~ on an application to switch instances...that would be a nice feature too.

Panels and Menu Bars
This area is the one I dread the most: I don't care for Apple's "whatever you are currently working on is the most important thing in the whole wide world and we would never want to distract you from anything else because we know how small your brain is that it can't handle more than one thing and by the way we'll also tell you what software to purchase and what's safe to have on your computer because Apple knows best and we love you and will always take care of you as long as you pay us and sign away your life and freedoms for the good of our company and our great leader"...ok, I'm getting off track.

Anyway, it _looks_ like the main menu is completely gone.  That's right, gone.  In the uper panel, on the left-hand side, there are two text areas: "Activities" (immutable, I think), and "Whatever you are working on right now".  There is a date in the middle (w/calendar dropdown), and the user-login on the right (social-networking integrated, of course, but also w/other options, some of which I haven't played w/yet).  The text describing the active window doesn't have a menu; as such, it is not at all what Apple does in OSX.  In fact, it doesn't do ANYTHING.  This is, of course, not very useful, because frankly, you already KNOW what you're looking at.  I'm not sure if they're leaving this open for applications to supply their own menus, but even GEdit didn't do anything with it.  I'll need to do some investigation to see what they're thinking.

You can't right-click on the upper panel, so the previous set of widget-style controls (e.g. system-monitor, network-monitor, app-launchers) is not available.  I'm not sure if that will be dealt with in the future, or if they'll allow you to add a secondary panel w/them.  I hope so -- I really like the quick-access icons.

 The lower bar is gone -- no idea where it went.  Which also means the task manager (e.g. your list of open windows) is also gone.  So...when you're on a virtual desktop, you don't have an immediate way of knowing what's currently running in the space.  The application switcher gives you a clue, but really, you need to go to the Activities view to see.  This is probably the biggest shortcoming: I want to know what I have running at a glance, not with a few keystrokes or sliding my mouse up to a certain view which lays everything out.

Activities View

Ok, this is pretty cool.  Slide the mouse up and to the left, and you'll have a new set of menus and options, along with a "Spaces"-style view of the desktops.  You can easily add/remove desktops and move applications from one to the other.  Every app has a nice 'x' next to it so you can kill them from this view; if the killed app needs to save state, it will zoom you into the desktop so you can confirm the prompt.  Not bad -- a nice set of usability tweaks around a virtual desktop manager.

There are several options in the Activities view:
* Find: doesn't really work -- most of what I search for can't be found and I get a ton of errors on the command-line (since I started Gnome-shell from it)
* Applications: has the applications which can be found in the Applications menu in Gnome 2.  Large icons, decent looking -- since Find is broken not very useful if you don't want to scroll alphabetically just to open Zim (which I DO use, BTW)  Oh yeah, underneath is a bunch of app icons (either recently or currently used, I think) -- useful for commonly accessed apps, but...meh.

* Places: standard folders for Gnome...nothing to see here.  Click on one and it will open (with a nice zoom in effect) in the first desktop and put you in that desktop

* Recent Documents: heck, I don't care about this feature, period.

* Tons of empty space from here on out  -- this would be the perfect spot for a slideshow, or scrolling text, or a Doom minigame...heck, SOMETHING

Note: AFAIK, there is no way to get the system administration/preferences/tools from the Activities view.  You can get to them by clicking on the menu in the rightmost corner on the panel, and selecting "System Preferences".  This gives you a nice Control Center, which has the system administration tools grouped together in categories.  I like this view, though I would prefer to get to it from the Activities view.  My guess is they're really striving for a logical split: daily work vs. administrative tasks (which are less regular).  I'm not convinced of the split, but I can overlook it and adapt.  I like Control Center style dialogs: they help me logically group things together, whilst still seeing the other tools in their appropriate context, so this is a nice change.

Performance and System Load
Well, my CPU and RAM haven't dipped one bit.  I'm running Flash, Firefox, Eclipse, and Thunderbird, and I'm having no lag from Gnome-Shell itself.  This is pretty impressive; this is a standard load for Friday nights and it TANKED KDE 4.4.  4.5 might have some performance boosts, so I'll install that when I get a chance, but...I'm pretty impressed.  Even with compositing (which I think is taxing my card a bit), my CPU hasn't spiked in heat or load, so I'm pretty content with the overall impact.  Out of 2G, I have ~1G available for other apps, and plenty of CPU to spare.

Other Thoughts
It was easy to install and launch...whoopie...

Oh yeah, Launchy barely works.  I can open it, but I can't see what I'm typing.  It will still launch the applications, but...if I make a typo, I don't know what it will do since I can't see what it thinks I'm trying to type.
General Impression
Seeing as how it's 1AM, I'll wrap this up.  Overall, not bad.  Nothing terribly great, but not bad.  The system performance is impressive, and the effects are minimal and nice.  They certainly don't get in the way (unlike compiz which, at times, can make window management hard), but they also don't offer fun eye-candy for no reason whatsoever.  I like the utility of the effects because they do, somewhat, visually aid in understanding what's happening.  When the Find-functionality is fixed, it will be a nice feature, esp. if they allow you to type in a custom command from your path (something Gnome-do and KDE's app launcher allows).  They need to decide on what the main panel is for.  If they've already decided, they need to think again because it makes NO sense to simply tell me what I'm looking at when I already know what I'm looking at simply because I'm looking at it...heck, for this to be useful, I would have to stop looking at what I'm looking at to look at the panel to tell me what I'm looking at...auuughhh!!! it's maaaadnessssss!!!!!

And I'd like a way to tell what's running on the current desktop at a glance...I can get accustomed to using Ctrl+Tab, but I don't see that going over very well.

Out of 10, I'd give it a 7.5.  I can use it, but I don't want to...yet.

Wednesday, April 7, 2010

Flex, Memory Management, and Event Listeners

ActionScript (the language used in the Flex framework) is a language in which GC is handled for you.  It's a great convenience, and makes coding quite a bit easier.  As with any automatic GC language, you have to keep track of your references and make sure they are cleaned up, but it's not terribly hard to do.

And yet, there's one subtle memory leak which can really bite you in the butt: event listeners.

When you add an Event Listener to a component, its default state (unless changed) will be as a "strong" reference.  This means the listener will not be cleaned up when the Garbage Collector runs.  As a result, any references the listener might have might not be cleaned up; this can wreak havoc on your code when components are rapidly added/removed.  The number of objects persisting in memory which can't be harvested may in turn cause further spikes as the Flash Player needs more room to work with.

Adobe's Flex 3 documentation describes Event Listeners and weak references as thus:

useWeakReference:Boolean (default = false) — Determines whether the reference to the listener is strong or weak. A strong reference (the default) prevents your listener from being garbage-collected. A weak reference does not

There are two ways of mitigating this.  If you chose to create Event Listeners as thus:

button.addEventListener(MouseEvent.CLICK, doSomething);

You should create a deconstructor which removes the listeners prior to tearing down the component:

button.removeEventListener(MouseEvent.CLICK, doSomething);

The other option is to create the listener and force it to use weak references:

button.addEventListener(MouseEvent.CLICK, doSomething, false, 0, true);

Thus, when the component is GC'd, the listener will be also.

Saturday, April 3, 2010

Spaced Repetition vs. Pseudo-randomness

Instead of putting a long comment to my last post, I'll update it here :)
My original algorithm for working through flashcards was based on a pseudo-random algorithm.  Frankly, it wasn't very good (though it did exactly what I wanted, which is probably good) :D

Imagine you have a set of flashcards.  The set is a random distribution of cards you
  1. have completely memorized
  2. know very well
  3. don't know very well
  4. don't know at all
So, you separate out your cards into 4 piles, each mapping to your level of knowledge, ordered from least to greatest knowledge.  According to Leitner's algorithm, every time you guess a card correctly, it moves one pile forward.  Every time you guess a card incorrectly, it moves one pile backward.  This means the cards at the back are of more immediate import than those at the front.

Now, how do you determine how often to take a card from each pile?  Do you just start with the last pile and move up?  Do you start with the first pile and move down?

My original implementation provided a pseudo-random distribution in which you were more likely to get cards from the lowest pile than the highest.  There were gradations of probability in the piles between.

For example: the odds of picking a card from pile 1 might be 60%, 20% from pile 2, 12% from pile 3, and 8% from pile 4.  As piles became exhausted, the probability would adjust, making the next lowest pile the most likely, say 70%, 20%, 10%.

It worked pretty well, but failed to take into account one of the fundamental aspects of learning: time.

In a single session, this system isn't a bad one.  It forces you to focus on the cards you know, while periodically making you go back over those you are starting to learn.  But, if you think of memorization as a function of capacity to know something in conjunction with its degradation over time, this system is really kinda worthless :)

Spaced Repetition is a system which compliments flashcards pretty well.  There are a number of apps which utilize it.  The theory is this: those cards in the first pile should be displayed more frequently than the others.  Note: there is no randomness to picking a card.  Instead of focusing on a given session, spaced repetition presents cards on fixed intervals, which increase as the user begins to learn the card.  Thus, a session lasts as long as the system is still presenting cards at intervals.  A single learning "session" could, in theory, be considered a lifetime.

For example: a card you are learning for the first time might be presented to you once an hour.  As you start to guess the card more correctly more often, it is presented less often, but still regularly (say, once a day).  This proceeds until you are only reviewing the card at large intervals (perhaps twice a year) -- just enough to keep it retained in memory.

It's a pretty decent system, and I really like the idea.  It will make me work with schedulers in Windows, Mac, and Linux (if I ever get the lousy GUI finished).

I'd like to work this app out so that it can do several things:
  • Utilize Leitner so the concept of advancement, degradation are in place
  • Allow users to swap in/out various algorithms for dictating the cards:
    • Spaced Repetation
    • Pseudo-random (for single-sessions)
    • ...
  • Allow users to swap in/out their own flashcards easily.
The last bullet point merits a lot of thought.  Should a user simply provide a comma-separated file w/questions and answers?  What about pictures?  How would you capture that?  Should everything be imported into a database for me to pull from?

Many thoughts :)  The framework, however, PureMVC is working beautifully in Python, which is exciting.  I'm a big fan of it, and I like to see it implemented well in a given language.