Howto remap keyboard keys in Linux

Almost two years since I wrote a blog post, but learnt a lot in these past two years. I’ll be writing everything I can remember in the coming days, but first, I need to record down something I learnt recently.

I came across one challenge to generate a key press event where the key is not at all in the normal US keyboard. That special key (Hangul/English Toggle key) is only available in Korean Keyboard. So, here is how I did

We need to choose any one key available in the normal US keyboard and remap it to produce Hangul/English Toggle Key’s code. For my purpose I’m going to remap F7 key to produce Hangul/English keypress events. First, I need to know what F7 produces when it gets pressed. There is a tool called “evtest” which will show the code generated by physical keyboard

Event: time 1496043435.462606, type 4 (EV_MSC), code 4 (MSC_SCAN), value 41
Event: time 1496043435.462606, type 1 (EV_KEY), code 65 (KEY_F7), value 0

Here, the MSC_SCAN value of “41” (hexadecimal) is the code generated by the physical keyboard. Using this value. we need to create one file (/usr/lib/udev/hwdb.d/63-keyboard.hwdb) with the following content

keyboard:name:AT Translated Set 2 keyboard:dmi:*
 KEYBOARD_KEY_41=hangeul

Here, The first line starting with “keyboard:” indicates the name of the keyboard. There are lot of way to match the keyboard (see /usr/lib/udev/hwdb.d/60-keyboard.hwdb file for more details). The second line which starting with “KEYBOARD_KEY_” should have one space before “KEYBOARD”. The “hangeul” string at the end of the second line is a suffixed lowercase substring of a macro defined in /usr/include/linux/input-event-codes.h file. You can use more than one “KEYBOARD_KEY_=” lines to remap the keys in your physical keyboard.

Once you create the 63-keyboard.hwdb file. Run the following command to update /etc/udev/hwdb.bin file which is used by udev

sudo udevadm hwdb --update

Once the hwdb.bin file updated, Either reboot your machine or trigger udev events for the particular keyboard (here, /dev/input/event1 may vary depend on your keyboard devfile mapping)

sudo udevadm trigger /dev/input/event1

Once you have the remapping, you can test it again with evtest.

Event: time 1496046275.166879, type 4 (EV_MSC), code 4 (MSC_SCAN), value 41
Event: time 1496046275.166879, type 1 (EV_KEY), code 122 (KEY_HANGUEL), value 0

In the above output, MSC_SCAN value “41” generates “KEY_HANGUEL” instead of “KEY_F7”.

Update (2018-02-06):

I recently have to remap Left Window Key to Right Window Key. So I created a new file in /etc/udev/hwdb.d/92-keyboard-override.hwdb and added following lines

# keyboard overrides

# laptop keyboard
libinput:keyboard:*
 KEYBOARD_KEY_db=rightmeta
 KEYBOARD_KEY_dd=rightmeta

# USB keyboard
evdev:*
 KEYBOARD_KEY_700e3=rightmeta

Here KEYBOARD_KEY_dd=rightmeta changes Menu key to Right Window Key, KEYBOARD_KEY_db=rightmeta and KEYBOARD_KEY_700e3=rightmeta both changes Left Window Key to Right Window Key but former is for laptop keyboard and later is for USB keyboard.

howto change font in linux using fontconfig

To those who are not familier to fontconfig, it is the library which provides fonts to each program in your linux desktop (atleast in gnome3). It maintains the details about all the font files available in your linux box and provides best matched font when your program requests a specific type of font.

If you use only english in day-to-day activities, fontconfig dont come in your way, but its a nightmare if you are a multilingual user. Even if you are a multilingual user, fontconfig tries its best to make your life easy by matching the best font for your language automatically, but the pain starts if you don’t like what fontconfig provides and want to change the default font for your language to something which looks good in the editor.

I went through the pain and want to share what I did to fix. For me, fontconfig said “TAMu_Kadambari” is the best font for “Tamil” and gedit by default shows tamil fonts using “TAMu_Kadambari”. But, this font doesn’t look good in gedit. After much research, I’m able to change the default font for “Tamil” language from “TAMu_Kadambari” to “TAMu_Kalyani” using this xml file.


<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!--save this file as ~/.config/fontconfig/fonts.conf-->
<fontconfig>
<match>
<test name="lang">
<string>ta</string>
</test>
<edit name="family" mode="assign">
<string>TAMu_Kalyani</string>
</edit>
</match>
</fontconfig>

