Cat Lesson 101

This post was imported from my old blog “Blogarbage” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
We are their staff, and probably the poorest ones. I regularly watch kittens cams on Ustream.TV. Yesterday, I saw the following on this channel:

it's gif. gif gif on TwitPic

LOL! That's our destinies to serve them, well, as a sort of bed?

Love kittens!

Propery setter and deleter in Python 2.5-

This post was imported from my old blog “make YJL” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
In this documentation, it shows an example code:
class C(object):
def __init__(self):
self._x = None

@property
def x(self):
"""I'm the 'x' property."""
return self._x

@x.setter
def x(self, value):
self._x = value

@x.deleter
def x(self):
del self._x

Which only runs on Python 2.6/3.0. This blog post demonstrates how to add the property.setter in Python 2.5.

I made a small change. The following code will check the Python version and replace built-in property with new one.
import sys
import __builtin__

# For Python 2.5-, this will enable the simliar property mechanism as in
# Python 2.6+/3.0+. The code is based on
# http://bruynooghe.blogspot.com/2008/04/xsetter-syntax-in-python-25.html
if sys.version_info[:2] <= (2, 5):
# If you need to acces original built-in propery(), uncomment the next line.
# __builtin__._property = property
class property(property):

def __init__(self, fget, *args, **kwargs):

self.__doc__ = fget.__doc__
super(property, self).__init__(fget, *args, **kwargs)

def setter(self, fset):

cls_ns = sys._getframe(1).f_locals
for k, v in cls_ns.iteritems():
if v == self:
propname = k
break
cls_ns[propname] = property(self.fget, fset,
self.fdel, self.__doc__)
return cls_ns[propname]

def deleter(self, fdel):

cls_ns = sys._getframe(1).f_locals
for k, v in cls_ns.iteritems():
if v == self:
propname = k
break
cls_ns[propname] = property(self.fget, self.fset,
fdel, self.__doc__)
return cls_ns[propname]

__builtin__.property = property

This should make your code be compatible with both Python 2.5 and 2.6. Once decided to be 2.6 only, you will only need to remove the import statement. Actually, you don't have to if you are lazy. :-)

Painless upgrage to Google Friend Connect on Blogger

This post was imported from my old blog “The B Thing” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
Actually it's not only painless but also automatic upgrade if you used the Followers gadget. I heard this great news from Blogger Buzz. Now all Followers gadgets on my blogs have converted into the Google Friend Connect gadgets and still have previously followers. We left no one behind!

Good job, Blogger!

Building Google Gears for Firefox 64-bit on Fedora 10 x86_64

This post was imported from my old blog “Tux Wears Fedora” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
I created a new blog on WordPress.com, then I felt the dashboard is really really slow. I hoped the Google Gears can improve speed a lot.

Checkout from repository
$ svn checkout http://gears.googlecode.com/svn/trunk/ gears-read-only
$ cd gears-read-only

Patching

There is an patch in this comment. However this patch would not work with more efforts, because it still use the Gecko comes with repository and that Gecko in subversion has 32-bit binary stuff, we need the 64-bit binary of Gecko (aka. XULRunner), you can install it on Fedora using yum install xulrunner-devel.x86_64.

My patch for r3234 (include exact same patch from that comment and comment out line 1195 of gears/tools/rules.mk) for Fedora 10 x86_64 can be downloaded in my comment on that issue.

You can patch by running
patch -p0 < r3234-64bit.patch

Copying 64-bit binary

Starting building process by running
cd gears
make BROWSER=FF3

The process will be stopped with the following error message:
/usr/bin/ld: skipping incompatible ../third_party/gecko_1.9/linux/gecko_sdk/lib/libxpcom.so when searching for -lxpcom
/usr/bin/ld: cannot find -lxpcom
collect2: ld returned 1 exit status
make[1]: *** [bin-opt/linux-x86_64/ff3/libgears.so] Error 1
make: *** [default] Error 2
 [ 2 ] livibetter@dfed ~/var/src/gea/gears > file ../third_party/gecko_1.9/linux/gecko_sdk/lib/libxpcom.so
../third_party/gecko_1.9/linux/gecko_sdk/lib/libxpcom.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped

