Hacking by Walkingice


Configure shortcuts for Rhythmbox in Awesome WM

Well, I switched to use Awesome as my window manager several days ago. (goodbye gnome shell)

I used rhythmbox to play music, so this is my shortcuts.

awful.key( { "Shift", "Alt" }, "c", function ()
    awful.util.spawn("rhythmbox-client --no-start --play-pause", false) end),
awful.key( { "Shift", "Alt" }, "n", function ()
    awful.util.spawn("rhythmbox-client --no-start --next", false) end),
awful.key( { "Shift", "Alt" }, "p", function ()
    awful.util.spawn("rhythmbox-client --no-start --previous", false) end),
awful.key({ "Alt" }, "F12", function ()
    awful.util.spawn("rhythmbox-client --no-start --volume-up", false) end),
awful.key({ "Alt" }, "F11", function ()
    awful.util.spawn("rhythmbox-client --no-start --volume-down", false) end),

If you get the error message, do not forget to enable MPRIS D-bus Interface plug-in in Rythmbox settings.

(rhythmbox-client:15057): Rhythmbox-WARNING **: MPRIS D-Bus interface not available, some things won't work


Trac cannot log in

Yesterday I upgrade my trac-accountmanager to 0.4.3 on my Debian laptop, then I cannot log in anymore.

The problem occurs due to configuration changing. Turn of debug log you will see

Trac[htfile] ERROR: acct_mgr: check_password() -- Can't locate password file ""

Just edit your trac.ini

htdigest_realm = your_realm
password_file = /path/to/htdigest
password_store = HtDigestStore

htdigest_realm =your_realm
htdigest_file = /path/to/htdigest
password_store = HtDigestStore


Exclude dependency jar file from apk when using Ant for Android

To put it simply, Android ant packages each jar files under directory libs to the destination apk file, but I don't wanna it. This is just workaround. (I am using Android SDK Tools 22.0.1)

I am writing a simple Bluetooth 4.0 application which base on Samsung series mobile phone. Android is going to support Bluetooth 4.0 but it does not happen so far. That means I still need using Samsung BLE SDK to use Bluetooth 4.0, that's ok.

When I started learning Samsung BLE SDK via attached samples, it works well. It is build-able under Eclipse, it works. When I used Ant to build the apk (yes, I used to use command-line tool to do developing.), it failed.

I got a run-time error:  <A Class> had used a different <B class>; during pre-verification

W/dalvikvm(22070): Class resolved by unexpected DEX: Lcom/samsung/ble/pxpmonitor/ProximityService$3;(0x430e85d0):0x40086000 ref [Lcom/samsung/android/sdk/bt/gatt/BluetoothGattCallback;] Lcom/samsung/android/sdk/bt/gatt/BluetoothGattCallback;(0x430e85d0):0x40038000
W/dalvikvm(22070): (Lcom/samsung/ble/pxpmonitor/ProximityService$3; had used a different Lcom/samsung/android/sdk/bt/gatt/BluetoothGattCallback; during pre-verification)
W/dalvikvm(22070): Unable to resolve superclass of Lcom/samsung/ble/pxpmonitor/ProximityService$3; (60)
W/dalvikvm(22070): Link of class 'Lcom/samsung/ble/pxpmonitor/ProximityService$3;' failed
D/AndroidRuntime(22070): Shutting down VM
W/dalvikvm(22070): threadid=1: thread exiting with uncaught exception (group=0x41f83930)
E/AndroidRuntime(22070): FATAL EXCEPTION: main
E/AndroidRuntime(22070): java.lang.NoClassDefFoundError: com/samsung/ble/pxpmonitor/ProximityService$3
E/AndroidRuntime(22070):        at com.samsung.ble.pxpmonitor.ProximityService.(ProximityService.java:195)
E/AndroidRuntime(22070):        at java.lang.Class.newInstanceImpl(Native Method)
E/AndroidRuntime(22070):        at java.lang.ClassLoader.loadClass(ClassLoader.java:461) 

Because the apk file I built contains ble_sdk.jar, and Samsung Galaxy S4 has the same (at least, the same name) implementation under /system/framework.

The problem is that I have to build some classes which depend on ble_sdk.jar, but I cannot package the ble_sdk.jar into apk file since it makes duplication.

In general, we put dependency libraries to directory libs, but the dex-helper macro in Android Ant build system merges EVERY JAR FILES INTO classes.dex. Cool, that bites me.

To put the ble_sdk.jar outside directory libs and asks ant-building-system refer to it? it doesn't work, we even cannot override the property jar.libs.dir. (issue #33194)

I tried to figure it out but quit with no luck. If you know a good way match my requirement, please tell me. This is my workaround. (workaround means --- Someday I will bite myself.)

Workaround: Do not package each jar under libs unless I ask you to do that.

Add a custom_rules.xml to your project with these statements.

<target name="-post-compile">
        <path id="project.all.jars.path">
                <!-- un-comment below line if you want it-->
                <!-- <pathelement path="libs/please_package_this.jar"> -->
        <echo level="info">To be packaged jar: ${toString:project.all.jars.path}

It cleans project.all.jars.path that defines Android ant-building-system's merge targets. I don't like this idea but it basically works.


change directory helper function

I wrote an article about it long time ago, now I write again to avoid lost my function.

If you are working in a big project such as Android, you will find that changing directory in a deep tree is painful.

