Search Here

Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Sunday, March 8, 2015

Notify to your user in Linux - GNotification

Hello Readers,

In the last post, I was referring to GNotification. Here is the dedicated post of my experiments with GNotification APIs with Perl.


Notification - A pop up message to show the quick details about what is going in the application. Usually in both linux and windows, The notifications are shown in lower right corner (system tray) of the desktop. In Linux GNOME desktop, its usually upper right corner.

Linux KDE desktop notification looks something like this,



Note: The notification appearance may vary based on the theme that you set in your desktop.

In Windows OS, Desktop notification looks something like this,



I was looking for a good way to notify from my perl application to user in Linux. In windows os, There is only one way to do. Call windows APIs yourself. But we are in free world, Linux, We have more than one way to do.

1. GNotification - Notification APIs provided by GNOME and tightly coupled for GTK applications but not hard to use in any applications even command line application. The main advantage of the GNotification APIs is its a persistence notification. Even after the system crash / reboot user will see the notification until they respond to it.

GNotification can also create notifications like questions that user can respond.

2. Libnotify - Notification APIs provided by GNOME. Very simple to use and its kind of standalone api set not tightened up with GTK. Simple and less powerfull.

We will use the GNotification API with Perl application with the help of our best foreign library interaction perl module - FFI::Platypus.
 
GNotification Way of Working is,

1. Create a new GTK application and gets its application ID

2. Register the application

3. Create Notifications

4. Set the Notification parameters

5. Show the Notifications to the user

6. Clean up everything.

Note: If you write a native GTK application, Step #1, #2 is not necessary because its implicit.

Ok. Enough talking, Here is the code.


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
#!perl
#Description: Create GNOME Desktop notifications using GNOME libgio library and FFI::Platypus
#Refer: https://developer.gnome.org/gio/2.42/gio-GNotification.html
#Author: Bakkiaraj Murugesan
use strict;
use warnings;
use FFI::Platypus;
use FFI::Platypus::Declare;
use FFI::CheckLib;
use Data::Dumper;

$|++;
my $ffiObj = "";

print "\n Perl FFI::Platypus Gnome Notification Example";
#Find the lib
my $libPath =  find_lib( lib => '*', verify => sub { $_[0] =~ /^gio-2\.[0-9]+/ },libpath=>'/usr/lib64' );
my $gobjectLibPath = find_lib(lib=>'*',verify => sub { $_[0] =~ /^gobject-2\.[0-9]+/ },libpath=>'/usr/lib64');
my $glibLibPath = find_lib(lib=>'*',verify =>sub { $_[0] =~m/^glib-2\.\d+/;},libpath=>'/usr/lib64');

#Find the library Paths
print "\n Found libgio-2.0 in :", $libPath;
print "\n Found libgobject-2.0 in :", $gobjectLibPath;
print "\n Found libglib-2.0 in :", $glibLibPath;

#Create FFI::Platypus object
$ffiObj = FFI::Platypus->new();
$ffiObj->lang('C'); #FFI supports more than C language
$ffiObj->lib($libPath);

my $ffiObj1 = FFI::Platypus->new();
$ffiObj1->lang('C'); #FFI supports more than C language
$ffiObj1->lib($gobjectLibPath);

my $ffiObj2 = FFI::Platypus->new();
$ffiObj2->lang('C'); #FFI supports more than C language
$ffiObj2->lib($glibLibPath);

#Create gapplication
#g_application_new (const gchar *application_id,GApplicationFlags flags);
$ffiObj->attach('g_application_new',['string','int'],'opaque');

#Check application ID is valid 
$ffiObj->attach('g_application_id_is_valid',['string'],'int');
#Set GApplication Name
my $appName = 'perl.ffi.platypus.gnome.notify.example';
print "\n App Name $appName is valid? ",g_application_id_is_valid($appName); 
#G_APPLICATION_FLAGS_NONE is 0
my $GApplicationPrt = g_application_new ($appName,0);

#Register the application
#gboolean g_application_register (GApplication *application, GCancellable *cancellable, GError **error);
$ffiObj->attach('g_application_register',['opaque','opaque','opaque'],'int');
#GCancellable *g_cancellable_new (void);
#$ffiObj->attach('g_cancellable_new',['void'],'void');
#my $GCancellablePtr = g_cancellable_new();
print "\n Application Registration ID:", g_application_register($GApplicationPrt,undef,undef);

print "\n Send Welcome notification";
#Create GNotification                        
#GNotification *g_notification_new (const gchar *title);
$ffiObj->attach('g_notification_new',['string'],'opaque');
my $GNotificationPtr = g_notification_new('Welcome');