Now we need to do the follows:
cp /usr/lib64/xulrunner-sdk-1.9/sdk/lib/libxpcom.so ../third_party/gecko_1.9/linux/gecko_sdk/lib/libxpcom.so
cp /usr/lib64/xulrunner-sdk-1.9/sdk/lib/libxpcomglue_s.a ../third_party/gecko_1.9/linux/gecko_sdk/lib/libxpcomglue_s.a
cp /usr/lib64/xulrunner-sdk-1.9/sdk/lib/libxul.so ../third_party/gecko_1.9/linux/gecko_sdk/lib/libxul.so
cp /usr/lib64/xulrunner-1.9/xpt_link ../third_party/gecko_1.9/linux/gecko_sdk/bin/xpt_link
chmod +x ../third_party/gecko_1.9/linux/gecko_sdk/bin/xpt_link

Build again, you should have no problem this time.

Packaging XPI installer

Packing can be done by running
make installers

The XPI should be generated under gears/bin-opt/installers.

You can download it here.

Testing

There are few demos that you can try out. I got no errors when ran them.

Using Djangos I18N in Google App Engine

This post was imported from my old blog “make YJL” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
(This post is written only for Django 0.96.1 in GAE)

Two days ago, I started to create another Google App Engine application. This application will be internationalized when it's finished. I tried searching for some solution, then I realized that there is no very simple way to achieve.

Normally, you can handle gettext stuff on your own, but our Google App Engine applications usually use templating from the SDK, which is from Django actually. One way or another, we have to incooperate with Django partially.

The goal here is:
  • Use minimal Django stuff, only import the essential stuff in order to get Django's I18N support to work.
  • Messages in template must be translated, too.
  • Capable to decide the language from the cookie, django_language, or the request header, HTTP_ACCEPT_LANGUAGE.
I have already made a sample code, which you can read here and you can see it at http://yjltest.appspot.com/i18n.

Before we go into the code, please read the I18N and Settings of Django.

Setting Up

We need to use Django Settings to make I18N work. The reason of using Setting was due to Django's gettext helper will require Settings module and decide location of message files by the location of Settings module.

If we want to use Django Setting, we must run the following code:
from google.appengine.ext.webapp import template

os.environ['DJANGO_SETTINGS_MODULE'] = 'conf.settings'
from django.conf import settings
# Force Django to reload settings
settings._target = None

Note that you must import the google.appengine.ext.webapp.template module, or you might get error about conf.settings is not able to be imported.

We need to set the environment varible DJANGO_SETTINGS_MODULE to the location of Setting module, conf.settings in this case. conf is the package and settings is a module file, our Settings module.

Why conf? Because when we generate message files from Python scripts and templates we will see how to generate later, the Django message file generator, make-messages.py, will create files under conf/locale/ from where it's run.

Settings

What do we need in conf/settings.py?
USE_I18N = True

# Valid languages
LANGUAGES = (
# 'en', 'zh_TW' match the directories in conf/locale/*
('en', _('English')),
('zh_TW', _('Chinese')),
    # or ('zh-tw', _('Chinese')), # But the directory must still be conf/locale/zh_TW
)# This is a default languageLANGUAGE_CODE = 'en'

Mark the messages

Wraps those need to be translated with _("message") in Python script and {% trans "message" %} in template files. Please read I18N for more usages.

Generate message files

Before you run the helper script, we need to create conf/locale, the helper won't create it for us.

Make sure you are at root of Google App Engine application's directory, then run
$ PYTHONPATH=/path/to/googleappengine/python/lib/django/ /path/to/googleappengine/python/lib/django/django/bin/make-messages.py -l en

/path/to/googleappengine/ is the Google App Engine SDK's location. This command should generate the conf/locale/en/LC_MESSAGE/django.po. Now you can open it to translate.

Don't forget to set CHARSET, Usually UTF-8 will be fine, the line would read like:
"Content-Type: text/plain; charset=UTF-8\n"

Once you finish translating, you need to run
$ PYTHONPATH=/path/to/python/googleappengine/lib/django/ /path/to/googleappengine/python/lib/django/django/bin/compile-messages.py