Here, the <match> tag contains one test which checks if the provided language is “Tamil” (lang=ta). If it is, then edit the original request coming from the application and assign family name as “TAMu_Kalyani”(family=TAMu_Kalyani) so that fontconfig matching algorithm will match only “TAMu_Kalyani”.

Thats it, my gedit now picks “TAMu_Kalyani” and it looks good. More details about fontconfig is available here.

fontconfig uses patterns for its matching algorithm, and it goes like this


<families>-<point sizes>:<name1>=<values1>:<name2>=<values2>..

for example, here is how you can check which is the best matched font available in your system for language “Tamil”. Output also contains top 10 ranked fonts for tamil. The first preferred font is “TAMu_Kalyani”, because I have overridden in ~/.config/fontconfig/fonts.conf


[mohan@mohanlaptop0 ~]$ fc-match -s 'monospace-10:lang=ta' | head
TAMu_Kalyani.ttf: "TAMu_Kalyani" "Regular"
TSCu_Comic.ttf: "TSCu_Comic" "Normal"
DejaVuSans.ttf: "DejaVu Sans" "Book"
DejaVuSansMono.ttf: "DejaVu Sans Mono" "Book"
DejaVuSerif.ttf: "DejaVu Serif" "Book"
Pothana2000.ttf: "Pothana2000" "Pothana2000"
MalOtf.ttf: "MalOtf" "Book"
TSCu_Paranar.ttf: "TSCu_Paranar" "Regular"
SyrCOMAdiabene.otf: "East Syriac Adiabene" "Regular"
SyrCOMKharput.otf: "Serto Kharput" "Regular"
[mohan@mohanlaptop0 ~]$

If I remove ~/.config/fontconfig/fonts.conf, it goes back to the original behaviour and provides “TAMu_Kadambari” as preferred font for “Tamil”


[mohan@mohanlaptop0 ~]$ fc-match -s 'monospace-10:lang=ta' | head
TAMu_Kadampari.ttf: "TAMu_Kadambri" "Regular"
TAMu_Kalyani.ttf: "TAMu_Kalyani" "Regular"
DejaVuSansMono.ttf: "DejaVu Sans Mono" "Book"
DejaVuSansMono-Bold.ttf: "DejaVu Sans Mono" "Bold"
DejaVuSans.ttf: "DejaVu Sans" "Book"
DejaVuSerif.ttf: "DejaVu Serif" "Book"
Pothana2000.ttf: "Pothana2000" "Pothana2000"
MalOtf.ttf: "MalOtf" "Book"
TSCu_Comic.ttf: "TSCu_Comic" "Normal"
TSCu_Paranar.ttf: "TSCu_Paranar" "Regular"
[mohan@mohanlaptop0 ~]$

fontconfig configuration files are very versatile and one can do lot of things, but we need to first understand its patterns to do anything useful. Anyway, I hope this article provide good example for fc-match command-line tool and fontconfig patterns.

SPA (Single Page Application) for amateur web developer

That amateur web developer is none other than “yours truely”.

Recently, I came across this article about a over-engineered blog. It is awesome and gave me insights into React and how client side view-controller frameworks ( like Angular, Ember, Backbone etc.,) works and how modern web developers offloading business logic to client side. The blog post not only inspired me to learn more about these frameworks, it introduced me to what people call SPA (Single Page Application).

After reading about SPA, I cannot control myself to change my personal website into a SPA application. Here I share my experience about the tools I used to develop the new website.

Node.js and Hapi

My previous choice was Node with Express but, this time, I thought I’m not doing anything in the server, its going to be only serving the bytes. So, I decided to use any REST serving framework instead of Generic framework. I came across Restify but decided to go with Hapi for its simplicity (it turned out that I made the right decision)

Request

I don’t use any database in my website and all the contents are fetched from wordpress, google drive and twitter web apis. The website relies heavily on request to connect to these web services and it is one awesome tool to have for a node application which heavily depend on third party web services.

Handlebars, Stylus and Jeet

These are damn good when it comes to view. Handlebars rocks but the built-in helpers are not that helpful, the if block helper not even allow to check for logical operations. I have to write my own helper to do that. Stylus provided the easiest way to design my UI components and Jeet provided the easiest way to create boxes.

Website_Blog

 google-code-prettify and jsOnlyLightBox (customized for dynamic picture loading)

Great thing about prettify is, you don’t need to specify the language, it automatically detects and format the pre and code tags. I used jsOnlyLightBox to show pictures in my Gallery. I have customized it for this website because the vennila jsOnlyLightBox requires all the images to be present before we call load(). I did some changes to make it work with dynamically created img tags and it looks simple and elegant.

Website_Gallery

Socket.IO and Twitter Streaming