#void g_notification_set_body (GNotification *notification, const gchar *body);
$ffiObj->attach('g_notification_set_body',['opaque','string'],'void');

g_notification_set_body ($GNotificationPtr, "Welcome to GNotifications using perl + FFI::Platypus...");

#void g_application_send_notification (GApplication *application, const gchar *id, GNotification *notification);
$ffiObj->attach('g_application_send_notification',['opaque','string','opaque'],'void');
g_application_send_notification($GApplicationPrt,'perl.ffi.platypus.gnome.notify.welcome',$GNotificationPtr);

print "\n Send Urgent notification";
#void g_notification_set_urgent (GNotification *notification, gboolean urgent);
$ffiObj->attach('g_notification_set_priority',['opaque','int'],'void');
$GNotificationPtr = g_notification_new('Urgent');
g_notification_set_body ($GNotificationPtr, "This is Urgent Notification. Have a look at me!");
g_notification_set_priority($GNotificationPtr,2);
g_application_send_notification($GApplicationPrt,'perl.ffi.platypus.gnome.notify.urgent',$GNotificationPtr);

print "\n Notification with Buttons";
$GNotificationPtr = g_notification_new('Wanna Coffee?');
g_notification_set_body ($GNotificationPtr, "Would you like to drink Coffee?");

                 
#void g_notification_add_button (GNotification *notification,const gchar *label,const gchar *detailed_action);
$ffiObj->attach('g_notification_add_button',['opaque','string','string'],'void');
g_notification_add_button ($GNotificationPtr, "Ok. Sure", "app.ok");


g_application_send_notification($GApplicationPrt,'perl.ffi.platypus.gnome.notify.coffee',$GNotificationPtr);
                        
print "\n Clean Up everything";
#Do clean up
#void g_object_unref (gpointer object);
$ffiObj1->attach('g_object_unref',['opaque'],'void');
g_object_unref ($GNotificationPtr);
g_object_unref ($GApplicationPrt);

print "\n Ta Ta from PID:", $$;
print "\n Note: GNotification is persitant, Even after this application quit, System reboots, Notification will be there until user acknowledge it.";
#All is Well Bye
exit 0;


Here is the stdout looks like,


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 Perl FFI::Platypus Gnome Notification Example
 Found libgio-2.0 in :/usr/lib64/libgio-2.0.so.0.4200.2
 Found libgobject-2.0 in :/usr/lib64/libgobject-2.0.so.0.4200.2
 Found libglib-2.0 in :/usr/lib64/libglib-2.0.so.0.4200.2
 App Name perl.ffi.platypus.gnome.notify.example is valid? 1
 Application Registration ID:1
 Send Welcome notification
 Send Urgent notification
 Notification with Buttons
 Clean Up everything
 Ta Ta from PID:3768
 Note: GNotification is persitant, Even after this application quit, System reboots, Notification will be there until user acknowledge it.

Here is the screen shot of the notifications generated by the above code,


Conclusion. Notify your user with as much as meaningful information. Do not make them to think that your application is not responding and doing something crap !!.

Bye.



Sunday, March 1, 2015

Running Win32 specific perl code in Linux

Hello Readers,

My wife and my son decided to give me a short "me" time. They are out of town for this whole month. I have planned to watch lots of movies and do some more experiments with perl + FFI.

As usual, I will update the experiment results here. Stay tuned.

WINE - Wine is an open source project. It aims to provide a Windows compatibility layer in Linux. So we can run the windows applications with in linux without going through Virtualization or any other tough route.

I must admit that I never really had any success of running useful windows application in my Fedora Linux via WINE. It appears that WINE can properly emulate core APIs but not fully the .NET kind of APIs, Also many guys out there using WINE for running Windows games in Linux Box. Games usually use the raw and core APIs of the OS.

I have a server grade computer with dual boot. One OS is obviously Fedora Linux 21 and other is Windows 7. I hate to login to Windows and my default login is set to Fedora Linux. Most of the time, I will finish my work in Linux OS itself and @Work I force to use Windows 7  laptop anyway. So I will defer my windows releated tasks to @Work laptop.

This week end, I was doing some experiments with perl and I had a situation to Win32 module. I can not do it Linux anyway because Win32 module, As name suggest needs windows OS to run. Win32 module exports a set of Windows OS APIs in to perl world.

In my other dual boot windows os, I have Active State perl v5.21 with all the perl development modules installed. But I don't like to shutdown and boot into Windows OS because of many days I did not login, It will complain about missing patches and older Virus Scanner. (Virus scanner!! another piece of crap, It will slow down the computer like anything and in Linux, We ask what is Virus? :))