It will geneate django.mo files in each language directories. You also need to update when you modify scripts or template, run
$ PYTHONPATH=/path/to/googleappengine/python/lib/django/ /path/to/googleappengine/python/lib/django/django/bin/make-messages.py -a

This will update all languages in conf/locale.

Working?

If you run you application, now it should show the language in conf.settings.LANGUAGE_CODE.

This is a per application setting, which is not normally that we want. We will expect each user can choose their own language. Django has a helper that calls LocaleMiddleware can do the job, unfortunately, it needs Django's request and response class to work normally.

Do the dirty job

In order to do what LocaleMiddleware does, we need to make Google App Engine's request/response objects have same behavior as Djagno's. For easing the complexity, we create a new class, I18NRequestHandler, which inherits google.ext.webapp.RequestHandler. You only need to replace with it in your handlers.

import os

from google.appengine.ext import webapp
from django.utils import translation

class I18NRequestHandler(webapp.RequestHandler):

def initialize(self, request, response):

webapp.RequestHandler.initialize(self, request, response)

self.request.COOKIES = Cookies(self)
self.request.META = os.environ
self.reset_language()

def reset_language(self):

# Decide the language from Cookies/Headers
language = translation.get_language_from_request(self.request)
translation.activate(language)
self.request.LANGUAGE_CODE = translation.get_language()

# Set headers in response
self.response.headers['Content-Language'] = translation.get_language()
# translation.deactivate()

Where Cookies is from http://appengine-cookbook.appspot.com/recipe/a-simple-cookie-class/. When request comes in, it can automatically activate the language from what Cookies/Headers specify.

Caching problem

It's not so perfect. I have noticed a problem in development server. If you change code and/or the message file, recompile the message file while server still runs, those message in entry script may not be translated for reflecting to cookie django_language's change. I believe that is about the caching.

I am not sure the natural problems, so I couldn't solve it. However, this may not be severe problem.

Encoding

If you use unicode string (not str string) in {% blocktrans %} template tag, you may get error, encode it to utf-8 first, e.g. s.encode('utf-8').

Language Code

You must use underscore not dash for messages directory, e.g aa_BB, or Django would not recognize directory named as aa-BB or aa-bb. But in conf.settings you can use aa-bb, this means the language code and directory can be different, e.g. zh-tw for the language code in Python and zh_TW as message directory name.

Conclusion

Although this will work, but it may be broken if any changes to Django framework within Google App Engine. There isn't a good solution for I18N in Google App Engine if Google doesn't natively support it.

Updated on 2009-11-25: Added not about template module first and encoding issue, and updated the path of Python lib in GAE SDK.
Updated on 2009-12-24: Added a note about Language Code format, thanks BRAGA, again.
Updated on 2010-02-04: Added a note about the Language Code and message directory name.

Billing is now on Google App Engine

This post was imported from my old blog “make YJL” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
Google App Engine just announced the free quota will be reduced in 90 days, by 2009-05-25. The detail changes are:
  • CPU Time: 46.3 down to 6.5 hours, about 14% remaining.
  • Bandwidth In/Out: 10.0 GB down to 1.0 GB, 10 % remaining.
It's not all reductions, they also doubled the storage quota from 0.5 GB to 1.0 GB.

If you just signed in the dashboard, you would need to agree new Terms of Service, then you would see the new billing section. The most important change of ToS possibly is 4.4. You may not develop multiple Applications to simulate or act as a single Application or otherwise access the Service in a manner intended to avoid incurring fees.

Even though it cut off much more free quota on CPU Time and Bandwidth. My apps will stay in free quota, they are not hot. :)

A Dream on New Years Day

This post was imported from my old blog “Blogarbage” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
(This is a late post. I think this is possible the last moment to post.)

After I watched a family broadcast celebration (fireworks) of New Years in Disney's Polynesian Resort, an idea was suddenly stuck in my head. Or more like a dream, an unrealistic dream or wish.

I wonder if it is possible that I can travel for living? Travel as my job, but not like those you will see on TV or read on books. I get money to travel in any way I like. Ha! We then ask who would like to give you money to travel? Yep, I doubt that, too.