Just like my previous website, I used socket.io to relay the tweets coming from twitter streams. Integrating twitter streaming with my website took some heavy hours, but the final result is worth for every second I spent.

Website_Tweets

Browserify and Gulp

I didn’t use any client side javascript frameworks (like Angular, React, Backbone etc.,) but plain javascript classes as node modules. Browserify helped to bundle all the client side modules with ease. Gulp is the one which rendered all the stylus and handlebars files.

What next?

I dont even know whether I did something good or bad. but, compare to previous codebase, the current one is much simplified(without loosing the functionalities) and clean. It was a great learning exprement. But, I bet, I’ll not going to keep this codebase till the next year. If I see another good inspirational article which introduces any latest technologies, then, I’ll jump-in straight. Afterall, no-one is going to care about my personal website except me. The sources are available here. If you want, just take it and tinker yourself.

yield in vala and gio concurrency

By no means, I’m an expert in vala or gio. Infact, I’m just a beginner, but I have learned something while playing with vala which I want to record (for future reference). Here I’ll explain how Gio’s async framework works and how vala uses Gio beneath the tree.

Gio Async Framework:

Better to explain with an example,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define TEST_TYPE_GIO_ASYNC (test_gio_async_get_type())
#define TEST_GIO_ASYNC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TEST_TYPE_GIO_ASYNC, TestGioAsync))
#define TEST_GIO_ASYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_GIO_ASYNC, TestGioAsyncClass))
#define TEST_IS_GIO_ASYNC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TEST_TYPE_GIO_ASYNC))
#define TEST_IS_GIO_ASYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_GIO_ASYNC))
#define TEST_GIO_ASYNC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TEST_TYPE_GIO_ASYNC, TestGioAsyncClass))
#define TEST_GIO_ASYNC_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), TEST_TYPE_GIO_ASYNC, TestGioAsyncPrivate))
typedef struct _TestGioAsync TestGioAsync;
typedef struct _TestGioAsyncClass TestGioAsyncClass;
typedef struct _TestGioAsyncPrivate TestGioAsyncPrivate;
struct _TestGioAsyncClass {
GObjectClass parent;
};
struct _TestGioAsyncPrivate {
gchar *something_to_say;
};
struct _TestGioAsync {
GObject parent_instance;
TestGioAsyncPrivate *priv;
};
enum {
TEST_GIO_ASYNC_DUMMY_PROPERTY,
TEST_GIO_ASYNC_SOMETHING_TO_SAY
};
static gpointer test_gio_async_parent_class = NULL;
GType test_gio_async_get_type(void) G_GNUC_CONST;
static void test_gio_async_set_property(GObject *obj, guint prop_id, const GValue *value, GParamSpec *spec) {
TestGioAsyncPrivate *priv = NULL;
priv = TEST_GIO_ASYNC_GET_PRIVATE(obj);
switch(prop_id) {
case TEST_GIO_ASYNC_SOMETHING_TO_SAY:
priv->something_to_say = g_value_dup_string(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
}
}
static void test_gio_async_get_property(GObject *obj, guint prop_id, GValue *value, GParamSpec *spec) {
TestGioAsyncPrivate *priv = NULL;
priv = TEST_GIO_ASYNC_GET_PRIVATE(obj);
switch(prop_id) {
case TEST_GIO_ASYNC_SOMETHING_TO_SAY:
g_value_set_string(value, priv->something_to_say);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
}
}
static void test_gio_async_instance_init(TestGioAsync *self) {
self->priv = TEST_GIO_ASYNC_GET_PRIVATE(self);
}
static void test_gio_async_finalize(GObject *obj) {
TestGioAsyncPrivate *priv = NULL;
priv = TEST_GIO_ASYNC_GET_PRIVATE(obj);
g_free(priv->something_to_say);
G_OBJECT_CLASS(test_gio_async_parent_class)->finalize(obj);
}
static void test_gio_async_class_init(TestGioAsyncClass *klass) {
test_gio_async_parent_class = g_type_class_peek_parent(klass);
g_type_class_add_private(klass, sizeof(TestGioAsyncPrivate));
G_OBJECT_CLASS(klass)->set_property = test_gio_async_set_property;
G_OBJECT_CLASS(klass)->get_property = test_gio_async_get_property;
G_OBJECT_CLASS(klass)->finalize = test_gio_async_finalize;
g_object_class_install_property(G_OBJECT_CLASS(klass),
TEST_GIO_ASYNC_SOMETHING_TO_SAY,
g_param_spec_string("something_to_say",
"something_to_say",
"something_to_say",
NULL,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT));
}
GType test_gio_async_get_type(void) {
static volatile gsize test_gio_async_type_id__volatile = 0;
if(g_once_init_enter(&test_gio_async_type_id__volatile)) {
static const GTypeInfo g_define_type_info = { sizeof(TestGioAsyncClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) test_gio_async_class_init,
(GClassFinalizeFunc) NULL,
NULL,
sizeof(TestGioAsync),
0,
(GInstanceInitFunc) test_gio_async_instance_init,
NULL };
, GType test_gio_async_type_id = g_type_register_static(G_TYPE_OBJECT,
"TestGioAsync",
&g_define_type_info,
0);
g_once_init_leave(&test_gio_async_type_id__volatile, test_gio_async_type_id);
}
return test_gio_async_type_id__volatile;
}
TestGioAsync* test_gio_async_new(void) {
return g_object_new(TEST_TYPE_GIO_ASYNC, NULL);
}
static gboolean test_gio_async_say_idle_func(gpointer user_data) {
TestGioAsync *self = (TestGioAsync *) user_data;
GSimpleAsyncResult *simple = g_object_get_data(G_OBJECT(self), "simple");
gchar *result = NULL;
g_object_get(G_OBJECT(self), "something_to_say", &result, NULL);
g_simple_async_result_set_op_res_gpointer(simple, result, g_free);
g_simple_async_result_complete_in_idle(simple);
_g_object_unref0(simple);
return FALSE;
}
void test_gio_async_say(TestGioAsync *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data) {
GSimpleAsyncResult *simple = g_simple_async_result_new(G_OBJECT(self),
callback,
user_data,
test_gio_async_say);
g_simple_async_result_set_check_cancellable(simple, cancellable);
g_object_set_data(G_OBJECT(self), "simple", simple);
g_idle_add(test_gio_async_say_idle_func, self);
}
gchar* test_gio_async_say_finish(TestGioAsync *self,
GAsyncResult *res,
GError **error) {
GSimpleAsyncResult *simple = NULL;
g_return_val_if_fail(g_simple_async_result_is_valid(res, G_OBJECT(self), test_gio_async_say), NULL);
simple = (GSimpleAsyncResult *) res;
if(error) g_simple_async_result_propagate_error(simple, error);
return g_simple_async_result_get_op_res_gpointer(simple);
}
static void test_gio_async_say_cb(GObject *self, GAsyncResult *res, gpointer user_data) {
gchar *result = test_gio_async_say_finish(TEST_GIO_ASYNC(self), res, NULL);
GMainLoop *mainloop = (GMainLoop *) user_data;
g_print("%s\n", result);
g_main_loop_quit(mainloop);
}
int main(int argc, char *argv[]) {
TestGioAsync *test = test_gio_async_new();
GMainLoop *mainloop = g_main_loop_new(NULL, TRUE);
g_object_set(G_OBJECT(test), "something_to_say", "hello world", NULL);
test_gio_async_say(test, NULL, test_gio_async_say_cb, mainloop);
g_print("started saying..\n");
g_main_loop_run(mainloop);
return 0;
}

view raw
testgioasync.c
hosted with ❤ by GitHub

Here, I have created a new GObject class called TestGioAsync with something_to_say property. I have implemented a simple async function called test_gio_async_say.  When called, test_gio_async_say will setup GSimpleAsync object, attach another function called test_gio_async_say_idle_func into GMainLoop’s next idle iteration and return.

Once test_gio_async_say_idle_func triggered, it takes the value from something_to_say property and put it into g_simple_async_result_set_op_res_pointer as op_res (which will be picked-up later) and completes the async transaction with g_simple_async_result_complete_in_idle which will call the test_gio_async_say_cb provided in test_gio_async_say in GMainLoop’s next idle iteration.

Once test_gio_async_say_cb triggered, it will call test_gio_async_say_finish which will simply return op_res which contains the value taken from something_to_say property.

Vala Async Framework:

This is the equivalent vala example for the above C example

#!/usr/bin/env vala
class Test.Async : GLib.Object {
public async string say(string sentence) {
GLib.Idle.add(this.say.callback);
yield;
return sentence;
}
public static int main(string[] args) {
Test.Async myasync = new Test.Async();
GLib.MainLoop mainloop = new GLib.MainLoop();
myasync.say.begin("helloworld",
(obj, res) => {
string sentence = myasync.say.end(res);
print("%s\n", sentence);
mainloop.quit();
});
mainloop.run();
return 0;
}
}

view raw
testasync.vala
hosted with ❤ by GitHub

Vala async functions returns immediately whenever it reaches yield keyword, In this example, I have hooked this.say.callback into GMainLoop’s next idle iteration. In the next idle iteration, this.say will be called and will start execution exactly after the yield statement which will eventually trigger the anonymous lambda function provided in  this.say.begin with sentence as return value.

Once the lambda function triggered, it will call this.say.end which will return the sentence value to the lambda function.

In Vala example, this.say.callback is equivalent to test_gio_async_say_idle_func in C example.

Setup Gnome Development Environment in Archlinux

Many people who want to contribute to Gnome will go with Fedora, because it is the best suitable for gnome developer. But, Archlinux is as good as Fedora in terms of providing latest gnome libraries. Here I’ll explain how I setup my development environment in Archlinux using pacstrap, jhbuild and arch-chroot.

Setup Base

In your home directory, create a folder for gnome and install archlinux packages

$ mkdir -p ~/Devel/gnome/runtime
$ cd ~/Devel/gnome
$ su
# pacstrap -d runtime base base-devel
# chown -R <username>:<groupname> runtime
# exit
$

Here, <username>:<groupname> must be your username and groupname to make sure you are able to modify the files inside ~/Devel/gnome/runtime without any issues. The above steps will install Archlinux base packages. Now, we need to install jhbuild,

Jhbuild

$ cd ~/Devel/gnome/checkout
$ git clone git://git.gnome.org/jhbuild
$ cd jhbuild
$ PYTHON=/usr/bin/python2 ./autogen.sh --prefix="${HOME}/Devel/gnome/runtime/usr"
$ make install

done, next step is to configure jhbuild to setup the paths properly, to do this, we need to copy the sample jhbuildrc file from jhbuild source directory to ~/.config directory and edit that file,

$ cp ~/Devel/gnome/checkout/jhbuild/examples/sample.jhbuildrc ~/.config/jhbuildrc

Here is my .jhbuildrc modifications

# -*- mode: python -*-
--- /home/mohan/Devel/gnome/checkout/jhbuild/examples/sample.jhbuildrc   2015-01-17 11:38:40.055187155 +0800
+++ /home/mohan/.config/jhbuildrc       2015-01-06 09:07:34.493161676 +0800
@@ -10,22 +10,25 @@
 # jhbuild/defaults.jhbuildrc, but can be any file in the modulesets directory
 # or a URL of a module set file on a web server.
 # moduleset = 'gnome-apps-3.12'
-#
+moduleset = 'gnome-world'
+
 # A list of the modules to build.  Defaults to the GNOME core and tested apps.
 # modules = [ 'meta-gnome-core', 'meta-gnome-apps-tested' ]
 
 # Or to build the old GNOME 2.32:
 # moduleset = 'gnome2/gnome-2.32'
 # modules = ['meta-gnome-desktop']
+modules = ['gjs', 'farstream', 'gnome-online-accounts', 'polari', 'gnome-shell', 'glade', 'gnome-builder']
 
 # what directory should the source be checked out to?
-checkoutroot = '~/jhbuild/checkout'
+checkoutroot = '~/Devel/gnome/checkout'
 
 # the prefix to configure/install modules to (must have write access)
-prefix = '~/jhbuild/install'
+prefix = '~/Devel/gnome/runtime/usr'
 
 # custom CFLAGS / environment pieces for the build
 # os.environ['CFLAGS'] = '-Wall -g -O0'
+os.environ['PYTHON'] = '/usr/bin/python2'
 
 # extra arguments to pass to all autogen.sh scripts
 # to speed up builds of GNOME, try '--disable-static --disable-gtk-doc'

Here is the details of my changes,

  • moduleset – A moduleset is an xml file contains details (like modulename, version info, repo address, type of repo, how to build etc.,) of each and every project (we call it as module) needed for gnome environment. jhbuild maintains moduleset for each release, you can see the different modulesets inside your jhbuild directory (~/Devel/gnome/jhbuild/modulesets). “gnome-world” moduleset represent generic set which will be updated for every release. So, I use “gnome-world” to make my environment as latest as possible.
  • modules – when we execute “jhbuild build” command, jhbuild will compile only the modules listed in this place. make sure you build what you want instead of building all the gnome projects (aka “meta-gnome-desktop”)
  • checkoutroot – place where jhbuild will clone the gnome repositories. set this to ~/Devel/gnome/checkout.
  • prefix – place where jhbuild will put the compiled binaries, set this to ~/Devel/gnome/runtime/usr. If you notice, you will see that ~/Devel/gnome/runtime is the same path where we installed archlinux base, so, we basically put the gnome binaries (libraries & executables) on top of archlinux, I’ll tell you why we are doing this when I explain arch-chroot.
  • os.environ[‘PYTHON’] – set this to /usr/bin/python2 because, Archlinux’s default python is python3 but most of gnome modules don’t like python3 (especially jhbuild. see here – https://wiki.archlinux.org/index.php/JHBuild#Python_issues).

Compiling

All set, its time to compile.

$ ~/Devel/gnome/runtime/usr/bin/jhbuild build

If jhbuild finds any missing libraries to compile the modules listed in jhbuildrc, it will throw error, here comes the need of arch-chroot.

Installing missing Dependencies

The reason we setup archlinux base in ~/Devel/gnome/runtime is to install any missing libraries here from arch packages using arch-chroot and packman and make sure we don’t distrub the current system. Let say, jhbuild throws that ‘spotread’ is missing when compiling colord module. ‘spotread’ executable is provided by ‘argyllcms’ package and here is the simple way to fix the dependency issue,

$ cd ~/Devel/gnome
$ su
# arch-chroot runtime /usr/bin/bash
# pacman --sync --refresh
# pacman --sync --sysupgrade
# pacman --sync argyllcms
# exit
# chown -R <username>:<groupname> runtime
# exit
$

Now, we can start compiling again, I suggest to switch to jhbuild environment before we compile, because jhbuild will setup necessary environment variables (like LD_LIBRARY_PATH pointing to ~/Devel/gnome/runtime/usr/lib etc.,) to make sure dependency libraries are resolved from ~/Devel/gnome/runtime/usr.

$ ~/Devel/gnome/runtime/usr/bin/jhbuild shell
$ jhbuild build
$ exit

Now, to execute the latest compiled gnome-builder,  here is the commandline

$ ~/Devel/gnome/runtime/usr/bin/jhbuild run gnome-builder

Thats it, you have your gnome development environment ready.

gistnotes – a gnome shell extension

Well, I should probably say, its basically a gnome application disguised as a shell extension. written entirely using javascript.

Nothing much to say more than what the README say here, https://github.com/mohan43u/gistnotes

gistnotes

This is my first contribution to gnome. you can install it through https://extensions.gnome.org/extension/917/gistnotes/. Check it out, and provide feedback.

Issue with Sabayon

Long time since I blogged. Life is crazy mate (specially after you become a husband). Personals aside, I have been waiting to blog about my experience with Sabayon.

I was a user of sabyon for about two and half years. But now, I’m a Arch user and thats one damn thing I did right to kickstart my hunger for coding again. Well, sorry sabayon developers, you guys suck!! because you dont worry about your users anymore.

Nothing wrong with the distro (I admire the stability it provided), but your attitude towards the users suck!! everytime we report a bug, you people either say raise this bug to upstream (or) raise this bug in gentoo’s bugzilla because they are the one who create the package.

If gentoo have a package and we ask it to enable it in sabayon overlay, you will say, we don’t enable some package because of one user and one can use gentoo’s overlay if they want. Dammit!! if I want to use gentoo’s overlay, why do I need to install sabayon?

Anyway, goodbye. I’m now in a true rolling distro.

GnomeContinuous using systemd-nspawn

OSTree:

One of interesting projects from Gnome Community which tries to define a new way of packaging. I really don’t know how exactly OSTree works, but it generates daily builds (qcow2 images) for Gnome. The OSTree repository which helps in building qcow2 images for Gnome is called “GnomeContinuous“. Similarly, there is another OSTree repository which builds qcow2 images for Fedora is called “rpm-ostree“(see ProjectAtomic)

Systemd-Nspawn:

Someone in the vast internet call this tool as “Poor Man’s Virtualization”. This is nothing but the good old chroot jail with modern walls (namespaces).

So, my experiment is to boot gnome-continus generated qcow2 image using systemd-nspawn to run a pure gnome OS parallelly. First thing is to download the gnome-continuous qcow2 image.

Note: all commands in this post executed under root

# wget http://build.gnome.org/continuous/buildmaster/images/z/current/gnome-continuous-x86_64-devel-debug-20140720.0.qcow2.gz
# gunzip gnome-continuous-x86_64-devel-debug-20140720.0.qcow2.gz
# ln -s gnome-continuous-x86_64-devel-debug-20140720.0.qcow2 gnome.qcow2

Network Block Device:

In order to open-up qcow2 images, qemu provides a tool called “qemu-nbd”. this tool requires ‘nbd’ kernel module to be loaded. So, load nbd driver as root,

# modprobe nbd
# qemu-nbd --connect /dev/nbd0 gnome.qcow2

Now, we have associated /dev/nbd0 with qcow2 image. This image contains three partitions(boot, swap and root), we have to seperate them into loop devices,

# parted /dev/nbd0 unit B print
Model: Unknown (unknown)
Disk /dev/nbd0: 8589934592B
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start       End          Size         Type     File system     Flags
 1      32768B      209747967B   209715200B   primary  ext4            boot
 2      209747968B  276856831B   67108864B    primary  linux-swap(v1)
 3      276856832B  8589934591B  8313077760B  primary  ext4

# losetup -o 276856832 -f /dev/nbd0
# losetup -o 32768 -f /dev/nbd0
# losetup -j /dev/nbd0
/dev/loop0: [0005]:849 (/dev/nbd0), offset 276856832
/dev/loop1: [0005]:849 (/dev/nbd0), offset 32768
#

Now we have to get the “ostree” boot parameter from /dev/loop1 (which is the boot partition in qcow2 image)

#mkdir boot
#mount /dev/loop1 boot
#grep 'ostree=' boot/syslinux/syslinux.cfg
APPEND root=LABEL=gnostree-root quiet splash ostree=/ostree/boot.0/gnome-continuous/f5a97103e9911b5a19ec154ecccfc6bd77f43e90e27a64adabf054e4db06c38b/0
#umount /dev/loop1
#rm boot

“ostree” boot parameter is importent for ostree tools to operate properly, so we have to append this boot parameter into our host machine’s /boot/grub/grub.cfg so that this boot parameter will be reflected in /proc/cmdline. Open your host machine’s /boot/grub/grub.cfg and append “ostree” parameter like this,

        linux   /kernel-genkernel-x86_64-3.14.0-sabayon init=/sbin/init root=UUID=80b5a49b-4156-49b3-ab4d-71d1de2dca36 resume=UUID=7550843f-1e8a-4c8e-b9a3-3c9907164726 ro rd.auto rd.lvm.vg=vg_mohanlaptop rd.vconsole.keymap=us quiet splash ostree=/ostree/boot.0/gnome-continuous/f5a97103e9911b5a19ec154ecccfc6bd77f43e90e27a64adabf054e4db06c38b/0
        initrd  /initramfs-dracut-x86_64-3.14.0-sabayon

Once done, reboot your host machine and re-setup /dev/loop0 and /dev/loop1 as we did in above steps.

We have to adjust root partition to stop plymouthd and modify default runlevel to “multi-user” instead of “graphical”,

# mkdir root
# mount /dev/loop1 root
# rm root/ostree/boot.0/gnome-continuous/f5a97103e9911b5a19ec154ecccfc6bd77f43e90e27a64adabf054e4db06c38b/0/etc/systemd/system/default.target
# ln -s root/ostree/boot.0/gnome-continuous/f5a97103e9911b5a19ec154ecccfc6bd77f43e90e27a64adabf054e4db06c38b/0/usr/lib/systemd/system/multi-user.target root/ostree/boot.0/gnome-continuous/f5a97103e9911b5a19ec154ecccfc6bd77f43e90e27a64adabf054e4db06c38b/0/etc/systemd/system/default.target
# mv root/ostree/boot.0/gnome-continuous/f5a97103e9911b5a19ec154ecccfc6bd77f43e90e27a64adabf054e4db06c38b/0/usr/bin/{plymouthd,plymouthd.disabled}
# umount /dev/loop1
# rm root

Now, time to setup the filesystems,

# mkdir root
# mount /dev/loop0 root
# mount --bind root/ root/ostree/boot.0/gnome-continuous/f5a97103e9911b5a19ec154ecccfc6bd77f43e90e27a64adabf054e4db06c38b/0/sysroot/
# mkdir /dev/exported
# ln /dev/loop1 /dev/exported/

Now we are ready to chroot,

# systemd-nspawn --bind /dev/exported -b -D root/ostree/boot.0/gnome-continuous/f5a97103e9911b5a19ec154ecccfc6bd77f43e90e27a64adabf054e4db06c38b/0

this will boot the qcow2 image which we downloaded and show a login prompt, get inside as root and mount the boot partition we exported from host machine which will be available inside /dev/exported/loop1,

GNOME-OSTree 0+snapshot-20140717 qemux86-64 console
qemux86-64 login: root
Last login: Sat Jul 19 22:38:48 SGT 2014 on console
root@qemux86-64:~# mount /dev/exported/loop1 /boot

Now, we can start the gnome session by running a X in host’s vt2 and point gnome-session inside chroot to connect to DISPLAY=:1

In Host Machine:

press ctrl-alt-f1 and login as root, then type this command
# X :1 vt2

Above step will start another X server in vt2 (you can switch between different X servers using ctrl-alt-f[1-9]).

Inside Systemd-Nspawn type,

root@qemux86-64:~# DISPLAY=:1 gnome-session

This will start gnome session in host machine’s vt2(ctrl-alt-f2) and show the latest gnome version built by OSTree which you downloaded as qcow2 image in the first step,

Screenshot from 2014-07-20 14:50:49

Also, you can verify which ostree version the current qcow2 image pointing to, open a gnome-terminal in the gnome-session started in vt2(ctrl-alt-f2) and type the below command,

root@qemux86-64:~# ostree admin status
* gnome-continuous 9b441d1f14c4caea17eb2b50a778da4a08e31cbbdf1104edf2cd2cb40a4e3374.0
    origin refspec: gnome-continuous:gnome-continuous/buildmaster/x86_64-devel-debug
root@qemux86-64:~# 

you can also update to the latest version of gnome using following command,

root@qemux86-64:~# ostree admin upgrade

To stop the gnome-session, go to the terminal where you started it and press ctrl-c. It will stop the gnome-session on vt2(ctrl-alt-f2) and give root prompt, now type following command to shutdown the systemd-nspawn machine

root@qemux86-64:~# systemctl poweroff

You will be back to host machine. Now, type following commands to peacefully disconnect everything,

# umount /dev/loop0
# umount /dev/loop0
# rm root
# rm -fr /dev/exported
# losetup -D
# qemu-nbd --disconnect /dev/nbd0

Thats it, the qcow2 image will be properly closed.

Well, if you don’t understand the steps in this post, commant here, I’ll try to explain as much as possible.

Creating My Own Website with Zero Cost

First of all, I’m not at all a web developer and had very little interest to learn web technology. All started changing during my marrage time, I wanted to create a wedding invitation website just to invite my friends.

My invitation website got good response in office. my colleagues asked about how I managed to create it because I belongs to c/c++ croud and very few in my team have broad knowledge about web technologies to create a website.

I came to know about node.js when I was digging with spidermonkey and gjs. So, for me, node.js becomes obvious choice as I already know little bit about javascript through spidermonkey and gjs.

A little research about node.js exposed me to express.js(web application framework), jade.js(HTML Template engine), stylus.js(CSS Engine) and jeet.js(Grid system)

I then created my wedding invitation site. Initially, I thought I have to spend money to host my wedding invitation site, but I came to know more about Heroku from one of the talk in Ilugc. Soon, my research about PaaS environments introduced me to OpenShift from RedHat. Openshift provides free hosting and OpenShift itself is OpenSource.

So, All I have to do is, create free account in OpenShift, Install rhc gem in my laptop, push my website into openshift through git. Thats all. My wedding invitation site is accessable anywhere and I was able to impress my friends,colleagues and finally my wife.

My wedding invitation app gave me overview of how current web development works, so I decided to have my personal website which consists of blog posts and my photos gallery. Instead of using blog framework available for node.js, I decided to use my existing wordpress blog for blog posts and my existing google drive account for storing photos so that I don’t need to use any database for my personal website.

I wrote two node.js modules wordpressrest.js and googlerest.js to access contents in wordpress and google dynamically.

Finally, I was able to come up with somewhat viewable personal website https://mohan43uweb-silentcrooks.rhcloud.com.

If you are viewing this Article through mohan43u.wordpress.com, checkout my personal website at https://mohan43uweb-silentcrooks.rhcloud.com and suggest me better ways to improve it.

SystemCtl Restart MyBlog

Its been 1yr 3months since I published my last post, lot of changes happened in my life. Just a quick look at my past

Marrage

I got married on 06-Dec-2013 to Deepa (A facebook addict who always wants to be in touch with her friends). Atlast, there is someone who will scold me when I don’t eat/sleep/bath properly. I got a nice traveller now to travell with me rest of my life. My stomach is not burning when I go to multiplexes and malls after marrage :)

Moved to Pune

Moved to beautiful Pune on Oct-2013. Nice city. But, I’m missing ilugc meetings very much. I have to start going to lug meeting in pune.

GStreamer

Learnt GStreamer basics and wrote a module for dhvani-tts which can use gstreamer for playing sound.

Node.js & Web

First started learning during my wedding to create a simple website just to show my invitation, now developed a personal website using node.js (more about this in next post).

Well, nice to be back to blogging after a long gap.