Hmm... I have one more choice. In the Linux OS, I have KVM based windows XP virtual machine. I thought to start the Windows XP virtual machine and continue my perl experiments. After I logged into Windows XP virtual machine, I realize that, I do not have my perl development environment setup in it.

Like some people can not sleep in any beds and need their own bed and pillow, I need my development setup else my brain won't let me work. It keep points advantage of my development environment.

By the way, My perl development environment is,

Windows OS: Active Perl 5.20 +Eclipse IDE + EPIC Plugin + PPM for package management + gcc compiler + dmake

Linux OS: System default perl+ Eclipse IDE + EPIC plugin + CPAN for package management + gcc compiler + gmake

So, Windows XP Virtual Machine also not useful for now. I am too lazy to re setup my development environment in the Windows XP Virtual Machine.

Since I have the Dual Boot, I have also mounted my Windows drives (C:, E:) into my Linux via following entries in /etc/fstab file.


1
2
/dev/sda3 /mnt/WinD ntfs-3g rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other 0 0
/dev/sda2 /mnt/WinC ntfs-3g rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other 0 0

This allows me to access all Windows OS installed applications in /mnt/WinC. I finally thought to give a try with WINE.

Mission: Run Active Perl 5.20 which is installed in Windows OS in Linux using WINE.

First we need a WINE installed, I have installed long long back (May be since 2003, I have WINE in the Linux system without much usage because I am not a good computer games fan).


1
2
wine --version
wine-1.7.36 (Staging)

Next need to access the Active Perl installation in Windows OS. Using /etc/fstab file, Windows hard disk partition (NTFS) also mounted in Linux under /mnt folder.

Finally run the Active State perl,


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ cd /mnt/WinC/Perl/bin/
$ wine perl -v
fixme:winediag:start_process Wine Staging is a testing version containing experimental patches.
fixme:winediag:start_process Please report bugs at http://bugs.wine-staging.com (instead of winehq.org).
fixme:ole:CoInitializeSecurity ((nil),-1,(nil),(nil),1,2,(nil),0,(nil)) - stub!
err:ole:CoGetClassObject class {0000034b-0000-0000-c000-000000000046} not registered
err:ole:CoGetClassObject no class object {0000034b-0000-0000-c000-000000000046} could be created for context 0x1
fixme:ole:RemUnknown_QueryInterface No interface for iid {00000019-0000-0000-c000-000000000046}

This is perl 5, version 20, subversion 1 (v5.20.1) built for MSWin32-x86-multi-thread-64int
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2014, Larry Wall

Binary build 2000 [298557] provided by ActiveState http://www.ActiveState.com
Built Oct 15 2014 22:10:49

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
$ fixme:crypt:ProvStore_release Unimplemented flags 1
fixme:crypt:MemStore_release Unimplemented flags 1
fixme:msvcrt:__clean_type_info_names_internal (0x36e3f8) stub
fixme:msvcrt:__clean_type_info_names_internal (0x10046a20) stub


Hurrah, perl runs smoothly. But WINE spits more debug messages, Its quite distractive. Put off the WINE debug messages with WINEDEBUG environment variable.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$ export WINEDEBUG=-all
$ wine perl -v

This is perl 5, version 20, subversion 1 (v5.20.1) built for MSWin32-x86-multi-thread-64int
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2014, Larry Wall

Binary build 2000 [298557] provided by ActiveState http://www.ActiveState.com
Built Oct 15 2014 22:10:49

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

Sweet :) Now, Perl runs as if I am running in Windows. But my main motive is to use the Win32 module, I still need to see WINE + Windows Perl can load the Win32 module.

Before that, I need to setup few environment variables for Windows Perl. Though WINE passes all the environment variables to running application due to OS difference few environment variables like PATH can not passed from Linux to Windows process running in WINE.

Special WINE environement variables needs to be exported via WINE Registry editor. It can be invoked via 'regedit' command OR if you are using KDE / GNOME desktop, You can get it in the start menu.



You can see that I have set the PATH variables with perl specific values. Z: is created by WINE, It is the Linux "/" folder.

Lets run Win32 code,


1
2
3
$ wine perl -e 'use Win32; print Win32::GetOSDisplayName()'

Windows XP Professional Service Pack 3


Awesome. Looks like WINE is emulating Windows XP.

This made me think, why perl can run peroperly under WINE?. Other commercial applications like Adobe Photoshop fails to run under WINE.

This is because Perl is super portable and it is mostly using libC (C runtime) core APIs (and modules will use other APIs, Depends on the Module) and perl as a language do not have may dynamic libs to link with. Basically, Perl is a low dependency language unlike MS Languages (.NETs).

No wonder perl is running in Over 100+ OS !!!!