About a year ago, I told a MSN contact about travel. I think a good trip is to try to be a local. Having conversations with people who live there for many years is a nice travel for me. Anthony Bourdain has said Be a traveller, not a tourist. I always remember that.

I wish I could stay in a place at least a week up to a month. Meet some local and host a live chat show with them. Not only for feeling for myself, but also sharing the people, the culture with Internet people. I can tweet, upload photos and clips, and write about what I see and hear.

Every year, I celebrate New Year from different places with different people, who I may or may not know. Learn the culture they have been living for generations and generations, taste the food they would never miss even for a single meal,enjoy the environment they protect and cherish, and listen to every aspect that they proud of.

Eventually, this is just a dream. That's not because it's unreal but I never tried to make it real.

Trying out the CMU Sphinx

This post was imported from my old blog “make YJL” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
Not this Sphinx, naming is really a important fact. Anyway, I tried to play with CMU Sphinx. It, the pocketsphinx, provides Python binding, though no real documentation. There are two modes that you can do recognization, by on-the-fly or by block of data. By default models, on-the-fly gives useless results, I don't know if it can do better after training a bit. However, I have no idea how to do that, too. By decoding a block a data gives acceptable results.

I was actually caught by gnome-voice-control. It does work, but it also crashes. I checked out the repository (I couldn't compile version 0.3) and installed sphinxbase 0.4.1 and pocketsphinx 0.5.1.

Since it crashes everytime, I wanted to write a simple or similar one using Python. Unfortnately, the result isn't good, though reduce word bank and do word slice on our own plus decode by block may help to improve the accuracy, but I think that's much effort to do and I have much knowledge of speech recognization. I stopped here.

I still organized a simple code, which uses pyalsaaudio 0.4 to capture audio. It records till you press Ctrl+C, then do recognization.

You can also try this Python script, which is a GUI and uses Sphinx'es Gstreamer plugin.

Making ghost avatar

This post was imported from my old blog “Get Ctrl Back” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
Earlier today, I changed my avatar on Twitter. It's for fun that make avatar look like blank image. However, you still can see something from the avatar.



So, here comes this post. I use GIMP to make another one from a cat image. The original is



(Kind of cool face, isn't?)


The rough steps

  1. Firstly, open it and duplicate the layer. And don't forget to add alpha channel. Name the duplicated layer as Edge.


  2. Apply Filters Edge-Detect Sobel... on Edge layer. The result looks like






  3. Remove some unwanted edges, only leave the main part. In this case, the cat's head.

  4. Add Black (full transparency) layer mask to Source layer.

  5. Copy Edge layer onto Source's layer mask.

  6. Reduce Opacity to make the image be barely seen.

  7. Enhance if the ghost image is not evenly seen:

    a) Duplicate the Edge as Enhance.

    b) Remove the parts that are too strong from Enhance layer.

    c) Adjust Opacity of Enhance layer to make ghost image looks balanced.


The final image




Yes, it's right above. (I set the opacity way too low. :p) The final GIMP file is here.

Some websites that support avatar in PNG format

This post was imported from my old blog “Get Ctrl Back” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
I just changed my avatar to:



