Saturday, July 17, 2010

GUI in Bash using GTK-server

Gtk-server allows to create GUI providing access to GTK+ library functions in interpreted programming and scripting languages such as bash (it  can also be used for many libraries other than GTK).To use gtk-server in bash , it has to be started asynchronously,upon starting it reads the configuration file (more on this later) and then GTK functions can be executed by sending it as plain text to gtk-server.Each time you send some text to gtk-server it sends reply in form of strings back.These functions can be send and replies obtained by various ways.

Gtk-server comes bundled with examples for using bash via fifo(named pipes),tcp and ipc to communicate with gtk-server.However, bash 4 supports coprocesses which allows execution of a command in the background with two file descriptors connected to standard output and standard input of the command.The coprocess can be created by using coproc builtin(see man bash or type help coproc at bash prompt for more information).We will be using coprocess for communication with gtk-server.(It is possible to create something similar to coprocess using named pipes and exec in earlier bash versions,but since gtk-server allows a  -fifo=fifo-name internal argument for creation of named pipes, its not worth the effort)

First off , we need a function to communicate with gtk-server and for that we need to write a function that will do exactly that.Here is a basic function that we can use to communicate with gtk-server.

#!/bin/bash

gtk()
{ 
printf '%s\n' "$*" >&"${COPROC[1]}" 
read -ru "$COPROC" 
}

Now we can go on to start gtk-server

coproc gtk-server -stdin

This starts gtk-server asynchronously and gives us two file descriptors to communicate with gtk-server stored in COPROC array which we used in the gtk function above and also a variable COPROC_PID which contains the pid of gtk-server.

With gtk-server started and communication function defined all we have to do is send gtk functions to gtk-server.But thats not all, you would need to define these functions in gtk-server's configuration file.For now we will not define any functions and use the standard configuration file that comes with gtk-server assuming that you have the configuration file in the same directory as your script or in one of the standard locations(read the manual for more on standard location of configuration file :) ).

First we need to initialize the gtk library.In C, you would do this in main as follows:
gtk_init( &argc, &argv );
The function would initialize gtk and parse some command line arguments.Using our gtk function, we will initialize the library as
gtk gtk_init NULL NULL 

Notice that we did not pass command line arguments to gtk_init(More on this later).We would not use the REPLY read by gtk function because gtk_init does not return any value.If you do an `echo "$REPLY"` just after this line in your script, it will echo ok.Gtk-server sends back "ok" for functions which do not return anything and -1 for any function which was send to it but was not described in the configuration file.

Now, lets create our main window,we will use gtk_window_new function
gtk gtk_window_new GTK_WINDOW_TOPLEVEL
window=$REPLY 

This time we stored the reply from gtk-server into variable window.gtk_window_new returns a pointer to the newly created window.Gtk-servr in turn replies back with a Widget Id to refer to the newly created window to our client script.We store the reply from gtk-server and use the value as Widget Id every time we want to refernce to the top level window.

Next we create a button with label hello on it.
gtk gtk_button_new_with_label hello 
button=$REPLY

Its time to add the button to the container window.In gtk,you add widgets to containers.The window can be used as a container and you can add buttons to it.But generally you would add a vbox or hbox or a table to the window and pack other widgets inside it.

gtk gtk_container_add "$window" "$button" 

Now that we have our button added to the window, we are ready to show it all,we shall use gtk_widget_show_all for this but you can use gtk_widget_show for each widget too.

gtk gtk_widget_show_all "$window" 

Having everything ready, all we need to do is create a main loop:
until [[ $event = $window ]];do
  gtk gtk_server_callback wait
  event=$REPLY
done

gtk gtk_server_exit
wait "$COPROC_PID"

In the standard configuration file, gtk_window_new is defined with callback signal delete-event.So if you click on the main window close button provided by the window manager, signal
is emitted.gtk_server_callback is an internal function provided by gtk-server fetches signals .The argument wait tells it to return only when a signal has occured.By default Widget ID is returned by gtk_server_callback on a signal.So unless widget ID of the main window which we stored in variable window, is returned we continue with the loop(gtk_server_callback also updates Gtk widgets).

Once the loop ends gtk_server_exit tells gtk-server to cleanup and exit.Finally we use wait builtin to wait for gtk-server to complete.This also returns the exit status of gtk-server.

Here is all of it put together.Please note that the example has been simplified and a lot of error checking has been omitted for the purpose of illustration.However this should get you started.You would notice that the window does not look very good, you need some more GTK functions to make it look decent(Check the GTK API documnetation at gtk.org link provided at the end)

gtk()
{ 
printf '%s\n' "$*" >&"${COPROC[1]}" 
read -ru "$COPROC" 
}
 