After a decade, I made use of WINE and I will continue to use with Windows specific perl expriments.

Just now, Got a call from wife and son, Accusing me that, Even they are not in home, I finish blog in late sunday night and its obvious that they are not responsible for me to work in late nights!! True.



Hey, I am also doing experiments with GNotification APIs. Let me update in upcoming blog posts.


Bye Bye folks.

Monday, December 1, 2014

Linux Tip: How to run GUI application as a other user

Its easy to run a command as other user in Linux.


sudo -u bakki id

uid=1000(bakki) gid=1000(bakki) groups=1000(bakki),10(wheel),18(dialout)




But when you try to run a GUI application as other user, its not as simple as commandline.


sudo -u bakki kwrite
No protocol specified
kwrite: cannot connect to X server :0

The above command does not work because user 'bakki' do not have necessary permission to work with X server running on other user.

Here is a difference, When compare to Windows OS, In Linux OS, X Server, which is responsible to draw in video hardware runs as a client in a given user with given permissions.

All the GUI applications sends the drawing request to the X server via X protocols. So if the X Server running user do not provide permission, No other user application can contact the X Server for display. This is the reason GUI applications fails to run as a other user using simple command line.

Solution: Provide X Server permission to users and run the command.


CMD="kwrite";
USER=bakki;xhost +SI:localuser:$USER; sudo -u $USER -H -b $CMD >/dev/null 2>&1 

It is particularly useful to run vlc media player under root account in linux. vlc will not run as a root but for some reason, if you need to run the vlc under root desktop login in linux, you can use following way,


CMD="vlc";USER=bakki;xhost +SI:localuser:$USER; sudo -u $USER -H -b $CMD >/dev/null 2>&1  
 
 
If you do not like to use the inbuilt commands, You can always use KDE / GNOME provided utilities to run Linux GUI applications as a other user. Its simple as well,

KDE:

kdesu -u bakki firefox 

Sunday, November 30, 2014

Blog development environment setup - A hello world post

Seriously, Yes. As a developer, I have been trained to,

1. Set up environment

2. Learn new things with "hello world"

I naturally followed the same above steps for this blog. I thought, I need a good desktop environment for blog development, so I spent close to 3 hours to find the right environment. My conclusion is,

Nothing !! No environment required.

I started with "Blogilo", KDE Desktop based blog client for Linux. It allows me to configure various blogger host services like blogger.com, wordpress.com etc..  allows to create content offline and upload it.

I thought, Its my IDE for blogs and literally started this blog in it with screen shots. When I submitted the blog, it was submitting ....  submitting... submitting ... I finished coffee and my mind strated working again. Hey! Why are you taking so long time?

I closed the Blogilo app its crashed and the post was not submitted to blogger.com. WTF?

I tried to debug, Found that, when you insert an image (in my case, screenshots), Blogilo app inserts following html code,

<html><head></head><body><img src="file:///tmp/And2.png"></body></html>


Looks normal, But when you look st the image source, it is pointing to local machine. So the Blogilo need to upload the image first and the upload my post But blogger.com API or Blogspot.com API doesn't support uploading media.



This explains the crash problem with Blogilo.  

I found a trick to overcome this problem. Open the Libreoffice Writter (equivalent to  MS Office Word) and copy paste the image / insert the image then copy the image (Ctrl+C) and paste in Blogilo in this case Blogilo adds the image with base64 encoded binary data, Not as a link to local machine.

But base64 bloats up the size and its a very cumbersome way of doing anything.

Ok, Its open source world, If not Blogilo, there should be something else.

Unfortunately, under linux, I did not find another good blog editing desktop client. I found one called ScribeFire, which is a firefox extension and runs under firefox. I installed it,

But, If I can open the firefox, I can browse to www.blogger.com and use its awesome online WYSWYG editor. Hey , its an experiment, dont put more thoughts..

ScribeFire also suffers the same problem of Blogilo. But
ScribeFire is little intelligent, when I try to insert an image, It tried to upload the image to Google Picasa and tried to insert a link than img src from local machine but this operation fails.
 

Hmm... What could be wrong, Why Blogilo is behaving this way. Why dont I find a good open source desktop blogger tool?

After some more readings and understanding, I found that the limitation comes from the blog hosting services. Unless they export the APIs, its impossible to develop the clients.

Looks like Wordpress supports most of the APIs so Blogilo would be more suitable to Wordpress.

I thought a moment to migrate the blog to Wordpress but decided to keep my blog in blogger because of the admin simplicity and its powerful web statistics.

Conclusion is that I am going to use blogger.com's web interface to add the blog posts and officially I have learned "Hello World" in www.blogger.com.


                                          "Hello World"
                                          "Hello Blogger"