Try adding this function to ~/.bashrc
..() {
    test $1 || num=1
    seq=`seq $num`
    next=`printf '../%.0s' {$seq}`
    cd $next

suppose you are at /home/foo/L1/L2/L3/L4

$ .. # will go to L3
$ .. 2 # will go to L2
$ .. 3 # will go to L1
$ .. 100 # will go to /


Gnome-shell makes things tough

That is my murmur in google+.

Debian Testing is my distribution of choice, last night it upgrade gnome-shell from 3.2 to 3.4. The good thing it provides 'fixed workspace number' in settings. The bad things I loose all my 'shorcut key binding'. I have to reconfigure my working environment this morning to get things work, includes digging in extensions.gnome.org.

I do not use a computer for using computer itself, but I do use computer for finishing some works in my life.

However, each time I upgrade gnome-shell (metacity to gnome-shell 3.0, 3.0 to 3.2, 3.2 to 3.4). I have to spend lots of time to make my laptop becomes working.

Working means it acts like that I wish it was. That is too stupid, I get a new thing and spend time to make it old since the old one works better.

I use Linux since it provides more options to customize to fits me, otherwise I will use Mac OS X. I had a iBook G4, everytime when I was using it, I heard Steve Jobs is shouting "Fool, you are using your computer in wrong way". well, I think gnome-shell team is trying to teach me how to use computer as well.

Extensions website save my life. but it is wrong. extension should be 'improving' but not 'saving'. It is weird gnome-shell says 'do not complain, you have way to clean your room since I mess it up.'

I am a developer, I understand things must forward, I agree with 'making gnome forwarding'. But making a political decision is not only about right or wrong but about how.

If gnome-shell made everthing looks like before and pretend nothing changed when the first time people see gnome-shell. Trust me, everybody will love it. ("it make gnome forward slowly?" as I said, we are using computer to finish job, we are not using computer to use gnome-shell.)

One more thing, there is a executable called 'gnome-shell-extension-prefs' to modify preferences of extension, thats great. but you cannot find it by searching. you have to launch it via command line. AWESOME!


Android Clickable Span in TextView

Note: You could find chinese version in my chinese blog.

Spannable brings lots of possibility to TextView, includes displaying various appearance of a Text and onClick callbak.

The normal way to make a TextView clickable is to use View.setOnClickListener. It sets a callback listener to the whole view. What if we just want to add callback to a substring of a text?

This pictures demonstrate

  • One TextView
  • The sub-string has variant color
  • The sub-string is clickable

Of course we could use ViewGroup + many TextView to accomplish that, spannable make things eaiser.(maybe....)

We can understand Span in this way: Put extra function to a CharSequence. For example, If I have string 'TheFinalAnswerIs42', I can set Red color to "Final" and make 42 clickable. But the TextView does not know so much things, it only focus on showing the whole string.

We know that TextView only needs CharSequence as its content, and both of Spannable and Spanned are sub-interface of CharSequence. The question becomes 'How to build desired CharSequence'

Android API Documentations tells us that we can use SpannableStringBuilder to generate SpannableString.

Spannable span = (new SpannableStringBuilder()).newSpannable("TheFinalAnswerIs42");
span.setSpan(new ForegroundColorSpan(0xFFFF0000), 3, 5,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

So the string "Final" becomes red.And we are going to make '42' clickable.

span.setSpan(new MyClickableSpan(), 16, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

MyClickableSpan is to be a implementation of ClickableSpan. All we have to do is override method onClick.

Further question: why setSpan is using primitive class Object but not some interface such as Spanned?

API documentation also tells you that you can bind any your own object as Span to TextView. But how to use my customized span object? To solve this, we should understand how the TextView use ClickableSpan.

The source code of TextView tells us that it handle ClickableSpan in onTouchEvent.

In other words, to handle our customzied span object, we should extends TextView to use CustomizedTextView to accomplish it.


tmux split window in current directory

I use tmux to instead of gnu-screen due to tmux supports vertical window splitting.

There are many common question such as 'How to create a new window in the current directory'. Here are some simple how-to, inspired by tmux FAQ.

1. Preparing - set environment variable by PS1 in shell
add this line to your .bashrc
PS1='$([ -n "$TMUX" ] && tmux setenv TMUXPWD_$(tmux display -p "#I") $PWD)${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '

How it works?

$([ -n "$TMUX" ] && tmux setenv TMUXPWD_$(tmux display -p "#I") $PWD)
The previous half part makes the magic, #I indicates the index of each displays. In display 1, it saves current directory ($PWD) into environment variable $TMUXPWD_1, corresponding to $TMUXPWD_2, $TMUXPWD_3 ...etc.

Just type 'printenv |grep TMUXPWD' and you will know everything.

Well, this is my own prompt (such as walkingice@my_laptop$ ), you can keep your own settings by 'cat ~/.bashrc |grep PS1'

2. Create new window in current directory
Follow the common FAQ, add this line to your .tmux.conf
bind-key c run-shell 'tmux neww "cd $(tmux display -p "\$TMUXPWD_#I"); exec bash"'
3. Split window in current directory
Since we did the magic to PS1, why don't we keep using it? Add these two lines to your .tmux.conf
bind-key h run-shell 'tmux splitw -v "cd $(tmux display -p "\$TMUXPWD_#I"); exec bash"'
bind-key v run-shell 'tmux splitw -h "cd $(tmux display -p "\$TMUXPWD_#I"); exec bash"'
Caution: I prefer Ctrl-a h to split horizontal window(splitw -v). In other words, when I click Ctrl-a h, I am saying "Hey, give me a horizontal line". I think it make more sense than tmux original key binding.