(Yes, it's really here, I guarantee!)


Because it's special, therefore only those websites which support PNG can use it, or it will only be ugly black avatar.



Anyway, here is the list of those websites that support PNG avatar:

  • Blogger

  • Get Satisfaction


  • Google Groups

  • Google Profile

  • Jamendo


  • Last.fm


  • LiveJournal

  • Picasa Web Albums

  • Twitter

  • Yahoo


  • Youtube

Here is another list of those websites which don't support PNG avatar:

  • 43Things

  • Blip.fm


  • Disqus


  • Facebook

  • Flickr


  • FriendFeed

  • Gravatar

  • Technorati


  • Ustream.tv


  • Verisign PIP

  • Vimeo


speak.py

This post was imported from my old blog “make YJL” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
I wrote a simple program using PyQt4 and Speech Dispatcher.


I wrote it for understanding how to work with PyQt. I used Qt4 Designer to design the UI and the program loads the UI file at run-time.

Before you can really use this program, you have to make sure Speech Dispatcher really working. I have to set the output device of each module to PulseAudio, somehow, ALSA doesn't work. For festival module, I also need to start the server with these files.

You can see and download the source here. The speak.py is the main program. It's licensed under the GPLv3.

Stop greedy Flash Player

This post was imported from my old blog “make YJL” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
On my another blog, I wrote about how to do live screencast on Linux with AVLD, ffmpeg, and mencoder. There was an unsolve problem, the performance of Flash Player. Actually, it also has problem with ustreamer.tv's broadcaster, the Flash object. It makes me get kerneloops. I seemed to solve it too, as well as the performance issue.

I have to clear that I don't know much of C and not even to mention about kernel knowledge. Basically, you can say that I know nothing.

The kerneloops

I checked up the gspca's code, I found out it uses copy_to_user instead of memcpy in read operation. That seems to solve the problem, though I really can't say. At least, I haven't seen oops again, so far.

Performance Issue

I thought Flash Player is the only one should take response of low FPS. But I realized that ffmpeg and mencoder actually can't take care of 1280960 at 4 FPS, they only use 12~15% CPU utilization, I don't know why would they take more. Anyway, I downed the setting to 960720 at 5 FPS. So far so good.

Now, back to Flash Player. I turned on debug switch in AVLD, then I found out Flash Player requests 1699 reads per second. But I only have 4 or 5 frames data. Isn't that is too high? Same, I don't know why would Flash Player request that many, but I do know that is the problem of performance. Flash Player must want to process all 1699 frames, though they are only in 5 different frames.

So what can I do? I just copy and paste a piece of code from v4l_write and paste that into v4l_read without any changes. Yep, exactly the same. My 2 cores use around 30%.

Patch

Here is a repack with modified video_device.c, and this is the bad patch.

I hope someone who knows entire thing can fix it correctly. I have mailed the author of AVLD few days ago when I just had problem, so far, I didn't get any response from the author.

Live screencast through Flash Player on Fedora

This post was imported from my old blog “Tux Wears Fedora” on 2010-09-28. Some stuff in this post may be broken, please leave a comment if you see any, then I will try to fix it.
It's been a while that I wanted to broadcast my desktop screen on Linux. You can set up your broadcast server, of course, but that may not be giving you many viewers.

I want to stream on ustream.tv, I know I need an new /dev/video# for Flash Player to detect as a webcam. Another Video Loopback Device can help create a dummy video device, you can even use it to stream video. The version I used is 0.1.4. AVLD is easy to compile, make and make install, that is all.

Now you can load the kernel module:
sudo modprobe avld width=320 height=240 fps=5 palette=0
sudo chmod 666 /dev/video0

First three parameters to avld module should be clear with explanation, the last one means color palette is RGB24.

The second command allows everyone to read, and to write, to the dummy video device. That may not be a good idea to do that, but I haven't had a better way.

Next is to grab your screen and write to dummy video device:
ffmpeg -f x11grab -vc rawvideo -s 1280x960 -r $FPS -an -i :0.0 -f rawvideo -pix_fmt rgb24 - | mencoder - -demuxer rawvideo -rawvideo fps=$FPS:w=1280:h=960:format=rgb24 -nosound -ovc raw -vf scale=320:240,format=bgr24 -of rawvideo -ofps $FPS -o /dev/video0

I use ffmpeg to grab and mencoder to scale image and write to video device. Here is some facts about this command, codec is rawvideo, in-format is rgb24, out-format is bgr24 (not match with the avld module parameter?), out-size is 320240.

You can use mplayer to check up if it works:
mplayer tv:// -tv "driver=v4l:device=/dev/video0:noaudio:outfmt=bgr24" -vo x11 -fps $FPS

Problem

The performance of Flash Player is simply awful, Firefox eats up entire core. Even though I have downed to 4 FPS in setting, the result screen still looks like 1/4 FPS.

I was trying to install Flash Media Live Encoder 3 with WINE, it installed and ran, but it can not grab any screen from the dummy device. I also tried a real webcam, can't do, either.

I also wrote a simple script to help me broadcast, you can check it out, it also use some filters that add blur or desaturation effects.

If you are interested, I am broadcasting at Wearing Fedora.

Updated on 2009-02-02: I have made a bad patch to solve the FPS issue. Later, I found a better one, Webcamstudio.