coproc gtk-server -stdin

gtk gtk_init NULL NULL 

gtk gtk_window_new GTK_WINDOW_TOPLEVEL
window=$REPLY 

gtk gtk_button_new_with_label hello 
button=$REPLY

gtk gtk_container_add "$window" "$button" 
gtk gtk_widget_show_all "$window" 

until [[ $event = $window ]];do
  gtk gtk_server_callback wait
  event=$REPLY
done

gtk gtk_server_exit
wait "$COPROC_PID"

The configuration file not only allows you to tell gtk-server about a gtk function but also define some constants and enumerations, include another configuration file and define macros.The macros make gtk-server highly programmable(you can write a simple stand alone program in it).I will take a closer look on gtk-server configuration file and macros in my future posts.

To Be Continued...

External Links:

Tuesday, April 27, 2010

making sense of "the common sense"

So i had a clumsy moment , and then i hear some loud voice punching on my ear drums--"Where is your COMMON SENSE?"


"I do have common sense but probably thats not your definition of the terminology" , i yelled back.

( Yelling is like reflex action , when some one yells at you , you yell back.In this way it is similar to yawning, the consequences of yelling are most of the time worse than result of yawning though )

So we all have common sense.However, the "common" in it is quite misleading.There isn't a specific and "common" to all set of "senses" defined in "The Common Sense Bible" that people should possess in order to have common sense.Common sense is rather a set of "senses" that is  "unique" to an individual( this set overlaps or intersects to certain extent with other individual sets and one can argue that it is not unique at all ).And using this "set of senses" in our "common" or day to day life we find it so natural that we consider it as "common sense".People have common sense that seems natural and common to them and it is not the same as the common sense I  have, We all have common sense but it is not common to all of us.

Common sense is not something we are born with hard coded in our genes, it is acquired. Doing simple task as buttoning a shirt or balancing on single or both feet(walking i mean) may seem trivial today, but we had to learn it once upon a time

Brain is the best organ of all in Human body, the reason why there is war and why we do everything we do, good or bad (In fact "good" and "bad" are the creation of the brain too).It is interesting but complicated and the power and complexities of the organ "brain" continues to amaze many great "brains" even today.  It is our brain that learns each and every thing we do consciously or unconsciously with every repetition storing it in memory so that walking or cycling which once seems so difficult, becomes effortless ( not completely, you still need your voluntary will and muscle power ).It is amazing how the brain deals with the physics without you thinking about it, making you lean and move in direction that help you keep your balance.It creates an abstraction layer between things stored in the memory and our conscious movements.

Brain makes mistakes too, and while cycling you may fall, but again brain learns from this mistake and stores it in the memory.It is unlikely but possible that you may fall making the same mistake( probably the saying "Man makes mistakes but fools repeats them" was an indication towards the fact all brain except foolish ones learn from their mistakes).It is that people do not accept the fact that the best way of learning is by commiting mistakes because if they did the education system wouldn't treat failure as bad but as a step forward in the learning process.

We all have led a different life and had our own journey of learning by practicing and commiting mistakes since our birth to where ever we stand now in the road of life.So we have all acquired a specific set of sense, actually the learned memory of our brain which we apply every day in our lives.This is common sense and only things i find common here is that we all acquire it through a process of learning and that we all seem to find it natural once we acquire it. A person who spent his school days solving math problems may find a certain way of solving those problems as common sense while others may not.Similarly a person who never actually looked at those idiotic fashion magazines or paid attention to how people dress in TV or real life may lack fashion sense according to some others(fashion sense is a subset of common sense that some of us acquire as we grow up and so is civic sense and many others). So what may seem common sense to you , may not seem the same to me and saying  "you DONT HAVE COMMON SENSE" reflects nothing but the fact that you dont really understand common sense or you dont define it as i do or the fact that i misunderstood what common sense is (take your pick, i dont want to know which option you chose)

If you read the entire of this ****  and if it makes no sense to you , dont worry, even our way of understanding and looking at things is acquired and therefore not common (that tells you something about my  life , doesn't it? )

Friday, March 19, 2010

Reflections

I have had quite a few blogs on various subjectsand almost all were poorly updated  and maintained. A busy life ( yes , my life sucks )  makes it almost impossible to maintain so many blogs. I have been thinking of uniting all these blogs into one blog for quite some time. Its far easier to write one blog for someone with as less time (read: lazy) as me. But being lazy as i am ( its congenital , i cant help) i never really made such a blog until now.
Finally , here is the blog called "Reflections" , a united blog which i promise myself to update regularly. However , as you know , i am lazy...